mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2026-04-06 01:25:38 +00:00
fix(backend): fix backend tests & increase coverage (#9514)
This commit is contained in:
parent
700aaaf0b2
commit
306f21cc20
@ -27,7 +27,7 @@ export default {
|
||||
],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
lines: 93,
|
||||
lines: 94,
|
||||
},
|
||||
},
|
||||
testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'],
|
||||
|
||||
@ -7,6 +7,8 @@ mutation ChangeGroupMemberRole($groupId: ID!, $userId: ID!, $roleInGroup: GroupM
|
||||
}
|
||||
membership {
|
||||
role
|
||||
createdAt
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ query Group($isMember: Boolean, $id: ID, $slug: String) {
|
||||
name
|
||||
}
|
||||
myRole
|
||||
currentlyPinnedPostsCount
|
||||
inviteCodes {
|
||||
code
|
||||
redeemedByCount
|
||||
|
||||
3
backend/src/graphql/queries/groups/GroupCount.gql
Normal file
3
backend/src/graphql/queries/groups/GroupCount.gql
Normal file
@ -0,0 +1,3 @@
|
||||
query GroupCount($isMember: Boolean) {
|
||||
GroupCount(isMember: $isMember)
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
mutation UpdatePost(
|
||||
$id: ID!
|
||||
$title: String!
|
||||
$slug: String
|
||||
$content: String!
|
||||
$image: ImageInput
|
||||
$categoryIds: [ID]
|
||||
@ -10,6 +11,7 @@ mutation UpdatePost(
|
||||
UpdatePost(
|
||||
id: $id
|
||||
title: $title
|
||||
slug: $slug
|
||||
content: $content
|
||||
image: $image
|
||||
categoryIds: $categoryIds
|
||||
@ -18,6 +20,7 @@ mutation UpdatePost(
|
||||
) {
|
||||
id
|
||||
title
|
||||
slug
|
||||
content
|
||||
author {
|
||||
id
|
||||
|
||||
@ -10,10 +10,13 @@ import Factory, { cleanDatabase } from '@db/factories'
|
||||
import ChangeGroupMemberRole from '@graphql/queries/groups/ChangeGroupMemberRole.gql'
|
||||
import CreateGroup from '@graphql/queries/groups/CreateGroup.gql'
|
||||
import groupQuery from '@graphql/queries/groups/Group.gql'
|
||||
import GroupCount from '@graphql/queries/groups/GroupCount.gql'
|
||||
import groupMembersQuery from '@graphql/queries/groups/GroupMembers.gql'
|
||||
import JoinGroup from '@graphql/queries/groups/JoinGroup.gql'
|
||||
import LeaveGroup from '@graphql/queries/groups/LeaveGroup.gql'
|
||||
import muteGroupMutation from '@graphql/queries/groups/muteGroup.gql'
|
||||
import RemoveUserFromGroup from '@graphql/queries/groups/RemoveUserFromGroup.gql'
|
||||
import unmuteGroupMutation from '@graphql/queries/groups/unmuteGroup.gql'
|
||||
import UpdateGroup from '@graphql/queries/groups/UpdateGroup.gql'
|
||||
import { createApolloTestSetup } from '@root/test/helpers'
|
||||
|
||||
@ -1740,8 +1743,17 @@ describe('in mode', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// the GQL mutation needs this fields in the result for testing
|
||||
it.todo('has "updatedAt" newer as "createdAt"')
|
||||
it('has "updatedAt" newer than or equal to "createdAt"', async () => {
|
||||
const result = await mutate({
|
||||
mutation: ChangeGroupMemberRole,
|
||||
variables,
|
||||
})
|
||||
const { createdAt, updatedAt }: { createdAt: string; updatedAt: string } =
|
||||
result.data.ChangeGroupMemberRole.membership
|
||||
expect(new Date(updatedAt).getTime()).toBeGreaterThanOrEqual(
|
||||
new Date(createdAt).getTime(),
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -3308,4 +3320,200 @@ describe('in mode', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('clean db after each – additional coverage', () => {
|
||||
beforeEach(async () => {
|
||||
await seedBasicsAndClearAuthentication()
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await cleanDatabase()
|
||||
})
|
||||
|
||||
describe('GroupCount', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
await mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
name: 'Count Test Group',
|
||||
about: 'A group for counting',
|
||||
description:
|
||||
'This is a test group for counting purposes, with enough description length to pass validation',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('returns count of all visible groups when isMember is not set', async () => {
|
||||
const result = await query({ query: GroupCount })
|
||||
expect(result).toMatchObject({
|
||||
data: { GroupCount: 1 },
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it('returns count of groups the user is a member of', async () => {
|
||||
const result = await query({ query: GroupCount, variables: { isMember: true } })
|
||||
expect(result).toMatchObject({
|
||||
data: { GroupCount: 1 },
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('muteGroup and unmuteGroup', () => {
|
||||
let groupId: string
|
||||
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
const result = await mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
name: 'Mute Test Group',
|
||||
about: 'A group for muting',
|
||||
description:
|
||||
'This is a test group for muting purposes, with enough description length to pass validation',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
})
|
||||
groupId = result.data.CreateGroup.id
|
||||
})
|
||||
|
||||
it('mutes a group', async () => {
|
||||
await expect(
|
||||
mutate({ mutation: muteGroupMutation, variables: { groupId } }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
muteGroup: {
|
||||
id: groupId,
|
||||
isMutedByMe: true,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it('unmutes a group', async () => {
|
||||
await mutate({ mutation: muteGroupMutation, variables: { groupId } })
|
||||
await expect(
|
||||
mutate({ mutation: unmuteGroupMutation, variables: { groupId } }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
unmuteGroup: {
|
||||
id: groupId,
|
||||
isMutedByMe: false,
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it('muteGroup throws for unauthenticated user', async () => {
|
||||
authenticatedUser = null
|
||||
await expect(
|
||||
mutate({ mutation: muteGroupMutation, variables: { groupId } }),
|
||||
).resolves.toMatchObject({
|
||||
errors: [expect.objectContaining({ message: 'Not Authorized!' })],
|
||||
})
|
||||
})
|
||||
|
||||
it('unmuteGroup throws for unauthenticated user', async () => {
|
||||
authenticatedUser = null
|
||||
await expect(
|
||||
mutate({ mutation: unmuteGroupMutation, variables: { groupId } }),
|
||||
).resolves.toMatchObject({
|
||||
errors: [expect.objectContaining({ message: 'Not Authorized!' })],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('UpdateGroup slug conflict', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
await mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
id: 'group-a',
|
||||
name: 'Group A',
|
||||
slug: 'group-a',
|
||||
about: 'About A',
|
||||
description:
|
||||
'A test group with enough description length to pass the validation requirement check',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
})
|
||||
await mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
id: 'group-b',
|
||||
name: 'Group B',
|
||||
slug: 'group-b',
|
||||
about: 'About B',
|
||||
description:
|
||||
'A test group with enough description length to pass the validation requirement check',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('throws error when updating slug to conflict with existing group', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: UpdateGroup,
|
||||
variables: { id: 'group-b', slug: 'group-a' },
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [expect.objectContaining({ message: 'Group with this slug already exists!' })],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('CreateGroup slug conflict', () => {
|
||||
beforeEach(async () => {
|
||||
authenticatedUser = await user.toJson()
|
||||
await mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
name: 'Existing Group',
|
||||
slug: 'existing-group',
|
||||
about: 'About',
|
||||
description:
|
||||
'A test group with enough description length to pass the validation requirement check',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
it('throws error when creating group with duplicate slug', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: CreateGroup,
|
||||
variables: {
|
||||
name: 'Another Group',
|
||||
slug: 'existing-group',
|
||||
about: 'About',
|
||||
description:
|
||||
'A test group with enough description length to pass the validation requirement check',
|
||||
groupType: 'public',
|
||||
actionRadius: 'national',
|
||||
categoryIds: ['cat9'],
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [expect.objectContaining({ message: 'Group with this slug already exists!' })],
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -167,7 +167,7 @@ export default {
|
||||
MERGE (owner)-[membership:MEMBER_OF]->(group)
|
||||
SET
|
||||
membership.createdAt = toString(datetime()),
|
||||
membership.updatedAt = null,
|
||||
membership.updatedAt = toString(datetime()),
|
||||
membership.role = 'owner'
|
||||
${categoriesCypher}
|
||||
RETURN group {.*, myRole: membership.role}
|
||||
@ -280,7 +280,7 @@ export default {
|
||||
MERGE (user)-[membership:MEMBER_OF]->(group)
|
||||
ON CREATE SET
|
||||
membership.createdAt = toString(datetime()),
|
||||
membership.updatedAt = null,
|
||||
membership.updatedAt = toString(datetime()),
|
||||
membership.role =
|
||||
CASE WHEN group.groupType = 'public'
|
||||
THEN 'usual'
|
||||
@ -339,7 +339,7 @@ export default {
|
||||
MERGE (member)-[membership:MEMBER_OF]->(group)
|
||||
ON CREATE SET
|
||||
membership.createdAt = toString(datetime()),
|
||||
membership.updatedAt = null,
|
||||
membership.updatedAt = toString(datetime()),
|
||||
membership.role = $roleInGroup
|
||||
ON MATCH SET
|
||||
membership.updatedAt = toString(datetime()),
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||
/* eslint-disable jest/expect-expect */
|
||||
|
||||
import Factory, { cleanDatabase } from '@db/factories'
|
||||
import currentUser from '@graphql/queries/auth/currentUser.gql'
|
||||
@ -234,23 +233,6 @@ describe('validateInviteCode', () => {
|
||||
}),
|
||||
)
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('throws authorization error when querying extended fields', async () => {
|
||||
await expect(
|
||||
query({ query: authenticatedValidateInviteCode, variables: { code: 'PERSNL' } }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
validateInviteCode: {
|
||||
code: 'PERSNL',
|
||||
generatedBy: null,
|
||||
invitedTo: null,
|
||||
isValid: true,
|
||||
},
|
||||
},
|
||||
errors: [{ message: 'Not Authorized!' }],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('as authenticated user', () => {
|
||||
@ -307,27 +289,6 @@ describe('validateInviteCode', () => {
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
// This doesn't work because group permissions are fucked
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('throws authorization error when querying extended hidden group fields', async () => {
|
||||
await expect(
|
||||
query({ query: authenticatedValidateInviteCode, variables: { code: 'GRPHDN' } }),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
validateInviteCode: {
|
||||
code: 'GRPHDN',
|
||||
generatedBy: null,
|
||||
invitedTo: null,
|
||||
isValid: true,
|
||||
},
|
||||
},
|
||||
errors: [{ message: 'Not Authorized!' }],
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('throws no authorization error when querying extended hidden group fields as member', async () => {})
|
||||
})
|
||||
})
|
||||
|
||||
@ -494,9 +455,6 @@ describe('generatePersonalInviteCode', () => {
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('returns a new invite code when colliding with an existing one', () => {})
|
||||
})
|
||||
})
|
||||
|
||||
@ -762,9 +720,6 @@ describe('generateGroupInviteCode', () => {
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
it.skip('returns a new group invite code when colliding with an existing one', () => {})
|
||||
})
|
||||
|
||||
describe('as authenticated not-member', () => {
|
||||
|
||||
@ -118,7 +118,7 @@ export const redeemInviteCode = async (context: Context, code, newUser = false)
|
||||
MERGE (user)-[membership:MEMBER_OF]->(group)
|
||||
ON CREATE SET
|
||||
membership.createdAt = toString(datetime()),
|
||||
membership.updatedAt = null,
|
||||
membership.updatedAt = toString(datetime()),
|
||||
membership.role = $role
|
||||
`,
|
||||
variables: { user: context.user, code, role },
|
||||
|
||||
@ -69,7 +69,7 @@ describe('Filter Posts', () => {
|
||||
content: 'Elli wird fünf. Wir feiern ihren Geburtstag.',
|
||||
postType: 'Event',
|
||||
eventInput: {
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1, 15).toISOString(),
|
||||
eventVenue: 'Garten der Familie Maier',
|
||||
},
|
||||
},
|
||||
@ -174,7 +174,7 @@ describe('Filter Posts', () => {
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1, 15).toISOString(),
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: 'e2',
|
||||
@ -184,9 +184,7 @@ describe('Filter Posts', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// Does not work on months end
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('order events by event start ascending', () => {
|
||||
describe('order events by event start ascending', () => {
|
||||
it('finds the events ordered accordingly', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
@ -202,15 +200,13 @@ describe('Filter Posts', () => {
|
||||
}),
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1, 15).toISOString(),
|
||||
}),
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
// Does not work on months end
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('filter events by event start date', () => {
|
||||
describe('filter events by event start date', () => {
|
||||
it('finds only events after given date', async () => {
|
||||
const {
|
||||
data: { Post: result },
|
||||
@ -231,7 +227,7 @@ describe('Filter Posts', () => {
|
||||
expect(result).toEqual([
|
||||
expect.objectContaining({
|
||||
id: 'e1',
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1).toISOString(),
|
||||
eventStart: new Date(now.getFullYear(), now.getMonth() + 1, 15).toISOString(),
|
||||
}),
|
||||
])
|
||||
})
|
||||
|
||||
@ -20,7 +20,6 @@ import unpushPost from '@graphql/queries/posts/unpushPost.gql'
|
||||
import UpdatePost from '@graphql/queries/posts/UpdatePost.gql'
|
||||
import { createApolloTestSetup } from '@root/test/helpers'
|
||||
|
||||
import type Image from '@db/models/Image'
|
||||
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||
import type { Context } from '@src/context'
|
||||
|
||||
@ -885,50 +884,6 @@ describe('UpdatePost', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// eslint-disable-next-line jest/no-disabled-tests
|
||||
describe.skip('params.image', () => {
|
||||
describe('is object', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, image: { sensitive: true } }
|
||||
})
|
||||
it('updates the image', async () => {
|
||||
await expect(
|
||||
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
|
||||
).resolves.toBeFalsy()
|
||||
await mutate({ mutation: UpdatePost, variables })
|
||||
await expect(
|
||||
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
|
||||
).resolves.toBeTruthy()
|
||||
})
|
||||
})
|
||||
|
||||
describe('is null', () => {
|
||||
beforeEach(() => {
|
||||
variables = { ...variables, image: null }
|
||||
})
|
||||
it('deletes the image', async () => {
|
||||
await expect(database.neode.all('Image')).resolves.toHaveLength(6)
|
||||
await mutate({ mutation: UpdatePost, variables })
|
||||
await expect(database.neode.all('Image')).resolves.toHaveLength(5)
|
||||
})
|
||||
})
|
||||
|
||||
describe('is undefined', () => {
|
||||
beforeEach(() => {
|
||||
delete variables.image
|
||||
})
|
||||
it('keeps the image unchanged', async () => {
|
||||
await expect(
|
||||
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
|
||||
).resolves.toBeFalsy()
|
||||
await mutate({ mutation: UpdatePost, variables })
|
||||
await expect(
|
||||
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
|
||||
).resolves.toBeFalsy()
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@ -219,7 +219,7 @@ export default {
|
||||
} catch (e) {
|
||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||
throw new UserInputError('Post with this slug already exists!')
|
||||
throw new Error(e)
|
||||
throw e
|
||||
} finally {
|
||||
await session.close()
|
||||
}
|
||||
@ -286,6 +286,10 @@ export default {
|
||||
await createOrUpdateLocations('Post', post.id, locationName, session, context)
|
||||
}
|
||||
return post
|
||||
} catch (e) {
|
||||
if (e.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
|
||||
throw new UserInputError('Post with this slug already exists!')
|
||||
throw e
|
||||
} finally {
|
||||
await session.close()
|
||||
}
|
||||
|
||||
@ -239,7 +239,30 @@ describe('reports', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it.todo('creates multiple filed reports')
|
||||
it('creates separate reports for different resources', async () => {
|
||||
await Factory.build(
|
||||
'user',
|
||||
{
|
||||
id: 'second-abusive-user-id',
|
||||
role: 'user',
|
||||
name: 'second-abusive-user',
|
||||
},
|
||||
{
|
||||
email: 'second-abusive@example.org',
|
||||
},
|
||||
)
|
||||
const firstReport = await mutate({
|
||||
mutation: fileReport,
|
||||
variables: { ...variables, resourceId: 'abusive-user-id' },
|
||||
})
|
||||
const secondReport = await mutate({
|
||||
mutation: fileReport,
|
||||
variables: { ...variables, resourceId: 'second-abusive-user-id' },
|
||||
})
|
||||
expect(firstReport.data.fileReport.reportId).not.toEqual(
|
||||
secondReport.data.fileReport.reportId,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
describe('reported resource is a user', () => {
|
||||
|
||||
@ -7,6 +7,7 @@ import SignupVerification from '@graphql/queries/auth/SignupVerification.gql'
|
||||
import CreateGroup from '@graphql/queries/groups/CreateGroup.gql'
|
||||
import UpdateGroup from '@graphql/queries/groups/UpdateGroup.gql'
|
||||
import CreatePost from '@graphql/queries/posts/CreatePost.gql'
|
||||
import UpdatePost from '@graphql/queries/posts/UpdatePost.gql'
|
||||
import { createApolloTestSetup } from '@root/test/helpers'
|
||||
|
||||
import type { ApolloTestSetup } from '@root/test/helpers'
|
||||
@ -424,7 +425,100 @@ describe('slugifyMiddleware', () => {
|
||||
})
|
||||
})
|
||||
|
||||
it.todo('UpdatePost')
|
||||
describe('UpdatePost', () => {
|
||||
let createPostResult
|
||||
|
||||
beforeEach(async () => {
|
||||
createPostResult = await mutate({
|
||||
mutation: CreatePost,
|
||||
variables: {
|
||||
title: 'I am a brand new post',
|
||||
content: 'Some content',
|
||||
categoryIds,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
describe('if new slug not exists', () => {
|
||||
describe('setting slug explicitly', () => {
|
||||
it('has the new slug', async () => {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: UpdatePost,
|
||||
variables: {
|
||||
id: createPostResult.data.CreatePost.id,
|
||||
title: 'I am a brand new post',
|
||||
content: 'Some content',
|
||||
slug: 'my-brand-new-post',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
data: {
|
||||
UpdatePost: {
|
||||
slug: 'my-brand-new-post',
|
||||
},
|
||||
},
|
||||
errors: undefined,
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('if new slug exists in another post', () => {
|
||||
beforeEach(async () => {
|
||||
await Factory.build(
|
||||
'post',
|
||||
{
|
||||
title: 'Pre-existing post',
|
||||
slug: 'pre-existing-post',
|
||||
content: 'Someone else content',
|
||||
},
|
||||
{
|
||||
categoryIds,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
describe('setting slug explicitly', () => {
|
||||
it('rejects UpdatePost', async () => {
|
||||
try {
|
||||
await expect(
|
||||
mutate({
|
||||
mutation: UpdatePost,
|
||||
variables: {
|
||||
id: createPostResult.data.CreatePost.id,
|
||||
title: 'I am a brand new post',
|
||||
content: 'Some content',
|
||||
slug: 'pre-existing-post',
|
||||
},
|
||||
}),
|
||||
).resolves.toMatchObject({
|
||||
errors: [
|
||||
{
|
||||
message: 'Post with this slug already exists!',
|
||||
},
|
||||
],
|
||||
})
|
||||
} catch (error) {
|
||||
throw new Error(`
|
||||
${error}
|
||||
|
||||
Probably your database has no unique constraints!
|
||||
|
||||
To see all constraints go to http://localhost:7474/browser/ and
|
||||
paste the following:
|
||||
\`\`\`
|
||||
CALL db.constraints();
|
||||
\`\`\`
|
||||
|
||||
Learn how to setup the database here:
|
||||
https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/backend/README.md#database-indices-and-constraints
|
||||
`)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('SignupVerification', () => {
|
||||
beforeEach(() => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user