Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create editExerciseComment mutation and update some snapshots for tests #2731

Merged
merged 19 commits into from
Feb 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 162 additions & 51 deletions graphql/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export type Mutation = {
deleteExercise: Exercise
deleteModule: Module
editComment?: Maybe<Comment>
editExerciseComment: ExerciseComment
flagExercise?: Maybe<Exercise>
login?: Maybe<AuthResponse>
logout?: Maybe<AuthResponse>
Expand Down Expand Up @@ -278,6 +279,11 @@ export type MutationEditCommentArgs = {
id: Scalars['Int']
}

export type MutationEditExerciseCommentArgs = {
content: Scalars['String']
id: Scalars['Int']
}

export type MutationFlagExerciseArgs = {
flagReason: Scalars['String']
id: Scalars['Int']
Expand Down Expand Up @@ -504,6 +510,57 @@ export type UserLesson = {
userId?: Maybe<Scalars['String']>
}

export type LessonAndChallengeInfoFragment = {
__typename?: 'Lesson'
id: number
docUrl?: string | null
githubUrl?: string | null
videoUrl?: string | null
chatUrl?: string | null
order: number
description: string
title: string
challenges: Array<{
__typename?: 'Challenge'
id: number
description: string
lessonId: number
title: string
order: number
}>
}

export type SubmissionsInfoFragment = {
__typename?: 'Submission'
id: number
status: SubmissionStatus
diff?: string | null
comment?: string | null
challengeId: number
lessonId: number
createdAt?: string | null
updatedAt: string
challenge: { __typename?: 'Challenge'; title: string; description: string }
user: { __typename?: 'User'; id: number; username: string }
reviewer?: {
__typename?: 'User'
id: number
username: string
name: string
} | null
comments?: Array<{
__typename?: 'Comment'
id: number
content: string
submissionId: number
createdAt: string
authorId: number
line?: number | null
fileName?: string | null
author?: { __typename?: 'User'; username: string; name: string } | null
}> | null
}

export type AcceptSubmissionMutationVariables = Exact<{
submissionId: Scalars['Int']
comment: Scalars['String']
Expand Down Expand Up @@ -805,57 +862,6 @@ export type FlagExerciseMutation = {
flagExercise?: { __typename?: 'Exercise'; id: number } | null
}

export type LessonAndChallengeInfoFragment = {
__typename?: 'Lesson'
id: number
docUrl?: string | null
githubUrl?: string | null
videoUrl?: string | null
chatUrl?: string | null
order: number
description: string
title: string
challenges: Array<{
__typename?: 'Challenge'
id: number
description: string
lessonId: number
title: string
order: number
}>
}

export type SubmissionsInfoFragment = {
__typename?: 'Submission'
id: number
status: SubmissionStatus
diff?: string | null
comment?: string | null
challengeId: number
lessonId: number
createdAt?: string | null
updatedAt: string
challenge: { __typename?: 'Challenge'; title: string; description: string }
user: { __typename?: 'User'; id: number; username: string }
reviewer?: {
__typename?: 'User'
id: number
username: string
name: string
} | null
comments?: Array<{
__typename?: 'Comment'
id: number
content: string
submissionId: number
createdAt: string
authorId: number
line?: number | null
fileName?: string | null
author?: { __typename?: 'User'; username: string; name: string } | null
}> | null
}

export type GetAppQueryVariables = Exact<{ [key: string]: never }>

export type GetAppQuery = {
Expand Down Expand Up @@ -1543,6 +1549,20 @@ export type UserInfoQuery = {
} | null
}

export type EditExerciseCommentMutationVariables = Exact<{
id: Scalars['Int']
content: Scalars['String']
}>

export type EditExerciseCommentMutation = {
__typename?: 'Mutation'
editExerciseComment: {
__typename?: 'ExerciseComment'
id: number
content: string
}
}

export type WithIndex<TObject> = TObject & Record<string, any>
export type ResolversObject<TObject> = WithIndex<TObject>

Expand Down Expand Up @@ -1991,6 +2011,12 @@ export type MutationResolvers<
ContextType,
RequireFields<MutationEditCommentArgs, 'content' | 'id'>
>
editExerciseComment?: Resolver<
ResolversTypes['ExerciseComment'],
ParentType,
ContextType,
RequireFields<MutationEditExerciseCommentArgs, 'content' | 'id'>
>
flagExercise?: Resolver<
Maybe<ResolversTypes['Exercise']>,
ParentType,
Expand Down Expand Up @@ -6691,6 +6717,89 @@ export type UserInfoQueryResult = Apollo.QueryResult<
UserInfoQuery,
UserInfoQueryVariables
>
export const EditExerciseCommentDocument = gql`
mutation editExerciseComment($id: Int!, $content: String!) {
editExerciseComment(id: $id, content: $content) {
id
content
}
}
`
export type EditExerciseCommentMutationFn = Apollo.MutationFunction<
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables
>
export type EditExerciseCommentProps<
TChildProps = {},
TDataName extends string = 'mutate'
> = {
[key in TDataName]: Apollo.MutationFunction<
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables
>
} & TChildProps
export function withEditExerciseComment<
TProps,
TChildProps = {},
TDataName extends string = 'mutate'
>(
operationOptions?: ApolloReactHoc.OperationOption<
TProps,
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables,
EditExerciseCommentProps<TChildProps, TDataName>
>
) {
return ApolloReactHoc.withMutation<
TProps,
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables,
EditExerciseCommentProps<TChildProps, TDataName>
>(EditExerciseCommentDocument, {
alias: 'editExerciseComment',
...operationOptions
})
}

/**
* __useEditExerciseCommentMutation__
*
* To run a mutation, you first call `useEditExerciseCommentMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useEditExerciseCommentMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [editExerciseCommentMutation, { data, loading, error }] = useEditExerciseCommentMutation({
* variables: {
* id: // value for 'id'
* content: // value for 'content'
* },
* });
*/
export function useEditExerciseCommentMutation(
baseOptions?: Apollo.MutationHookOptions<
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables
>
) {
const options = { ...defaultOptions, ...baseOptions }
return Apollo.useMutation<
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables
>(EditExerciseCommentDocument, options)
}
export type EditExerciseCommentMutationHookResult = ReturnType<
typeof useEditExerciseCommentMutation
>
export type EditExerciseCommentMutationResult =
Apollo.MutationResult<EditExerciseCommentMutation>
export type EditExerciseCommentMutationOptions = Apollo.BaseMutationOptions<
EditExerciseCommentMutation,
EditExerciseCommentMutationVariables
>
export type AlertKeySpecifier = (
| 'id'
| 'text'
Expand Down Expand Up @@ -6897,6 +7006,7 @@ export type MutationKeySpecifier = (
| 'deleteExercise'
| 'deleteModule'
| 'editComment'
| 'editExerciseComment'
| 'flagExercise'
| 'login'
| 'logout'
Expand Down Expand Up @@ -6933,6 +7043,7 @@ export type MutationFieldPolicy = {
deleteExercise?: FieldPolicy<any> | FieldReadFunction<any>
deleteModule?: FieldPolicy<any> | FieldReadFunction<any>
editComment?: FieldPolicy<any> | FieldReadFunction<any>
editExerciseComment?: FieldPolicy<any> | FieldReadFunction<any>
flagExercise?: FieldPolicy<any> | FieldReadFunction<any>
login?: FieldPolicy<any> | FieldReadFunction<any>
logout?: FieldPolicy<any> | FieldReadFunction<any>
Expand Down
11 changes: 11 additions & 0 deletions graphql/queries/editExerciseComment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { gql } from '@apollo/client'

const EDIT_EXERCISE_COMMENT = gql`
mutation editExerciseComment($id: Int!, $content: String!) {
editExerciseComment(id: $id, content: $content) {
id
content
}
}
`
export default EDIT_EXERCISE_COMMENT
4 changes: 3 additions & 1 deletion graphql/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ import {
import {
getExerciseComments,
addExerciseComment,
getChildComments
getChildComments,
editExerciseComment
} from './resolvers/exerciseCommentCrud'
import { updateUserNames, updateUserPassword } from './resolvers/userDataCrud'

Expand Down Expand Up @@ -103,6 +104,7 @@ export default {
removeExercise,
unlinkDiscord,
addExerciseComment,
editExerciseComment,
updateUserNames,
updateUserPassword
}
Expand Down
65 changes: 64 additions & 1 deletion graphql/resolvers/exerciseCommentCrud.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import prismaMock from '../../__tests__/utils/prismaMock'
import {
addExerciseComment,
getExerciseComments,
getChildComments
getChildComments,
editExerciseComment
} from './exerciseCommentCrud'

describe('addExerciseComment resolver tests', () => {
Expand Down Expand Up @@ -126,3 +127,65 @@ describe('getChildComments resolver tests', () => {
})
})
})

describe('editExerciseComment resolver tests', () => {
test('Should throw error if user is invalid or not loggedin', async () => {
const mockContext = { req: { user: null } }
const mockArgs = {
id: 1,
content: 'no user'
}

await expect(
editExerciseComment(undefined, mockArgs, mockContext)
).rejects.toEqual(new Error('No user'))
})

test('Should throw error if authorID does not match original post', async () => {
const mockContext = { req: { user: { id: 1 } } }
const mockArgs = { id: 2, content: 'no user match' }
const mockExerciseComment = {
id: 2,
exerciseId: 1,
authorId: 2,
parentId: 1,
content: 'there is user',
userPic: null
}

prismaMock.exerciseComment.findUnique.mockResolvedValue(mockExerciseComment)
await expect(
editExerciseComment(undefined, mockArgs, mockContext)
).rejects.toEqual(new Error('Comment is not by user'))

expect(prismaMock.exerciseComment.findUnique).toBeCalledWith({
where: {
id: 2
}
})
})

test('Should edit existing comment with matching id in prisma', async () => {
const mockContext = { req: { user: { id: 1 } } }
const mockArgs = { id: 2, content: 'new content' }
const mockExerciseComment = {
id: 2,
exerciseId: 1,
authorId: 1,
content: 'old content',
userPic: null
}

prismaMock.exerciseComment.findUnique.mockResolvedValue(mockExerciseComment)
prismaMock.exerciseComment.update.mockResolvedValue(mockExerciseComment)

await expect(
editExerciseComment(undefined, mockArgs, mockContext)
).resolves.toEqual(mockExerciseComment)

expect(prismaMock.exerciseComment.update).toBeCalledWith({
where: { id: mockArgs.id },
data: { content: mockArgs.content }
})
})
})
Loading