refactor(backend): externalize all remaining queries in spec files (#8902)

* refactor: externalize all remaining queries in spec files

* User with different queries due to permissions

* fix notification:groups

* fix hashtagsmiddleware

* fix blockedUsers

* fix softDeleteMiddleware

* fix shouts.spec

* fix userInteractions spec

* fix mutedUsers spec

* seocialMedia spec

* fix notificationMiddleware.spec

* fix user.spce & fix undefined activeCategories

* fix notifications.spec

* fix userInteractions.spec

* fix blockedUsers & mutedUsers spec

* remove unused comment

* fix locations spec

* fix orderByMiddleware & spec

* fix lint

* fix shout spec
This commit is contained in:
Ulf Gebhardt 2025-09-18 17:43:15 +02:00 committed by GitHub
parent 2c285d6bfb
commit 45d2283138
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 1177 additions and 1570 deletions

View File

@ -18,7 +18,7 @@ module.exports = {
],
coverageThreshold: {
global: {
lines: 92,
lines: 93,
},
},
testMatch: ['**/src/**/?(*.)+(spec|test).ts?(x)'],

View File

@ -18,7 +18,7 @@ export default {
},
title: { type: 'string', disallow: [null], min: 3 },
slug: { type: 'string', allow: [null], unique: 'true' },
content: { type: 'string', disallow: [null], min: 3 },
content: { type: 'string', disallow: [null], required: true, min: 3 },
contentExcerpt: { type: 'string', allow: [null] },
deleted: { type: 'boolean', default: false },
disabled: { type: 'boolean', default: false },

View File

@ -8,6 +8,8 @@ export const CreateComment = gql`
author {
name
}
isPostObservedByMe
postObservingUsersCount
}
}
`

View File

@ -45,6 +45,7 @@ export const CreatePost = gql`
}
isObservedByMe
observingUsersCount
language
}
}
`

View File

@ -0,0 +1,14 @@
import gql from 'graphql-tag'
export const CreateSocialMedia = gql`
mutation ($url: String!) {
CreateSocialMedia(url: $url) {
id
url
url
ownedBy {
name
}
}
}
`

View File

@ -6,10 +6,34 @@ export const Post = gql`
id
title
content
contentExcerpt
eventStart
pinned
createdAt
pinnedAt
isObservedByMe
observingUsersCount
clickedCount
emotionsCount
emotions {
emotion
User {
id
}
}
author {
id
name
}
shoutedBy {
id
}
tags {
id
}
comments {
content
}
}
}
`

View File

@ -8,6 +8,8 @@ export const SignupVerification = gql`
$slug: String
$nonce: String!
$termsAndConditionsAgreedVersion: String!
$about: String
$locale: String
) {
SignupVerification(
email: $email
@ -16,9 +18,13 @@ export const SignupVerification = gql`
slug: $slug
nonce: $nonce
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
about: $about
locale: $locale
) {
id
slug
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
}
}
`

View File

@ -1,10 +1,44 @@
import gql from 'graphql-tag'
export const UpdatePost = gql`
mutation ($id: ID!, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
UpdatePost(id: $id, content: $postContent, title: $title, categoryIds: $categoryIds) {
mutation (
$id: ID!
$title: String!
$content: String!
$image: ImageInput
$categoryIds: [ID]
$postType: PostType
$eventInput: _EventInput
) {
UpdatePost(
id: $id
title: $title
content: $content
image: $image
categoryIds: $categoryIds
postType: $postType
eventInput: $eventInput
) {
id
title
content
author {
name
slug
}
createdAt
updatedAt
categories {
id
}
postType
eventStart
eventLocationName
eventVenue
eventLocation {
lng
lat
}
}
}
`

View File

@ -1,9 +1,38 @@
import gql from 'graphql-tag'
export const UpdateUser = gql`
mutation ($id: ID!, $name: String) {
UpdateUser(id: $id, name: $name) {
mutation (
$id: ID!
$name: String
$termsAndConditionsAgreedVersion: String
$locationName: String # empty string '' sets it to null
$emailNotificationSettings: [EmailNotificationSettingsInput]
) {
UpdateUser(
id: $id
name: $name
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
locationName: $locationName
emailNotificationSettings: $emailNotificationSettings
) {
id
name
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
locationName
location {
name
nameDE
nameEN
nameRU
}
emailNotificationSettings {
type
settings {
name
value
}
}
}
}
`

View File

@ -1,9 +1,165 @@
import gql from 'graphql-tag'
export const User = gql`
query ($name: String) {
User(name: $name) {
email
query ($id: ID, $name: String, $email: String) {
User(id: $id, name: $name, email: $email) {
id
name
badgeTrophiesCount
badgeTrophies {
id
}
badgeVerification {
id
isDefault
}
badgeTrophiesSelected {
id
isDefault
}
followedBy {
id
}
followedByCurrentUser
following {
name
slug
about
avatar {
url
}
comments {
content
contentExcerpt
}
contributions {
title
slug
image {
url
}
content
contentExcerpt
}
}
isMuted
isBlocked
location {
distanceToMe
}
activeCategories
}
}
`
export const UserEmailNotificationSettings = gql`
query ($id: ID, $name: String, $email: String) {
User(id: $id, name: $name, email: $email) {
id
name
badgeTrophiesCount
badgeTrophies {
id
}
badgeVerification {
id
isDefault
}
badgeTrophiesSelected {
id
isDefault
}
followedBy {
id
}
followedByCurrentUser
following {
name
slug
about
avatar {
url
}
comments {
content
contentExcerpt
}
contributions {
title
slug
image {
url
}
content
contentExcerpt
}
}
isMuted
isBlocked
location {
distanceToMe
}
emailNotificationSettings {
type
settings {
name
value
}
}
activeCategories
}
}
`
export const UserEmail = gql`
query ($id: ID, $name: String, $email: String) {
User(id: $id, name: $name, email: $email) {
id
name
email
badgeTrophiesCount
badgeTrophies {
id
}
badgeVerification {
id
isDefault
}
badgeTrophiesSelected {
id
isDefault
}
followedBy {
id
}
followedByCurrentUser
following {
name
slug
about
avatar {
url
}
comments {
content
contentExcerpt
}
contributions {
title
slug
image {
url
}
content
contentExcerpt
}
}
isMuted
isBlocked
location {
distanceToMe
}
activeCategories
}
}
`

View File

@ -3,6 +3,15 @@ import gql from 'graphql-tag'
export const currentUser = gql`
query currentUser {
currentUser {
id
slug
name
avatar {
url
}
email
role
activeCategories
following {
name
}

View File

@ -3,6 +3,7 @@ import gql from 'graphql-tag'
export const followUser = gql`
mutation ($id: ID!) {
followUser(id: $id) {
id
name
followedBy {
id

View File

@ -3,6 +3,7 @@ import gql from 'graphql-tag'
export const markAllAsRead = gql`
mutation {
markAllAsRead {
id
from {
__typename
... on Post {

View File

@ -3,14 +3,23 @@ import gql from 'graphql-tag'
export const notifications = gql`
query ($read: Boolean, $orderBy: NotificationOrdering) {
notifications(read: $read, orderBy: $orderBy) {
reason
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
read
createdAt

View File

@ -5,6 +5,7 @@ export const searchPosts = gql`
searchPosts(query: $query, firstPosts: $firstPosts, postsOffset: $postsOffset) {
postCount
posts {
__typename
id
title
content

View File

@ -1,14 +1,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import { TROPHY_BADGES_SELECTED_MAX } from '@constants/badges'
import Factory, { cleanDatabase } from '@db/factories'
import { revokeBadge } from '@graphql/queries/revokeBadge'
import { rewardTrophyBadge } from '@graphql/queries/rewardTrophyBadge'
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
import { setVerificationBadge } from '@graphql/queries/setVerificationBadge'
import { User } from '@graphql/queries/User'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -800,24 +799,6 @@ describe('Badges', () => {
describe('check test setup', () => {
it('user has one badge and has it selected', async () => {
authenticatedUser = await regularUser.toJson()
const userQuery = gql`
{
User(id: "regular-user-id") {
badgeTrophiesCount
badgeTrophies {
id
}
badgeVerification {
id
isDefault
}
badgeTrophiesSelected {
id
isDefault
}
}
}
`
const expected = {
data: {
User: [
@ -871,7 +852,9 @@ describe('Badges', () => {
},
errors: undefined,
}
await expect(query({ query: userQuery })).resolves.toMatchObject(expected)
await expect(
query({ query: User, variables: { id: 'regular-user-id' } }),
).resolves.toMatchObject(expected)
})
})

View File

@ -3,12 +3,12 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getDriver, getNeode } from '@db/neo4j'
import { followUser } from '@graphql/queries/followUser'
import { unfollowUser } from '@graphql/queries/unfollowUser'
import { User } from '@graphql/queries/User'
import createServer from '@src/server'
const driver = getDriver()
@ -22,17 +22,6 @@ let user1
let user2
let variables
const userQuery = gql`
query ($id: ID) {
User(id: $id) {
followedBy {
id
}
followedByCurrentUser
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -152,7 +141,7 @@ describe('follow', () => {
}
await expect(
query({
query: userQuery,
query: User,
variables: { id: user1.id },
}),
).resolves.toMatchObject({

View File

@ -2,10 +2,11 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { UpdateUser } from '@graphql/queries/UpdateUser'
import { User } from '@graphql/queries/User'
import createServer from '@src/server'
let query, mutate, authenticatedUser
@ -22,6 +23,9 @@ beforeAll(async () => {
driver,
neode,
user: authenticatedUser,
cypherParams: {
currentUserId: authenticatedUser ? authenticatedUser.id : null,
},
}
},
})
@ -43,17 +47,6 @@ describe('resolvers', () => {
describe('Location', () => {
describe('custom mutation, not handled by neo4j-graphql-js', () => {
let variables
const updateUserMutation = gql`
mutation ($id: ID!, $name: String) {
UpdateUser(id: $id, name: $name) {
name
location {
name: nameRU
nameEN
}
}
}
`
beforeEach(async () => {
variables = {
@ -78,12 +71,12 @@ describe('resolvers', () => {
})
it('returns `null` if location translation is not available', async () => {
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject({
data: {
UpdateUser: {
name: 'John Doughnut',
location: {
name: null,
nameRU: null,
nameEN: 'Paris',
},
},
@ -95,15 +88,6 @@ describe('resolvers', () => {
})
})
const distanceToMeQuery = gql`
query ($id: ID!) {
User(id: $id) {
location {
distanceToMe
}
}
}
`
let user, myPlaceUser, otherPlaceUser, noCordsPlaceUser, noPlaceUser
describe('distanceToMe', () => {
@ -191,21 +175,19 @@ describe('distanceToMe', () => {
authenticatedUser = await user.toJson()
const targetUser = await user.toJson()
await expect(
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
location: {
distanceToMe: 0,
},
query({ query: User, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: {
User: [
expect.objectContaining({
location: {
distanceToMe: 0,
},
],
},
errors: undefined,
}),
)
}),
],
},
errors: undefined,
})
})
})
@ -214,21 +196,19 @@ describe('distanceToMe', () => {
authenticatedUser = await user.toJson()
const targetUser = await myPlaceUser.toJson()
await expect(
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
location: {
distanceToMe: 0,
},
query({ query: User, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: {
User: [
expect.objectContaining({
location: {
distanceToMe: 0,
},
],
},
errors: undefined,
}),
)
}),
],
},
errors: undefined,
})
})
})
@ -237,21 +217,19 @@ describe('distanceToMe', () => {
authenticatedUser = await user.toJson()
const targetUser = await otherPlaceUser.toJson()
await expect(
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
location: {
distanceToMe: 746,
},
query({ query: User, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: {
User: [
expect.objectContaining({
location: {
distanceToMe: 746,
},
],
},
errors: undefined,
}),
)
}),
],
},
errors: undefined,
})
})
})
@ -260,21 +238,19 @@ describe('distanceToMe', () => {
authenticatedUser = await user.toJson()
const targetUser = await noCordsPlaceUser.toJson()
await expect(
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
location: {
distanceToMe: null,
},
query({ query: User, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: {
User: [
expect.objectContaining({
location: {
distanceToMe: null,
},
],
},
errors: undefined,
}),
)
}),
],
},
errors: undefined,
})
})
})
@ -283,19 +259,17 @@ describe('distanceToMe', () => {
authenticatedUser = await user.toJson()
const targetUser = await noPlaceUser.toJson()
await expect(
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
location: null,
},
],
},
errors: undefined,
}),
)
query({ query: User, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: {
User: [
expect.objectContaining({
location: null,
}),
],
},
errors: undefined,
})
})
})
})

View File

@ -165,44 +165,46 @@ describe('given some notifications', () => {
describe('no filters', () => {
it('returns all notifications of current user', async () => {
const expected = [
{
from: {
__typename: 'Comment',
content: 'You have seen this comment mentioning already',
},
read: true,
createdAt: '2019-08-30T15:33:48.651Z',
},
{
from: {
__typename: 'Post',
content: 'Already seen post mention',
},
read: true,
createdAt: '2019-08-30T17:33:48.651Z',
},
{
from: {
__typename: 'Comment',
content: 'You have been mentioned in a comment',
},
read: false,
createdAt: '2019-08-30T19:33:48.651Z',
},
{
from: {
__typename: 'Post',
content: 'You have been mentioned in a post',
},
read: false,
createdAt: '2019-08-31T17:33:48.651Z',
},
]
await expect(query({ query: notifications, variables })).resolves.toMatchObject({
data: {
notifications: expect.arrayContaining(expected),
notifications: expect.arrayContaining([
expect.objectContaining({
from: {
__typename: 'Comment',
content: 'You have seen this comment mentioning already',
id: 'c1',
},
read: true,
createdAt: '2019-08-30T15:33:48.651Z',
}),
expect.objectContaining({
from: {
__typename: 'Post',
content: 'Already seen post mention',
id: 'p2',
},
read: true,
createdAt: '2019-08-30T17:33:48.651Z',
}),
expect.objectContaining({
from: {
__typename: 'Comment',
content: 'You have been mentioned in a comment',
id: 'c2',
},
read: false,
createdAt: '2019-08-30T19:33:48.651Z',
}),
expect.objectContaining({
from: {
__typename: 'Post',
content: 'You have been mentioned in a post',
id: 'p3',
},
read: false,
createdAt: '2019-08-31T17:33:48.651Z',
}),
]),
},
errors: undefined,
})
@ -211,33 +213,34 @@ describe('given some notifications', () => {
describe('filter for read: false', () => {
it('returns only unread notifications of current user', async () => {
const expected = expect.objectContaining({
data: {
notifications: expect.arrayContaining([
{
from: {
__typename: 'Comment',
content: 'You have been mentioned in a comment',
},
read: false,
createdAt: '2019-08-30T19:33:48.651Z',
},
{
from: {
__typename: 'Post',
content: 'You have been mentioned in a post',
},
read: false,
createdAt: '2019-08-31T17:33:48.651Z',
},
]),
},
})
const response = await query({
query: notifications,
variables: { ...variables, read: false },
})
await expect(response).toMatchObject(expected)
await expect(response).toMatchObject({
data: {
notifications: expect.arrayContaining([
expect.objectContaining({
from: {
__typename: 'Comment',
content: 'You have been mentioned in a comment',
id: 'c2',
},
read: false,
createdAt: '2019-08-30T19:33:48.651Z',
}),
expect.objectContaining({
from: {
__typename: 'Post',
content: 'You have been mentioned in a post',
id: 'p3',
},
read: false,
createdAt: '2019-08-31T17:33:48.651Z',
}),
]),
},
})
await expect(response.data?.notifications).toHaveLength(2) // double-check
})
@ -394,11 +397,13 @@ describe('given some notifications', () => {
{
createdAt: '2019-08-30T19:33:48.651Z',
from: { __typename: 'Comment', content: 'You have been mentioned in a comment' },
id: 'mentioned_in_comment/c2/you',
read: true,
},
{
createdAt: '2019-08-31T17:33:48.651Z',
from: { __typename: 'Post', content: 'You have been mentioned in a post' },
id: 'mentioned_in_post/p3/you',
read: true,
},
]),

View File

@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { CreateComment } from '@graphql/queries/CreateComment'
import { CreatePost } from '@graphql/queries/CreatePost'
import { Post } from '@graphql/queries/Post'
import { toggleObservePost } from '@graphql/queries/toggleObservePost'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
@ -20,25 +20,6 @@ let query: ApolloTestSetup['query']
let database: ApolloTestSetup['database']
let server: ApolloTestSetup['server']
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
isPostObservedByMe
postObservingUsersCount
}
}
`
const postQuery = gql`
query Post($id: ID) {
Post(id: $id) {
isObservedByMe
observingUsersCount
}
}
`
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -101,7 +82,7 @@ describe('observing posts', () => {
it('has another user NOT observing the post BEFORE commenting it', async () => {
await expect(
query({
query: postQuery,
query: Post,
variables: { id: 'p2' },
}),
).resolves.toMatchObject({
@ -120,7 +101,7 @@ describe('observing posts', () => {
it('has another user observing the post AFTER commenting it', async () => {
await expect(
mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
postId: 'p2',
content: 'After commenting the post, I should observe the post automatically',
@ -137,7 +118,7 @@ describe('observing posts', () => {
await expect(
query({
query: postQuery,
query: Post,
variables: { id: 'p2' },
}),
).resolves.toMatchObject({
@ -185,7 +166,7 @@ describe('observing posts', () => {
it('does NOT alter the observation state', async () => {
await expect(
mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
postId: 'p2',
content:
@ -203,7 +184,7 @@ describe('observing posts', () => {
await expect(
query({
query: postQuery,
query: Post,
variables: { id: 'p2' },
}),
).resolves.toMatchObject({

View File

@ -2,8 +2,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import Image from '@db/models/Image'
import { AddPostEmotions } from '@graphql/queries/AddPostEmotions'
@ -18,6 +16,7 @@ import { pushPost } from '@graphql/queries/pushPost'
import { RemovePostEmotions } from '@graphql/queries/RemovePostEmotions'
import { unpinPost } from '@graphql/queries/unpinPost'
import { unpushPost } from '@graphql/queries/unpushPost'
import { UpdatePost } from '@graphql/queries/UpdatePost'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -133,18 +132,14 @@ describe('Post', () => {
describe('no filter', () => {
it('returns all posts', async () => {
const postQueryNoFilters = gql`
query Post($filter: _PostFilter) {
Post(filter: $filter) {
id
}
}
`
const expected = [{ id: 'happy-post' }, { id: 'cry-post' }, { id: 'post-by-followed-user' }]
variables = { filter: {} }
await expect(query({ query: postQueryNoFilters, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining(expected),
Post: expect.arrayContaining([
expect.objectContaining({ id: 'happy-post' }),
expect.objectContaining({ id: 'cry-post' }),
expect.objectContaining({ id: 'post-by-followed-user' }),
]),
},
})
})
@ -178,17 +173,6 @@ describe('Post', () => {
}) */
describe('by emotions', () => {
const postQueryFilteredByEmotions = gql`
query Post($filter: _PostFilter) {
Post(filter: $filter) {
id
emotions {
emotion
}
}
}
`
it('filters by single emotion', async () => {
const expected = {
data: {
@ -202,30 +186,25 @@ describe('Post', () => {
}
await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy'] } } }
await expect(
query({ query: postQueryFilteredByEmotions, variables }),
).resolves.toMatchObject(expected)
await expect(query({ query: Post, variables })).resolves.toMatchObject(expected)
})
it('filters by multiple emotions', async () => {
const expected = [
{
id: 'happy-post',
emotions: [{ emotion: 'happy' }],
},
{
id: 'cry-post',
emotions: [{ emotion: 'cry' }],
},
]
await user.relateTo(happyPost, 'emoted', { emotion: 'happy' })
await user.relateTo(cryPost, 'emoted', { emotion: 'cry' })
variables = { ...variables, filter: { emotions_some: { emotion_in: ['happy', 'cry'] } } }
await expect(
query({ query: postQueryFilteredByEmotions, variables }),
).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining(expected),
Post: expect.arrayContaining([
expect.objectContaining({
id: 'happy-post',
emotions: [expect.objectContaining({ emotion: 'happy' })],
}),
expect.objectContaining({
id: 'cry-post',
emotions: [expect.objectContaining({ emotion: 'cry' })],
}),
]),
},
errors: undefined,
})
@ -233,22 +212,9 @@ describe('Post', () => {
})
it('by followed-by', async () => {
const postQueryFilteredByUsersFollowed = gql`
query Post($filter: _PostFilter) {
Post(filter: $filter) {
id
author {
name
}
}
}
`
await user.relateTo(followedUser, 'following')
variables = { filter: { author: { followedBy_some: { id: 'current-user' } } } }
await expect(
query({ query: postQueryFilteredByUsersFollowed, variables }),
).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: [
{
@ -655,48 +621,6 @@ describe('CreatePost', () => {
describe('UpdatePost', () => {
let author, newlyCreatedPost
const updatePostMutation = gql`
mutation (
$id: ID!
$title: String!
$content: String!
$image: ImageInput
$categoryIds: [ID]
$postType: PostType
$eventInput: _EventInput
) {
UpdatePost(
id: $id
title: $title
content: $content
image: $image
categoryIds: $categoryIds
postType: $postType
eventInput: $eventInput
) {
id
title
content
author {
name
slug
}
createdAt
updatedAt
categories {
id
}
postType
eventStart
eventLocationName
eventVenue
eventLocation {
lng
lat
}
}
}
`
beforeEach(async () => {
author = await Factory.build('user', { slug: 'the-author' })
authenticatedUser = await author.toJson()
@ -719,7 +643,7 @@ describe('UpdatePost', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
authenticatedUser = null
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject({
await expect(mutate({ mutation: UpdatePost, variables })).resolves.toMatchObject({
errors: [{ message: 'Not Authorized!' }],
data: { UpdatePost: null },
})
@ -732,7 +656,7 @@ describe('UpdatePost', () => {
})
it('throws authorization error', async () => {
const { errors } = await mutate({ mutation: updatePostMutation, variables })
const { errors } = await mutate({ mutation: UpdatePost, variables })
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@ -747,9 +671,7 @@ describe('UpdatePost', () => {
data: { UpdatePost: { id: newlyCreatedPost.id, content: 'New content' } },
errors: undefined,
}
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdatePost, variables })).resolves.toMatchObject(expected)
})
it('updates a post, but maintains non-updated attributes', async () => {
@ -763,18 +685,16 @@ describe('UpdatePost', () => {
},
errors: undefined,
}
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdatePost, variables })).resolves.toMatchObject(expected)
})
it('updates the updatedAt attribute', async () => {
const {
data: { UpdatePost },
} = (await mutate({ mutation: updatePostMutation, variables })) as any // eslint-disable-line @typescript-eslint/no-explicit-any
expect(UpdatePost.updatedAt).toBeTruthy()
expect(Date.parse(UpdatePost.updatedAt)).toEqual(expect.any(Number))
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePost.updatedAt)
data: { UpdatePost: UpdatePostData },
} = (await mutate({ mutation: UpdatePost, variables })) as any // eslint-disable-line @typescript-eslint/no-explicit-any
expect(UpdatePostData.updatedAt).toBeTruthy()
expect(Date.parse(UpdatePostData.updatedAt)).toEqual(expect.any(Number))
expect(newlyCreatedPost.updatedAt).not.toEqual(UpdatePostData.updatedAt)
})
describe('no new category ids provided for update', () => {
@ -788,9 +708,7 @@ describe('UpdatePost', () => {
},
errors: undefined,
}
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdatePost, variables })).resolves.toMatchObject(expected)
})
})
@ -809,9 +727,7 @@ describe('UpdatePost', () => {
},
errors: undefined,
}
await expect(mutate({ mutation: updatePostMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdatePost, variables })).resolves.toMatchObject(expected)
})
})
@ -820,7 +736,7 @@ describe('UpdatePost', () => {
it('throws an error', async () => {
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: { ...variables, postType: 'Event' },
}),
).resolves.toMatchObject({
@ -837,7 +753,7 @@ describe('UpdatePost', () => {
it('throws an error', async () => {
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: {
...variables,
postType: 'Event',
@ -861,7 +777,7 @@ describe('UpdatePost', () => {
const now = new Date()
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: {
...variables,
postType: 'Event',
@ -885,7 +801,7 @@ describe('UpdatePost', () => {
const now = new Date()
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: {
...variables,
postType: 'Event',
@ -910,7 +826,7 @@ describe('UpdatePost', () => {
const now = new Date()
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: {
...variables,
postType: 'Event',
@ -936,7 +852,7 @@ describe('UpdatePost', () => {
const now = new Date()
await expect(
mutate({
mutation: updatePostMutation,
mutation: UpdatePost,
variables: {
...variables,
postType: 'Event',
@ -976,7 +892,7 @@ describe('UpdatePost', () => {
await expect(
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
).resolves.toBeFalsy()
await mutate({ mutation: updatePostMutation, variables })
await mutate({ mutation: UpdatePost, variables })
await expect(
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
).resolves.toBeTruthy()
@ -989,7 +905,7 @@ describe('UpdatePost', () => {
})
it('deletes the image', async () => {
await expect(database.neode.all('Image')).resolves.toHaveLength(6)
await mutate({ mutation: updatePostMutation, variables })
await mutate({ mutation: UpdatePost, variables })
await expect(database.neode.all('Image')).resolves.toHaveLength(5)
})
})
@ -1002,7 +918,7 @@ describe('UpdatePost', () => {
await expect(
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
).resolves.toBeFalsy()
await mutate({ mutation: updatePostMutation, variables })
await mutate({ mutation: UpdatePost, variables })
await expect(
database.neode.first<typeof Image>('Image', { sensitive: true }, undefined),
).resolves.toBeFalsy()
@ -2131,25 +2047,6 @@ describe('DeletePost', () => {
describe('emotions', () => {
let author, postToEmote
const PostsEmotionsCountQuery = gql`
query ($id: ID!) {
Post(id: $id) {
emotionsCount
}
}
`
const PostsEmotionsQuery = gql`
query ($id: ID!) {
Post(id: $id) {
emotions {
emotion
User {
id
}
}
}
}
`
beforeEach(async () => {
author = await database.neode.create('User', { id: 'u257' })
@ -2226,8 +2123,8 @@ describe('emotions', () => {
await mutate({ mutation: AddPostEmotions, variables })
await mutate({ mutation: AddPostEmotions, variables })
await expect(
query({ query: PostsEmotionsCountQuery, variables: postsEmotionsQueryVariables }),
).resolves.toEqual(expect.objectContaining(expected))
query({ query: Post, variables: postsEmotionsQueryVariables }),
).resolves.toMatchObject(expected)
})
it('allows a user to add more than one emotion', async () => {
@ -2247,8 +2144,8 @@ describe('emotions', () => {
variables = { ...variables, data: { emotion: 'surprised' } }
await mutate({ mutation: AddPostEmotions, variables })
await expect(
query({ query: PostsEmotionsQuery, variables: postsEmotionsQueryVariables }),
).resolves.toEqual(expect.objectContaining(expected))
query({ query: Post, variables: postsEmotionsQueryVariables }),
).resolves.toMatchObject(expected)
})
})
@ -2351,8 +2248,8 @@ describe('emotions', () => {
variables: removePostEmotionsVariables,
})
await expect(
query({ query: PostsEmotionsQuery, variables: postsEmotionsQueryVariables }),
).resolves.toEqual(expect.objectContaining(expectedResponse))
query({ query: Post, variables: postsEmotionsQueryVariables }),
).resolves.toMatchObject(expectedResponse)
})
})
})

View File

@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import EmailAddress from '@db/models/EmailAddress'
import User from '@db/models/User'
import { Signup } from '@graphql/queries/Signup'
import { SignupVerification } from '@graphql/queries/SignupVerification'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -158,31 +157,6 @@ describe('Signup', () => {
})
describe('SignupVerification', () => {
const mutation = gql`
mutation (
$name: String!
$password: String!
$email: String!
$nonce: String!
$about: String
$termsAndConditionsAgreedVersion: String!
$locale: String
) {
SignupVerification(
name: $name
password: $password
email: $email
nonce: $nonce
about: $about
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
locale: $locale
) {
id
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
}
}
`
describe('given valid password and email', () => {
beforeEach(() => {
variables = {
@ -219,7 +193,9 @@ describe('SignupVerification', () => {
})
it('rejects', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
errors: [{ message: 'Invalid email or nonce' }],
})
})
@ -237,7 +213,9 @@ describe('SignupVerification', () => {
describe('sending a valid nonce', () => {
it('creates a user account', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
data: {
SignupVerification: expect.objectContaining({
id: expect.any(String),
@ -247,7 +225,7 @@ describe('SignupVerification', () => {
})
it('sets `verifiedAt` attribute of EmailAddress', async () => {
await mutate({ mutation, variables })
await mutate({ mutation: SignupVerification, variables })
const email = await database.neode.first(
'EmailAddress',
{ email: 'john@example.org' },
@ -265,14 +243,14 @@ describe('SignupVerification', () => {
MATCH(email:EmailAddress)-[:BELONGS_TO]->(u:User {name: $name})
RETURN email
`
await mutate({ mutation, variables })
await mutate({ mutation: SignupVerification, variables })
const { records: emails } = await database.neode.cypher(cypher, { name: 'John Doe' })
expect(emails).toHaveLength(1)
})
it('sets `about` attribute of User', async () => {
variables = { ...variables, about: 'Find this description in the user profile' }
await mutate({ mutation, variables })
await mutate({ mutation: SignupVerification, variables })
const user = await database.neode.first<typeof User>(
'User',
{ name: 'John Doe' },
@ -285,7 +263,9 @@ describe('SignupVerification', () => {
it('allowing the about field to be an empty string', async () => {
variables = { ...variables, about: '' }
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
data: {
SignupVerification: expect.objectContaining({
id: expect.any(String),
@ -299,13 +279,15 @@ describe('SignupVerification', () => {
MATCH(email:EmailAddress)<-[:PRIMARY_EMAIL]-(u:User {name: $name})
RETURN email
`
await mutate({ mutation, variables })
await mutate({ mutation: SignupVerification, variables })
const { records: emails } = await database.neode.cypher(cypher, { name: 'John Doe' })
expect(emails).toHaveLength(1)
})
it('updates termsAndConditionsAgreedVersion', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
data: {
SignupVerification: expect.objectContaining({
termsAndConditionsAgreedVersion: '0.1.0',
@ -315,7 +297,9 @@ describe('SignupVerification', () => {
})
it('updates termsAndConditionsAgreedAt', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
data: {
SignupVerification: expect.objectContaining({
termsAndConditionsAgreedAt: expect.any(String),
@ -326,7 +310,9 @@ describe('SignupVerification', () => {
it('rejects if version of terms and conditions is missing', async () => {
variables = { ...variables, termsAndConditionsAgreedVersion: null }
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
errors: [
{
message:
@ -338,7 +324,9 @@ describe('SignupVerification', () => {
it('rejects if version of terms and conditions has wrong format', async () => {
variables = { ...variables, termsAndConditionsAgreedVersion: 'invalid version format' }
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
errors: [{ message: 'Invalid version format!' }],
})
})
@ -350,7 +338,9 @@ describe('SignupVerification', () => {
})
it('rejects', async () => {
await expect(mutate({ mutation, variables })).resolves.toMatchObject({
await expect(
mutate({ mutation: SignupVerification, variables }),
).resolves.toMatchObject({
errors: [{ message: 'Invalid email or nonce' }],
})
})

View File

@ -2,10 +2,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { searchPosts } from '@graphql/queries/searchPosts'
import { searchResults } from '@graphql/queries/searchResults'
import createServer from '@src/server'
@ -34,19 +34,6 @@ afterAll(async () => {
await driver.close()
neode.close()
})
const searchPostQuery = gql`
query ($query: String!, $firstPosts: Int, $postsOffset: Int) {
searchPosts(query: $query, firstPosts: $firstPosts, postsOffset: $postsOffset) {
postCount
posts {
__typename
id
title
content
}
}
}
`
describe('resolvers/searches', () => {
let variables
@ -605,7 +592,7 @@ und hinter tausend Stäben keine Welt.`,
describe('query with limit 1', () => {
it('has a count greater than 1', async () => {
variables = { query: 'beitrag', firstPosts: 1, postsOffset: 0 }
await expect(query({ query: searchPostQuery, variables })).resolves.toMatchObject({
await expect(query({ query: searchPosts, variables })).resolves.toMatchObject({
data: {
searchPosts: {
postCount: 2,

View File

@ -3,10 +3,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { Post } from '@graphql/queries/Post'
import { shout } from '@graphql/queries/shout'
import { unshout } from '@graphql/queries/unshout'
import createServer from '@src/server'
@ -14,16 +14,6 @@ import createServer from '@src/server'
let mutate, query, authenticatedUser, variables
const instance = getNeode()
const driver = getDriver()
const queryPost = gql`
query ($id: ID!) {
Post(id: $id) {
id
shoutedBy {
id
}
}
}
`
describe('shout and unshout posts', () => {
let currentUser, postAuthor
@ -38,6 +28,9 @@ describe('shout and unshout posts', () => {
driver,
neode: instance,
user: authenticatedUser,
cypherParams: {
currentUserId: authenticatedUser ? authenticatedUser.id : null,
},
}
},
})
@ -122,7 +115,7 @@ describe('shout and unshout posts', () => {
await expect(mutate({ mutation: shout, variables })).resolves.toMatchObject({
data: { shout: true },
})
await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: { Post: [{ id: 'another-user-post-id', shoutedBy: [{ id: 'current-user-id' }] }] },
errors: undefined,
})
@ -149,7 +142,7 @@ describe('shout and unshout posts', () => {
await expect(mutate({ mutation: shout, variables })).resolves.toMatchObject({
data: { shout: false },
})
await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: { Post: [{ id: 'current-user-post-id', shoutedBy: [] }] },
errors: undefined,
})
@ -191,7 +184,7 @@ describe('shout and unshout posts', () => {
await expect(mutate({ mutation: unshout, variables })).resolves.toMatchObject({
data: { unshout: true },
})
await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: { Post: [{ id: 'posted-by-another-user', shoutedBy: [] }] },
errors: undefined,
})

View File

@ -4,10 +4,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getDriver } from '@db/neo4j'
import { CreateSocialMedia } from '@graphql/queries/CreateSocialMedia'
import { DeleteSocialMedia } from '@graphql/queries/DeleteSocialMedia'
import { UpdateSocialMedia } from '@graphql/queries/UpdateSocialMedia'
import createServer from '@src/server'
@ -84,24 +84,16 @@ describe('SocialMedia', () => {
})
describe('create social media', () => {
let mutation, variables
let variables
beforeEach(() => {
mutation = gql`
mutation ($url: String!) {
CreateSocialMedia(url: $url) {
id
url
}
}
`
variables = { url }
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const user = null
const result = await socialMediaAction(user, mutation, variables)
const result = await socialMediaAction(user, CreateSocialMedia, variables)
expect(result.errors[0]).toHaveProperty('message', 'Not Authorized!')
})
@ -115,21 +107,19 @@ describe('SocialMedia', () => {
})
it('creates social media with the given url', async () => {
await expect(socialMediaAction(user, mutation, variables)).resolves.toEqual(
expect.objectContaining({
data: {
CreateSocialMedia: {
id: expect.any(String),
url,
},
await expect(socialMediaAction(user, CreateSocialMedia, variables)).resolves.toMatchObject({
data: {
CreateSocialMedia: {
id: expect.any(String),
url,
},
}),
)
},
})
})
it('rejects an empty string as url', async () => {
variables = { url: '' }
const result = await socialMediaAction(user, mutation, variables)
const result = await socialMediaAction(user, CreateSocialMedia, variables)
expect(result.errors[0].message).toEqual(
expect.stringContaining('"url" is not allowed to be empty'),
@ -138,7 +128,7 @@ describe('SocialMedia', () => {
it('rejects invalid urls', async () => {
variables = { url: 'not-a-url' }
const result = await socialMediaAction(user, mutation, variables)
const result = await socialMediaAction(user, CreateSocialMedia, variables)
expect(result.errors[0].message).toEqual(
expect.stringContaining('"url" must be a valid uri'),
@ -147,28 +137,13 @@ describe('SocialMedia', () => {
})
describe('ownedBy', () => {
beforeEach(() => {
mutation = gql`
mutation ($url: String!) {
CreateSocialMedia(url: $url) {
url
ownedBy {
name
}
}
}
`
})
it('resolves', async () => {
const user = someUser
await expect(socialMediaAction(user, mutation, variables)).resolves.toEqual(
expect.objectContaining({
data: {
CreateSocialMedia: { url, ownedBy: { name: 'Kalle Blomqvist' } },
},
}),
)
await expect(socialMediaAction(user, CreateSocialMedia, variables)).resolves.toMatchObject({
data: {
CreateSocialMedia: { url, ownedBy: { name: 'Kalle Blomqvist' } },
},
})
})
})
})

View File

@ -6,12 +6,12 @@
/* eslint-disable promise/prefer-await-to-callbacks */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable jest/unbound-method */
import gql from 'graphql-tag'
import { verify } from 'jsonwebtoken'
import { categories } from '@constants/categories'
import Factory, { cleanDatabase } from '@db/factories'
import { changePassword } from '@graphql/queries/changePassword'
import { currentUser } from '@graphql/queries/currentUser'
import { login } from '@graphql/queries/login'
import { saveCategorySettings } from '@graphql/queries/saveCategorySettings'
import { decode } from '@jwt/decode'
@ -86,24 +86,8 @@ afterEach(async () => {
})
describe('currentUser', () => {
const currentUserQuery = gql`
{
currentUser {
id
slug
name
avatar {
url
}
email
role
activeCategories
}
}
`
const respondsWith = async (expected) => {
await expect(query({ query: currentUserQuery, variables })).resolves.toMatchObject(expected)
await expect(query({ query: currentUser, variables })).resolves.toMatchObject(expected)
}
describe('unauthenticated', () => {
@ -211,7 +195,7 @@ describe('currentUser', () => {
})
it('returns only the saved active categories', async () => {
const result = await query({ query: currentUserQuery, variables })
const result = await query({ query: currentUser, variables })
expect(result.data?.currentUser.activeCategories).toHaveLength(4)
expect(result.data?.currentUser.activeCategories).toContain('cat1')
expect(result.data?.currentUser.activeCategories).toContain('cat3')

View File

@ -3,8 +3,6 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/require-await */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import gql from 'graphql-tag'
import { categories } from '@constants/categories'
import pubsubContext from '@context/pubsub'
import Factory, { cleanDatabase } from '@db/factories'
@ -15,6 +13,8 @@ import { saveCategorySettings } from '@graphql/queries/saveCategorySettings'
import { setTrophyBadgeSelected } from '@graphql/queries/setTrophyBadgeSelected'
import { switchUserRole } from '@graphql/queries/switchUserRole'
import { updateOnlineStatus } from '@graphql/queries/updateOnlineStatus'
import { UpdateUser } from '@graphql/queries/UpdateUser'
import { UserEmailNotificationSettings, User as userQuery } from '@graphql/queries/User'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -63,21 +63,12 @@ afterEach(async () => {
describe('User', () => {
describe('query by email address', () => {
let userQuery
beforeEach(async () => {
const user = await Factory.build('user', {
id: 'user',
role: 'user',
})
authenticatedUser = await user.toJson()
userQuery = gql`
query ($email: String) {
User(email: $email) {
name
}
}
`
variables = {
email: 'any-email-address@example.org',
}
@ -131,35 +122,7 @@ describe('User', () => {
})
describe('UpdateUser', () => {
let updateUserMutation
beforeEach(async () => {
updateUserMutation = gql`
mutation (
$id: ID!
$name: String
$termsAndConditionsAgreedVersion: String
$locationName: String # empty string '' sets it to null
) {
UpdateUser(
id: $id
name: $name
termsAndConditionsAgreedVersion: $termsAndConditionsAgreedVersion
locationName: $locationName
) {
id
name
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
locationName
location {
name
nameDE
nameEN
}
}
}
`
variables = {
id: 'u47',
name: 'John Doughnut',
@ -196,8 +159,10 @@ describe('UpdateUser', () => {
})
it('is not allowed to change other user accounts', async () => {
const { errors } = await mutate({ mutation: updateUserMutation, variables })
expect(errors?.[0]).toHaveProperty('message', 'Not Authorized!')
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject({
data: { UpdateUser: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -216,9 +181,7 @@ describe('UpdateUser', () => {
},
errors: undefined,
}
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject(expected)
})
describe('given a new agreed version of terms and conditions', () => {
@ -236,9 +199,7 @@ describe('UpdateUser', () => {
errors: undefined,
}
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject(expected)
})
})
@ -257,9 +218,7 @@ describe('UpdateUser', () => {
errors: undefined,
}
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject(
expected,
)
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject(expected)
})
})
@ -268,7 +227,7 @@ describe('UpdateUser', () => {
...variables,
termsAndConditionsAgreedVersion: 'invalid version format',
}
const { errors } = await mutate({ mutation: updateUserMutation, variables })
const { errors } = await mutate({ mutation: UpdateUser, variables })
expect(errors?.[0]).toHaveProperty('message', 'Invalid version format!')
})
@ -276,7 +235,7 @@ describe('UpdateUser', () => {
describe('change location to "Hamburg, New Jersey, United States"', () => {
it('has updated location to "Hamburg, New Jersey, United States"', async () => {
variables = { ...variables, locationName: 'Hamburg, New Jersey, United States' }
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject({
data: {
UpdateUser: {
locationName: 'Hamburg, New Jersey, United States',
@ -295,7 +254,7 @@ describe('UpdateUser', () => {
describe('change location to unset location', () => {
it('has updated location to unset location', async () => {
variables = { ...variables, locationName: '' }
await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
await expect(mutate({ mutation: UpdateUser, variables })).resolves.toMatchObject({
data: {
UpdateUser: {
locationName: null,
@ -548,15 +507,10 @@ describe('switch user role', () => {
id: 'user',
role: 'admin',
}
await expect(mutate({ mutation: switchUserRole, variables })).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
await expect(mutate({ mutation: switchUserRole, variables })).resolves.toMatchObject({
data: { switchUserRole: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -598,33 +552,6 @@ describe('switch user role', () => {
})
let anotherUser
const emailNotificationSettingsQuery = gql`
query ($id: ID!) {
User(id: $id) {
emailNotificationSettings {
type
settings {
name
value
}
}
}
}
`
const emailNotificationSettingsMutation = gql`
mutation ($id: ID!, $emailNotificationSettings: [EmailNotificationSettingsInput]!) {
UpdateUser(id: $id, emailNotificationSettings: $emailNotificationSettings) {
emailNotificationSettings {
type
settings {
name
value
}
}
}
}
`
describe('emailNotificationSettings', () => {
beforeEach(async () => {
@ -644,16 +571,11 @@ describe('emailNotificationSettings', () => {
authenticatedUser = await anotherUser.toJson()
const targetUser = await user.toJson()
await expect(
query({ query: emailNotificationSettingsQuery, variables: { id: targetUser.id } }),
).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
query({ query: UserEmailNotificationSettings, variables: { id: targetUser.id } }),
).resolves.toMatchObject({
data: { User: [null] },
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -662,112 +584,13 @@ describe('emailNotificationSettings', () => {
authenticatedUser = await user.toJson()
await expect(
query({
query: emailNotificationSettingsQuery,
query: UserEmailNotificationSettings,
variables: { id: authenticatedUser?.id },
}),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
emailNotificationSettings: [
{
type: 'post',
settings: [
{
name: 'commentOnObservedPost',
value: true,
},
{
name: 'mention',
value: true,
},
{
name: 'followingUsers',
value: true,
},
{
name: 'postInGroup',
value: true,
},
],
},
{
type: 'chat',
settings: [
{
name: 'chatMessage',
value: true,
},
],
},
{
type: 'group',
settings: [
{
name: 'groupMemberJoined',
value: true,
},
{
name: 'groupMemberLeft',
value: true,
},
{
name: 'groupMemberRemoved',
value: true,
},
{
name: 'groupMemberRoleChanged',
value: true,
},
],
},
],
},
],
},
}),
)
})
})
})
describe('mutate the field', () => {
const emailNotificationSettings = [{ name: 'mention', value: false }]
describe('as another user', () => {
it('throws an error', async () => {
authenticatedUser = await anotherUser.toJson()
const targetUser = await user.toJson()
await expect(
mutate({
mutation: emailNotificationSettingsMutation,
variables: { id: targetUser.id, emailNotificationSettings },
}),
).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
})
})
describe('as self', () => {
it('updates the emailNotificationSettings', async () => {
authenticatedUser = (await user.toJson()) as DecodedUser
await expect(
mutate({
mutation: emailNotificationSettingsMutation,
variables: { id: authenticatedUser.id, emailNotificationSettings },
}),
).resolves.toEqual(
expect.objectContaining({
data: {
UpdateUser: {
).resolves.toMatchObject({
data: {
User: [
{
emailNotificationSettings: [
{
type: 'post',
@ -778,7 +601,7 @@ describe('emailNotificationSettings', () => {
},
{
name: 'mention',
value: false,
value: true,
},
{
name: 'followingUsers',
@ -822,9 +645,99 @@ describe('emailNotificationSettings', () => {
},
],
},
},
],
},
})
})
})
})
describe('mutate the field', () => {
const emailNotificationSettings = [{ name: 'mention', value: false }]
describe('as another user', () => {
it('throws an error', async () => {
authenticatedUser = await anotherUser.toJson()
const targetUser = await user.toJson()
await expect(
mutate({
mutation: UpdateUser,
variables: { id: targetUser.id, emailNotificationSettings },
}),
)
).resolves.toMatchObject({
data: { UpdateUser: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})
describe('as self', () => {
it('updates the emailNotificationSettings', async () => {
authenticatedUser = (await user.toJson()) as DecodedUser
await expect(
mutate({
mutation: UpdateUser,
variables: { id: authenticatedUser.id, emailNotificationSettings },
}),
).resolves.toMatchObject({
data: {
UpdateUser: {
emailNotificationSettings: [
{
type: 'post',
settings: [
{
name: 'commentOnObservedPost',
value: true,
},
{
name: 'mention',
value: false,
},
{
name: 'followingUsers',
value: true,
},
{
name: 'postInGroup',
value: true,
},
],
},
{
type: 'chat',
settings: [
{
name: 'chatMessage',
value: true,
},
],
},
{
type: 'group',
settings: [
{
name: 'groupMemberJoined',
value: true,
},
{
name: 'groupMemberLeft',
value: true,
},
{
name: 'groupMemberRemoved',
value: true,
},
{
name: 'groupMemberRoleChanged',
value: true,
},
],
},
],
},
},
})
})
})
})
@ -860,15 +773,10 @@ describe('save category settings', () => {
})
it('throws an error', async () => {
await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toMatchObject({
data: { saveCategorySettings: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -877,14 +785,6 @@ describe('save category settings', () => {
authenticatedUser = await user.toJson()
})
const userQuery = gql`
query ($id: ID) {
User(id: $id) {
activeCategories
}
}
`
describe('no categories saved', () => {
it('returns true for active categories mutation', async () => {
await expect(mutate({ mutation: saveCategorySettings, variables })).resolves.toEqual(
@ -902,17 +802,15 @@ describe('save category settings', () => {
it('returns the active categories when user is queried', async () => {
await expect(
query({ query: userQuery, variables: { id: authenticatedUser?.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
activeCategories: expect.arrayContaining(['cat1', 'cat3', 'cat5']),
},
],
},
}),
)
).resolves.toMatchObject({
data: {
User: [
{
activeCategories: expect.arrayContaining(['cat1', 'cat3', 'cat5']),
},
],
},
})
})
})
})
@ -944,23 +842,21 @@ describe('save category settings', () => {
it('returns the new active categories when user is queried', async () => {
await expect(
query({ query: userQuery, variables: { id: authenticatedUser?.id } }),
).resolves.toEqual(
expect.objectContaining({
data: {
User: [
{
activeCategories: expect.arrayContaining([
'cat10',
'cat11',
'cat12',
'cat8',
'cat9',
]),
},
],
},
}),
)
).resolves.toMatchObject({
data: {
User: [
{
activeCategories: expect.arrayContaining([
'cat10',
'cat11',
'cat12',
'cat8',
'cat9',
]),
},
],
},
})
})
})
})
@ -984,15 +880,10 @@ describe('updateOnlineStatus', () => {
})
it('throws an error', async () => {
await expect(mutate({ mutation: updateOnlineStatus, variables })).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
await expect(mutate({ mutation: updateOnlineStatus, variables })).resolves.toMatchObject({
data: null,
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -1122,15 +1013,10 @@ describe('setTrophyBadgeSelected', () => {
mutation: setTrophyBadgeSelected,
variables: { slot: 0, badgeId: 'trophy_bear' },
}),
).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
).resolves.toMatchObject({
data: { setTrophyBadgeSelected: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})
@ -1500,15 +1386,10 @@ describe('resetTrophyBadgesSelected', () => {
})
it('throws an error', async () => {
await expect(mutate({ mutation: resetTrophyBadgesSelected })).resolves.toEqual(
expect.objectContaining({
errors: [
expect.objectContaining({
message: 'Not Authorized!',
}),
],
}),
)
await expect(mutate({ mutation: resetTrophyBadgesSelected })).resolves.toMatchObject({
data: { resetTrophyBadgesSelected: null },
errors: [{ message: 'Not Authorized!' }],
})
})
})

View File

@ -638,6 +638,7 @@ export default {
'allowEmbedIframes',
'showShoutsPublicly',
'locale',
'activeCategories',
],
boolean: {
followedByCurrentUser:

View File

@ -2,12 +2,12 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import gql from 'graphql-tag'
import { cleanDatabase } from '@db/factories'
import { blockedUsers } from '@graphql/queries/blockedUsers'
import { blockUser } from '@graphql/queries/blockUser'
import { Post } from '@graphql/queries/Post'
import { unblockUser } from '@graphql/queries/unblockUser'
import { User } from '@graphql/queries/User'
import { createApolloTestSetup } from '@root/test/helpers'
import type { ApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -155,56 +155,37 @@ describe('blockUser', () => {
it('unfollows the user when blocking', async () => {
await currentUser.relateTo(blockedUser, 'following')
const queryUser = gql`
query {
User(id: "u2") {
id
isBlocked
followedByCurrentUser
}
}
`
await expect(query({ query: queryUser })).resolves.toMatchObject({
await expect(query({ query: User, variables: { id: 'u2' } })).resolves.toMatchObject({
data: { User: [{ id: 'u2', isBlocked: false, followedByCurrentUser: true }] },
})
await mutate({ mutation: blockUser, variables: { id: 'u2' } })
await expect(query({ query: queryUser })).resolves.toMatchObject({
await expect(query({ query: User, variables: { id: 'u2' } })).resolves.toMatchObject({
data: { User: [{ id: 'u2', isBlocked: true, followedByCurrentUser: false }] },
})
})
describe('given both the current user and the to-be-blocked user write a post', () => {
let postQuery
beforeEach(async () => {
const post1 = await database.neode.create('Post', {
id: 'p12',
title: 'A post written by the current user',
content: 'content',
})
const post2 = await database.neode.create('Post', {
id: 'p23',
title: 'A post written by the blocked user',
content: 'content',
})
await Promise.all([
post1.relateTo(currentUser, 'author'),
post2.relateTo(blockedUser, 'author'),
])
postQuery = gql`
query {
Post(orderBy: createdAt_asc) {
id
title
author {
id
name
}
}
}
`
})
const bothPostsAreInTheNewsfeed = async () => {
await expect(query({ query: postQuery })).resolves.toMatchObject({
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: [
{
@ -238,7 +219,9 @@ describe('blockUser', () => {
// TODO: clarify proper behaviour
it("the blocked user's post still shows up in the newsfeed of the current user", async () => {
await expect(query({ query: postQuery })).resolves.toMatchObject({
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: [
{
@ -276,19 +259,21 @@ describe('blockUser', () => {
})
it("the current user's post will show up in the newsfeed of the blocked user", async () => {
await expect(query({ query: postQuery })).resolves.toMatchObject({
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
{
expect.objectContaining({
id: 'p23',
title: 'A post written by the blocked user',
author: { name: 'Blocked User', id: 'u2' },
},
{
}),
expect.objectContaining({
id: 'p12',
title: 'A post written by the current user',
author: { name: 'Current User', id: 'u1' },
},
}),
]),
},
})

View File

@ -1,10 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { queryLocations } from '@graphql/queries/queryLocations'
import { UpdateUser } from '@graphql/queries/UpdateUser'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -19,13 +18,6 @@ let query: any // eslint-disable-line @typescript-eslint/no-explicit-any
let database: ApolloTestSetup['database']
let server: ApolloTestSetup['server']
const updateUserMutation = gql`
mutation ($id: ID!, $name: String!, $locationName: String) {
UpdateUser(id: $id, name: $name, locationName: $locationName) {
locationName
}
}
`
const newlyCreatedNodesWithLocales = [
{
city: {
@ -203,7 +195,7 @@ describe('userMiddleware', () => {
name: 'Updating user',
locationName: 'Welzheim, Baden-Württemberg, Germany',
}
await mutate({ mutation: updateUserMutation, variables })
await mutate({ mutation: UpdateUser, variables })
const locations = await database.neode.cypher(
`MATCH (city:Location)-[:IS_IN]->(district:Location)-[:IS_IN]->(state:Location)-[:IS_IN]->(country:Location) return city {.*}, state {.*}, country {.*}`,
{},

View File

@ -3,13 +3,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { mutedUsers } from '@graphql/queries/mutedUsers'
import { muteUser } from '@graphql/queries/muteUser'
import { Post } from '@graphql/queries/Post'
import { unmuteUser } from '@graphql/queries/unmuteUser'
import { User } from '@graphql/queries/User'
import createServer from '@src/server'
const driver = getDriver()
@ -152,85 +153,68 @@ describe('muteUser', () => {
it('unfollows the user', async () => {
await currentUser.relateTo(mutedUser, 'following')
const queryUser = gql`
query {
User(id: "u2") {
id
isMuted
followedByCurrentUser
}
}
`
const { query } = createTestClient(server)
await expect(query({ query: queryUser })).resolves.toEqual(
expect.objectContaining({
data: { User: [{ id: 'u2', isMuted: false, followedByCurrentUser: true }] },
}),
)
await expect(query({ query: User, variables: { id: 'u2' } })).resolves.toMatchObject({
data: {
User: expect.arrayContaining([
expect.objectContaining({ id: 'u2', isMuted: false, followedByCurrentUser: true }),
]),
},
})
await muteAction({ id: 'u2' })
await expect(query({ query: queryUser })).resolves.toEqual(
expect.objectContaining({
data: { User: [{ id: 'u2', isMuted: true, followedByCurrentUser: false }] },
}),
)
await expect(query({ query: User, variables: { id: 'u2' } })).resolves.toMatchObject({
data: {
User: expect.arrayContaining([
expect.objectContaining({ id: 'u2', isMuted: true, followedByCurrentUser: false }),
]),
},
})
})
describe('given both the current user and the to-be-muted user write a post', () => {
let postQuery
beforeEach(async () => {
const post1 = await neode.create('Post', {
id: 'p12',
title: 'A post written by the current user',
content: 'content',
})
const post2 = await neode.create('Post', {
id: 'p23',
title: 'A post written by the muted user',
content: 'content',
})
await Promise.all([
post1.relateTo(currentUser, 'author'),
post2.relateTo(mutedUser, 'author'),
])
postQuery = gql`
query {
Post(orderBy: createdAt_asc) {
id
title
author {
id
name
}
}
}
`
})
const bothPostsAreInTheNewsfeed = async () => {
const { query } = createTestClient(server)
await expect(query({ query: postQuery })).resolves.toEqual(
expect.objectContaining({
data: {
Post: [
{
id: 'p12',
title: 'A post written by the current user',
author: {
name: 'Current User',
id: 'u1',
},
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
expect.objectContaining({
id: 'p12',
title: 'A post written by the current user',
author: {
name: 'Current User',
id: 'u1',
},
{
id: 'p23',
title: 'A post written by the muted user',
author: {
name: 'Muted User',
id: 'u2',
},
}),
expect.objectContaining({
id: 'p23',
title: 'A post written by the muted user',
author: {
name: 'Muted User',
id: 'u2',
},
],
},
}),
)
}),
]),
},
})
}
describe('from the perspective of the current user', () => {
@ -243,19 +227,19 @@ describe('muteUser', () => {
it("the muted user's post won't show up in the newsfeed of the current user", async () => {
const { query } = createTestClient(server)
await expect(query({ query: postQuery })).resolves.toEqual(
expect.objectContaining({
data: {
Post: [
{
id: 'p12',
title: 'A post written by the current user',
author: { name: 'Current User', id: 'u1' },
},
],
},
}),
)
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: [
expect.objectContaining({
id: 'p12',
title: 'A post written by the current user',
author: { name: 'Current User', id: 'u1' },
}),
],
},
})
})
})
})
@ -273,24 +257,24 @@ describe('muteUser', () => {
it("the current user's post will show up in the newsfeed of the muted user", async () => {
const { query } = createTestClient(server)
await expect(query({ query: postQuery })).resolves.toEqual(
expect.objectContaining({
data: {
Post: expect.arrayContaining([
{
id: 'p23',
title: 'A post written by the muted user',
author: { name: 'Muted User', id: 'u2' },
},
{
id: 'p12',
title: 'A post written by the current user',
author: { name: 'Current User', id: 'u1' },
},
]),
},
}),
)
await expect(
query({ query: Post, variables: { orderBy: 'createdAt_asc' } }),
).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
expect.objectContaining({
id: 'p23',
title: 'A post written by the muted user',
author: { name: 'Muted User', id: 'u2' },
}),
expect.objectContaining({
id: 'p12',
title: 'A post written by the current user',
author: { name: 'Current User', id: 'u1' },
}),
]),
},
})
})
})
})

View File

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import { cleanDatabase } from '@db/factories'
import { CreatePost } from '@graphql/queries/CreatePost'
import { Post } from '@graphql/queries/Post'
import { UpdatePost } from '@graphql/queries/UpdatePost'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
@ -17,15 +17,6 @@ let query: any // eslint-disable-line @typescript-eslint/no-explicit-any
let database: ApolloTestSetup['database']
let server: ApolloTestSetup['server']
const categoryIds = ['cat9']
const createPostMutation = gql`
mutation ($id: ID, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
CreatePost(id: $id, title: $title, content: $postContent, categoryIds: $categoryIds) {
id
title
content
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -64,7 +55,7 @@ afterEach(async () => {
describe('hashtags', () => {
const id = 'p135'
const title = 'Two Hashtags'
const postContent = `
const content = `
<p>
Hey Dude,
<a
@ -85,15 +76,6 @@ describe('hashtags', () => {
for everyone.
</p>
`
const postWithHastagsQuery = gql`
query ($id: ID) {
Post(id: $id) {
tags {
id
}
}
}
`
const postWithHastagsVariables = {
id,
}
@ -106,46 +88,43 @@ describe('hashtags', () => {
describe('create a Post with Hashtags', () => {
beforeEach(async () => {
await mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables: {
id,
title,
postContent,
content,
categoryIds,
},
})
})
it('both hashtags are created with the "id" set to their "name"', async () => {
const expected = [
{
id: 'Democracy',
},
{
id: 'Liberty',
},
]
await expect(
query({
query: postWithHastagsQuery,
query: Post,
variables: postWithHastagsVariables,
}),
).resolves.toEqual(
expect.objectContaining({
data: {
Post: [
{
tags: expect.arrayContaining(expected),
},
],
},
}),
)
).resolves.toMatchObject({
data: {
Post: [
{
tags: expect.arrayContaining([
expect.objectContaining({
id: 'Democracy',
}),
expect.objectContaining({
id: 'Liberty',
}),
]),
},
],
},
})
})
describe('updates the Post by removing, keeping and adding one hashtag respectively', () => {
// The already existing hashtag has no class at this point.
const postContent = `
const content = `
<p>
Hey Dude,
<a
@ -173,35 +152,32 @@ describe('hashtags', () => {
variables: {
id,
title,
postContent,
content,
categoryIds,
},
})
const expected = [
{
id: 'Elections',
},
{
id: 'Liberty',
},
]
await expect(
query({
query: postWithHastagsQuery,
query: Post,
variables: postWithHastagsVariables,
}),
).resolves.toEqual(
expect.objectContaining({
data: {
Post: [
{
tags: expect.arrayContaining(expected),
},
],
},
}),
)
).resolves.toMatchObject({
data: {
Post: [
{
tags: expect.arrayContaining([
expect.objectContaining({
id: 'Elections',
}),
expect.objectContaining({
id: 'Liberty',
}),
]),
},
],
},
})
})
})
})

View File

@ -1,9 +1,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { CreatePost } from '@graphql/queries/CreatePost'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -30,14 +29,6 @@ afterAll(async () => {
database.neode.close()
})
const createPostMutation = gql`
mutation ($title: String!, $content: String!, $categoryIds: [ID]) {
CreatePost(title: $title, content: $content, categoryIds: $categoryIds) {
language
}
}
`
describe('languagesMiddleware', () => {
variables = {
title: 'Test post languages',
@ -61,7 +52,7 @@ describe('languagesMiddleware', () => {
}
await expect(
mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables,
}),
).resolves.toMatchObject({
@ -80,7 +71,7 @@ describe('languagesMiddleware', () => {
}
await expect(
mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables,
}),
).resolves.toMatchObject({
@ -99,7 +90,7 @@ describe('languagesMiddleware', () => {
}
await expect(
mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables,
}),
).resolves.toMatchObject({
@ -119,7 +110,7 @@ describe('languagesMiddleware', () => {
}
await expect(
mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables,
}),
).resolves.toMatchObject({
@ -139,7 +130,7 @@ describe('languagesMiddleware', () => {
}
await expect(
mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables,
}),
).resolves.toMatchObject({

View File

@ -1,13 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { CreateComment } from '@graphql/queries/CreateComment'
import { CreateGroup } from '@graphql/queries/CreateGroup'
import { CreatePost } from '@graphql/queries/CreatePost'
import { followUser } from '@graphql/queries/followUser'
import { JoinGroup } from '@graphql/queries/JoinGroup'
import { markAllAsRead } from '@graphql/queries/markAllAsRead'
import { notifications } from '@graphql/queries/notifications'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -32,61 +33,6 @@ const mentionString = `
<a class="mention" data-mention-id="group-member" href="/profile/group-member/group-member">@group-member</a>
<a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member">@email-less-member</a>`
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
content
}
}
`
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
const followUserMutation = gql`
mutation ($id: ID!) {
followUser(id: $id) {
id
}
}
`
const markAllAsRead = async () =>
mutate({
mutation: gql`
mutation {
markAllAsRead {
id
}
}
`,
})
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -154,7 +100,7 @@ describe('emails sent for notifications', () => {
},
})
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
authenticatedUser = await emaillessMember.toJson()
@ -166,7 +112,7 @@ describe('emails sent for notifications', () => {
},
})
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
})
@ -206,7 +152,8 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -284,7 +231,8 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -363,7 +311,8 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -437,7 +386,8 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -503,18 +453,20 @@ describe('emails sent for notifications', () => {
})
authenticatedUser = await groupMember.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment',
content: `Hello, my beloved author.`,
postId: 'post',
},
})
await markAllAsRead()
await mutate({
mutation: markAllAsRead,
})
jest.clearAllMocks()
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment-2',
content: `Hello, ${mentionString}, my trusty followers.`,
@ -537,8 +489,9 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -591,18 +544,20 @@ describe('emails sent for notifications', () => {
})
authenticatedUser = await groupMember.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment',
content: `Hello, my beloved author.`,
postId: 'post',
},
})
await markAllAsRead()
await mutate({
mutation: markAllAsRead,
})
jest.clearAllMocks()
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment-2',
content: `Hello, ${mentionString}, my trusty followers.`,
@ -625,8 +580,9 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -680,18 +636,20 @@ describe('emails sent for notifications', () => {
})
authenticatedUser = await groupMember.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment',
content: `Hello, my beloved author.`,
postId: 'post',
},
})
await markAllAsRead()
await mutate({
mutation: markAllAsRead,
})
jest.clearAllMocks()
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'comment-2',
content: `Hello, ${mentionString}, my trusty followers.`,
@ -708,8 +666,9 @@ describe('emails sent for notifications', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),

View File

@ -1,12 +1,11 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { CreateGroup } from '@graphql/queries/CreateGroup'
import { CreatePost } from '@graphql/queries/CreatePost'
import { followUser } from '@graphql/queries/followUser'
import { notifications } from '@graphql/queries/notifications'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -26,41 +25,6 @@ let server: ApolloTestSetup['server']
let postAuthor, firstFollower, secondFollower, thirdFollower, emaillessFollower
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
const followUserMutation = gql`
mutation ($id: ID!) {
followUser(id: $id) {
id
}
}
`
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -135,22 +99,22 @@ describe('following users notifications', () => {
await secondFollower.update({ emailNotificationsFollowingUsers: false })
authenticatedUser = await firstFollower.toJson()
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
authenticatedUser = await secondFollower.toJson()
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
authenticatedUser = await thirdFollower.toJson()
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
authenticatedUser = await emaillessFollower.toJson()
await mutate({
mutation: followUserMutation,
mutation: followUser,
variables: { id: 'post-author' },
})
jest.clearAllMocks()
@ -172,7 +136,8 @@ describe('following users notifications', () => {
it('sends NO notification to the post author', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -186,7 +151,8 @@ describe('following users notifications', () => {
authenticatedUser = await firstFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -209,7 +175,8 @@ describe('following users notifications', () => {
authenticatedUser = await secondFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -232,7 +199,8 @@ describe('following users notifications', () => {
authenticatedUser = await emaillessFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -295,7 +263,8 @@ describe('following users notifications', () => {
it('sends NO notification to the post author', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -309,7 +278,8 @@ describe('following users notifications', () => {
authenticatedUser = await firstFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -364,7 +334,8 @@ describe('following users notifications', () => {
it('sends NO notification to the post author', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -378,7 +349,8 @@ describe('following users notifications', () => {
authenticatedUser = await firstFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -433,7 +405,8 @@ describe('following users notifications', () => {
it('sends NO notification to the post author', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -447,7 +420,8 @@ describe('following users notifications', () => {
authenticatedUser = await firstFollower.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {

View File

@ -1,14 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { ChangeGroupMemberRole } from '@graphql/queries/ChangeGroupMemberRole'
import { CreateComment } from '@graphql/queries/CreateComment'
import { CreateGroup } from '@graphql/queries/CreateGroup'
import { CreatePost } from '@graphql/queries/CreatePost'
import { JoinGroup } from '@graphql/queries/JoinGroup'
import { markAllAsRead } from '@graphql/queries/markAllAsRead'
import { notifications } from '@graphql/queries/notifications'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -35,53 +35,6 @@ const mentionString = `
<a class="mention" data-mention-id="email-less-member" href="/profile/email-less-member/email-less-member">@email-less-member</a>.
`
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $commentContent: String!) {
CreateComment(id: $id, postId: $postId, content: $commentContent) {
id
content
}
}
`
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
const markAllAsRead = async () =>
mutate({
mutation: gql`
mutation {
markAllAsRead {
id
}
}
`,
})
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -285,9 +238,9 @@ describe('mentions in groups', () => {
},
})
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await emaillessMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
})
afterEach(async () => {
@ -313,8 +266,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -339,8 +293,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -419,8 +374,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -436,8 +392,9 @@ describe('mentions in groups', () => {
authenticatedUser = await pendingMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -453,8 +410,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -521,8 +479,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -538,8 +497,9 @@ describe('mentions in groups', () => {
authenticatedUser = await pendingMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -555,8 +515,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -618,15 +579,15 @@ describe('mentions in groups', () => {
},
})
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await postAuthor.toJson()
jest.clearAllMocks()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'public-comment',
postId: 'public-post',
commentContent: `Hey everyone ${mentionString}! Please read this`,
content: `Hey everyone ${mentionString}! Please read this`,
},
})
})
@ -635,8 +596,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -661,8 +623,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -713,15 +676,15 @@ describe('mentions in groups', () => {
},
})
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await postAuthor.toJson()
jest.clearAllMocks()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'closed-comment',
postId: 'closed-post',
commentContent: `Hey members ${mentionString}! Please read this`,
content: `Hey members ${mentionString}! Please read this`,
},
})
})
@ -730,8 +693,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -747,8 +711,9 @@ describe('mentions in groups', () => {
authenticatedUser = await pendingMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -764,8 +729,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -810,15 +776,15 @@ describe('mentions in groups', () => {
},
})
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await postAuthor.toJson()
jest.clearAllMocks()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'hidden-comment',
postId: 'hidden-post',
commentContent: `Hey hiders ${mentionString}! Please read this`,
content: `Hey hiders ${mentionString}! Please read this`,
},
})
})
@ -827,8 +793,9 @@ describe('mentions in groups', () => {
authenticatedUser = await noMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -844,8 +811,9 @@ describe('mentions in groups', () => {
authenticatedUser = await pendingMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -861,8 +829,9 @@ describe('mentions in groups', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),

View File

@ -1,10 +1,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { CreateComment } from '@graphql/queries/CreateComment'
import { CreatePost } from '@graphql/queries/CreatePost'
import { notifications } from '@graphql/queries/notifications'
import { toggleObservePost } from '@graphql/queries/toggleObservePost'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
@ -25,41 +25,6 @@ let server: ApolloTestSetup['server']
let postAuthor, firstCommenter, secondCommenter, emaillessObserver
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
content
}
}
`
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -142,7 +107,7 @@ describe('notifications for users that observe a post', () => {
beforeAll(async () => {
authenticatedUser = await firstCommenter.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
postId: 'post',
id: 'c-1',
@ -154,7 +119,8 @@ describe('notifications for users that observe a post', () => {
it('sends NO notification to the commenter', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -168,7 +134,8 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await postAuthor.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -202,7 +169,7 @@ describe('notifications for users that observe a post', () => {
jest.clearAllMocks()
authenticatedUser = await secondCommenter.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
postId: 'post',
id: 'c-2',
@ -214,7 +181,8 @@ describe('notifications for users that observe a post', () => {
it('sends NO notification to the commenter', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -228,7 +196,8 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await postAuthor.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -259,7 +228,8 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await firstCommenter.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -309,7 +279,7 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
postId: 'post',
id: 'c-3',
@ -321,7 +291,8 @@ describe('notifications for users that observe a post', () => {
it('sends no new notification to the post author', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -352,7 +323,8 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await firstCommenter.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {
@ -375,7 +347,8 @@ describe('notifications for users that observe a post', () => {
authenticatedUser = await secondCommenter.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: { orderBy: 'updatedAt_desc' },
}),
).resolves.toMatchObject({
data: {

View File

@ -1,15 +1,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { ChangeGroupMemberRole } from '@graphql/queries/ChangeGroupMemberRole'
import { CreateGroup } from '@graphql/queries/CreateGroup'
import { CreatePost } from '@graphql/queries/CreatePost'
import { JoinGroup } from '@graphql/queries/JoinGroup'
import { markAllAsRead } from '@graphql/queries/markAllAsRead'
import { muteGroup } from '@graphql/queries/muteGroup'
import { notifications } from '@graphql/queries/notifications'
import { unmuteGroup } from '@graphql/queries/unmuteGroup'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
@ -30,44 +29,6 @@ let server: ApolloTestSetup['server']
let postAuthor, groupMember, pendingMember, emaillessMember
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
const markAllAsRead = async () =>
mutate({
mutation: gql`
mutation {
markAllAsRead {
id
}
}
`,
})
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -190,9 +151,9 @@ describe('notify group members of new posts in group', () => {
beforeEach(async () => {
jest.clearAllMocks()
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await postAuthor.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
await mutate({
mutation: CreatePost,
variables: {
@ -207,8 +168,9 @@ describe('notify group members of new posts in group', () => {
it('sends NO notification to the author of the post', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -224,8 +186,9 @@ describe('notify group members of new posts in group', () => {
authenticatedUser = await pendingMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -241,8 +204,9 @@ describe('notify group members of new posts in group', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -298,8 +262,9 @@ describe('notify group members of new posts in group', () => {
it('sends NO notification when another post is posted', async () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -330,7 +295,7 @@ describe('notify group members of new posts in group', () => {
it('sends notification when another post is posted', async () => {
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: CreatePost,
@ -344,8 +309,9 @@ describe('notify group members of new posts in group', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -376,7 +342,7 @@ describe('notify group members of new posts in group', () => {
beforeEach(async () => {
await groupMember.relateTo(postAuthor, 'blocked')
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
jest.clearAllMocks()
authenticatedUser = await postAuthor.toJson()
await mutate({
@ -394,8 +360,9 @@ describe('notify group members of new posts in group', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -416,7 +383,7 @@ describe('notify group members of new posts in group', () => {
beforeEach(async () => {
await groupMember.relateTo(postAuthor, 'muted')
authenticatedUser = await groupMember.toJson()
await markAllAsRead()
await mutate({ mutation: markAllAsRead })
jest.clearAllMocks()
authenticatedUser = await postAuthor.toJson()
await mutate({
@ -434,8 +401,9 @@ describe('notify group members of new posts in group', () => {
authenticatedUser = await groupMember.toJson()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),

View File

@ -4,16 +4,18 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-return */
import gql from 'graphql-tag'
import pubsubContext from '@context/pubsub'
import Factory, { cleanDatabase } from '@db/factories'
import { ChangeGroupMemberRole } from '@graphql/queries/ChangeGroupMemberRole'
import { CreateComment } from '@graphql/queries/CreateComment'
import { CreateGroup } from '@graphql/queries/CreateGroup'
import { CreateMessage } from '@graphql/queries/CreateMessage'
import { CreatePost } from '@graphql/queries/CreatePost'
import { CreateRoom } from '@graphql/queries/CreateRoom'
import { JoinGroup } from '@graphql/queries/JoinGroup'
import { LeaveGroup } from '@graphql/queries/LeaveGroup'
import { markAsRead } from '@graphql/queries/markAsRead'
import { notifications } from '@graphql/queries/notifications'
import { RemoveUserFromGroup } from '@graphql/queries/RemoveUserFromGroup'
import { UpdatePost } from '@graphql/queries/UpdatePost'
import type { ApolloTestSetup } from '@root/test/helpers'
@ -46,23 +48,6 @@ let database: ApolloTestSetup['database']
let server: ApolloTestSetup['server']
const categoryIds = ['cat9']
const createPostMutation = gql`
mutation ($id: ID, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
CreatePost(id: $id, title: $title, content: $postContent, categoryIds: $categoryIds) {
id
title
content
}
}
`
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $commentContent: String!) {
CreateComment(id: $id, postId: $postId, content: $commentContent) {
id
content
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -106,33 +91,6 @@ afterEach(async () => {
})
describe('notifications', () => {
const notificationQuery = gql`
query ($read: Boolean) {
notifications(read: $read, orderBy: updatedAt_desc) {
read
reason
createdAt
relatedUser {
id
}
from {
__typename
... on Post {
id
content
}
... on Comment {
id
content
}
... on Group {
id
}
}
}
}
`
describe('authenticated', () => {
beforeEach(async () => {
authenticatedUser = await notifiedUser.toJson()
@ -146,11 +104,11 @@ describe('notifications', () => {
const createPostAction = async () => {
authenticatedUser = await postAuthor.toJson()
await mutate({
mutation: createPostMutation,
mutation: CreatePost,
variables: {
id: 'p47',
title,
postContent,
content: postContent,
categoryIds,
},
})
@ -163,11 +121,11 @@ describe('notifications', () => {
await createPostAction()
authenticatedUser = await commentAuthor.toJson()
await mutate({
mutation: createCommentMutation,
mutation: CreateComment,
variables: {
id: 'c47',
postId: 'p47',
commentContent,
content: commentContent,
},
})
authenticatedUser = await notifiedUser.toJson()
@ -202,8 +160,9 @@ describe('notifications', () => {
await createCommentOnPostAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -243,8 +202,9 @@ describe('notifications', () => {
await createCommentOnPostAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -283,8 +243,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -302,8 +263,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -326,8 +288,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -366,8 +329,9 @@ describe('notifications', () => {
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone" target="_blank">@al-capone</a> how do you do?'
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -407,8 +371,9 @@ describe('notifications', () => {
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone" target="_blank">@al-capone</a> how do you do?'
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -473,7 +438,7 @@ describe('notifications', () => {
variables: {
id: 'p47',
title,
postContent: updatedContent,
content: updatedContent,
categoryIds,
},
})
@ -504,8 +469,9 @@ describe('notifications', () => {
})
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -513,27 +479,19 @@ describe('notifications', () => {
})
describe('if the notification was marked as read earlier', () => {
const markAsReadAction = async () => {
const mutation = gql`
mutation ($id: ID!) {
markAsRead(id: $id) {
read
}
}
`
await mutate({ mutation, variables: { id: 'p47' } })
}
describe('but the next mention happens after the notification was marked as read', () => {
it('sets the `read` attribute to false again', async () => {
await createPostAction()
await markAsReadAction()
await mutate({ mutation: markAsRead, variables: { id: 'p47' } })
const {
data: {
notifications: [{ read: readBefore }],
},
} = await query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
},
})
await updatePostAction()
const {
@ -541,7 +499,11 @@ describe('notifications', () => {
notifications: [{ read: readAfter }],
},
} = await query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
})
expect(readBefore).toEqual(true)
expect(readAfter).toEqual(false)
@ -549,13 +511,16 @@ describe('notifications', () => {
it('does not update the `createdAt` attribute', async () => {
await createPostAction()
await markAsReadAction()
await mutate({ mutation: markAsRead, variables: { id: 'p47' } })
const {
data: {
notifications: [{ createdAt: createdAtBefore }],
},
} = await query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
},
})
await updatePostAction()
const {
@ -563,7 +528,11 @@ describe('notifications', () => {
notifications: [{ createdAt: createdAtAfter }],
},
} = await query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
})
expect(createdAtBefore).toBeTruthy()
expect(Date.parse(createdAtBefore)).toEqual(expect.any(Number))
@ -588,8 +557,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -630,8 +600,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -704,8 +675,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -739,8 +711,9 @@ describe('notifications', () => {
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -771,8 +744,9 @@ describe('notifications', () => {
await createCommentOnPostAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -822,8 +796,9 @@ describe('notifications', () => {
await createCommentOnPostAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
@ -1118,7 +1093,11 @@ describe('notifications', () => {
await joinGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1156,7 +1135,11 @@ describe('notifications', () => {
await joinGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1213,7 +1196,11 @@ describe('notifications', () => {
await leaveGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1269,7 +1256,11 @@ describe('notifications', () => {
await leaveGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1340,7 +1331,11 @@ describe('notifications', () => {
await changeGroupMemberRoleAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1378,7 +1373,11 @@ describe('notifications', () => {
await changeGroupMemberRoleAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1436,7 +1435,11 @@ describe('notifications', () => {
await removeUserFromGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {
@ -1474,7 +1477,11 @@ describe('notifications', () => {
await removeUserFromGroupAction()
await expect(
query({
query: notificationQuery,
query: notifications,
variables: {
orderBy: 'updatedAt_desc',
read: false,
},
}),
).resolves.toMatchObject({
data: {

View File

@ -1,9 +1,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { Post } from '@graphql/queries/Post'
import createServer from '@src/server'
const neode = getNeode()
@ -15,6 +14,9 @@ const { server } = createServer({
user: null,
neode,
driver,
cypherParams: {
currentUserId: null,
},
}
},
})
@ -30,10 +32,10 @@ afterAll(async () => {
})
beforeEach(async () => {
await neode.create('Post', { title: 'first' })
await neode.create('Post', { title: 'second' })
await neode.create('Post', { title: 'third' })
await neode.create('Post', { title: 'last' })
await neode.create('Post', { title: 'first', content: 'content' })
await neode.create('Post', { title: 'second', content: 'content' })
await neode.create('Post', { title: 'third', content: 'content' })
await neode.create('Post', { title: 'last', content: 'content' })
})
// TODO: avoid database clean after each test in the future if possible for performance and flakyness reasons by filling the database step by step, see issue https://github.com/Ocelot-Social-Community/Ocelot-Social/issues/4543
@ -45,46 +47,35 @@ describe('Query', () => {
describe('Post', () => {
describe('orderBy', () => {
it('createdAt descending is default', async () => {
const posts = [
{ title: 'last' },
{ title: 'third' },
{ title: 'second' },
{ title: 'first' },
]
const expected = expect.objectContaining({ data: { Post: posts } })
await expect(
query({
query: gql`
{
Post {
title
}
}
`,
}),
).resolves.toEqual(expected)
await expect(query({ query: Post })).resolves.toMatchObject({
data: {
Post: [
expect.objectContaining({ title: 'last' }),
expect.objectContaining({ title: 'third' }),
expect.objectContaining({ title: 'second' }),
expect.objectContaining({ title: 'first' }),
],
},
})
})
describe('(orderBy: createdAt_asc)', () => {
it('orders by createdAt ascending', async () => {
const posts = [
{ title: 'first' },
{ title: 'second' },
{ title: 'third' },
{ title: 'last' },
]
const expected = expect.objectContaining({ data: { Post: posts } })
await expect(
query({
query: gql`
{
Post(orderBy: createdAt_asc) {
title
}
}
`,
query: Post,
variables: { orderBy: 'createdAt_asc' },
}),
).resolves.toEqual(expected)
).resolves.toMatchObject({
data: {
Post: [
expect.objectContaining({ title: 'first' }),
expect.objectContaining({ title: 'second' }),
expect.objectContaining({ title: 'third' }),
expect.objectContaining({ title: 'last' }),
],
},
})
})
})
})

View File

@ -6,13 +6,20 @@ import cloneDeep from 'lodash/cloneDeep'
const defaultOrderBy = (resolve, root, args, context, resolveInfo) => {
const copy = cloneDeep(resolveInfo)
const newestFirst = {
kind: 'Argument',
name: { kind: 'Name', value: 'orderBy' },
value: { kind: 'EnumValue', value: 'sortDate_desc' },
}
const [fieldNode] = copy.fieldNodes
if (fieldNode) fieldNode.arguments.push(newestFirst)
if (fieldNode) {
const orderByArg = fieldNode.arguments.find((arg) => arg.name.value === 'orderBy')
if (!orderByArg) {
fieldNode.arguments.push({
kind: 'Argument',
name: { kind: 'Name', value: 'orderBy' },
value: { kind: 'EnumValue', value: 'sortDate_desc' },
})
} else if (args.orderBy === undefined) {
orderByArg.value = { kind: 'EnumValue', value: 'sortDate_desc' }
}
}
return resolve(root, args, context, copy)
}

View File

@ -3,7 +3,7 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import Factory, { cleanDatabase } from '@db/factories'
import { Signup } from '@graphql/queries/Signup'
import { User } from '@graphql/queries/User'
import { User, UserEmail } from '@graphql/queries/User'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
@ -116,7 +116,7 @@ describe('authorization', () => {
it("exposes the owner's email address", async () => {
variables = { name: 'Owner' }
await expect(query({ query: User, variables })).resolves.toMatchObject({
await expect(query({ query: UserEmail, variables })).resolves.toMatchObject({
data: { User: [{ email: 'owner@example.org' }] },
errors: undefined,
})
@ -130,7 +130,7 @@ describe('authorization', () => {
it("throws an error and does not expose the owner's email address", async () => {
await expect(
query({ query: User, variables: { name: 'Owner' } }),
query({ query: UserEmail, variables: { name: 'Owner' } }),
).resolves.toMatchObject({
errors: [{ message: 'Not Authorized!' }],
data: { User: [null] },
@ -145,7 +145,7 @@ describe('authorization', () => {
it("throws an error and does not expose the owner's email address", async () => {
await expect(
query({ query: User, variables: { name: 'Owner' } }),
query({ query: UserEmail, variables: { name: 'Owner' } }),
).resolves.toMatchObject({
errors: [{ message: 'Not Authorized!' }],
data: { User: [null] },
@ -160,7 +160,7 @@ describe('authorization', () => {
it("exposes the owner's email address", async () => {
variables = { name: 'Owner' }
await expect(query({ query: User, variables })).resolves.toMatchObject({
await expect(query({ query: UserEmail, variables })).resolves.toMatchObject({
data: { User: [{ email: 'owner@example.org' }] },
errors: undefined,
})

View File

@ -3,15 +3,14 @@
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { Post } from '@graphql/queries/Post'
import { User } from '@graphql/queries/User'
import type { ApolloTestSetup } from '@root/test/helpers'
import { createApolloTestSetup } from '@root/test/helpers'
import type { Context } from '@src/context'
const categoryIds = ['cat9']
let graphqlQuery
let moderator
let user
let troll
@ -21,10 +20,6 @@ let query: ApolloTestSetup['query']
let database: ApolloTestSetup['database']
let server: ApolloTestSetup['server']
const action = () => {
return query({ query: graphqlQuery })
}
beforeAll(async () => {
await cleanDatabase()
const apolloSetup = createApolloTestSetup({ context })
@ -208,58 +203,15 @@ describe('softDeleteMiddleware', () => {
describe('read disabled content', () => {
let subject
const beforeComment = async () => {
graphqlQuery = gql`
{
User(id: "u1") {
following {
comments {
content
contentExcerpt
}
}
}
}
`
const { data } = await action()
const { data } = await query({ query: User, variables: { id: 'u1' } })
subject = (data as any).User[0].following[0].comments[0]
}
const beforeUser = async () => {
graphqlQuery = gql`
{
User(id: "u1") {
following {
name
slug
about
avatar {
url
}
}
}
}
`
const { data } = await action()
const { data } = await query({ query: User, variables: { id: 'u1' } })
subject = (data as any).User[0].following[0]
}
const beforePost = async () => {
graphqlQuery = gql`
{
User(id: "u1") {
following {
contributions {
title
slug
image {
url
}
content
contentExcerpt
}
}
}
}
`
const { data } = await action()
const { data } = await query({ query: User, variables: { id: 'u1' } })
subject = (data as any).User[0].following[0].contributions[0]
}
@ -341,16 +293,6 @@ describe('softDeleteMiddleware', () => {
describe('Query', () => {
describe('Post', () => {
beforeEach(async () => {
graphqlQuery = gql`
{
Post {
title
}
}
`
})
describe('as user', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
@ -358,7 +300,7 @@ describe('softDeleteMiddleware', () => {
it('hides deleted or disabled posts', async () => {
const expected = { data: { Post: [{ title: 'Publicly visible post' }] } }
await expect(action()).resolves.toMatchObject(expected)
await expect(query({ query: Post })).resolves.toMatchObject(expected)
})
})
@ -368,27 +310,18 @@ describe('softDeleteMiddleware', () => {
})
it('shows disabled but hides deleted posts', async () => {
const expected = [{ title: 'Disabled post' }, { title: 'Publicly visible post' }]
const { data } = await action()
const { Post } = data as any
expect(Post).toEqual(expect.arrayContaining(expected))
const { data } = await query({ query: Post })
const { Post: PostData } = data as any
expect(PostData).toEqual(
expect.arrayContaining([
expect.objectContaining({ title: 'Disabled post' }),
expect.objectContaining({ title: 'Publicly visible post' }),
]),
)
})
})
describe('.comments', () => {
beforeEach(async () => {
graphqlQuery = gql`
{
Post(id: "p3") {
title
comments {
content
}
}
}
`
})
describe('as user', () => {
beforeEach(async () => {
authenticatedUser = await user.toJson()
@ -399,7 +332,7 @@ describe('softDeleteMiddleware', () => {
{ content: 'Enabled comment on public post' },
{ content: 'UNAVAILABLE' },
]
const { data } = await action()
const { data } = await query({ query: Post, variables: { id: 'p3' } })
const {
Post: [{ comments }],
} = data as any
@ -417,7 +350,7 @@ describe('softDeleteMiddleware', () => {
{ content: 'Enabled comment on public post' },
{ content: 'Disabled comment' },
]
const { data } = await action()
const { data } = await query({ query: Post, variables: { id: 'p3' } })
const {
Post: [{ comments }],
} = data as any

View File

@ -2,10 +2,10 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { Post } from '@graphql/queries/Post'
import createServer from '@src/server'
let query, aUser, bUser, post, authenticatedUser, variables
@ -13,14 +13,6 @@ let query, aUser, bUser, post, authenticatedUser, variables
const driver = getDriver()
const neode = getNeode()
const postQuery = gql`
query ($id: ID) {
Post(id: $id) {
clickedCount
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -38,6 +30,9 @@ beforeAll(async () => {
driver,
neode,
user: authenticatedUser,
cypherParams: {
currentUserId: authenticatedUser ? authenticatedUser.id : null,
},
}
},
})
@ -52,12 +47,12 @@ afterAll(async () => {
describe('middleware/userInteractions', () => {
describe('given one post', () => {
it('does not change clickedCount when queried without ID', async () => {
await expect(query({ query: postQuery, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
{
expect.objectContaining({
clickedCount: 0,
},
}),
]),
},
})
@ -65,24 +60,24 @@ describe('middleware/userInteractions', () => {
it('changes clickedCount when queried with ID', async () => {
variables = { id: post.get('id') }
await expect(query({ query: postQuery, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
{
expect.objectContaining({
clickedCount: 1,
},
}),
]),
},
})
})
it('does not change clickedCount when same user queries the post again', async () => {
await expect(query({ query: postQuery, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
{
expect.objectContaining({
clickedCount: 1,
},
}),
]),
},
})
@ -90,12 +85,12 @@ describe('middleware/userInteractions', () => {
it('changes clickedCount when another user queries the post', async () => {
authenticatedUser = await bUser.toJson()
await expect(query({ query: postQuery, variables })).resolves.toMatchObject({
await expect(query({ query: Post, variables })).resolves.toMatchObject({
data: {
Post: expect.arrayContaining([
{
expect.objectContaining({
clickedCount: 2,
},
}),
]),
},
})

View File

@ -2,11 +2,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import { createTestClient } from 'apollo-server-testing'
import gql from 'graphql-tag'
import Factory, { cleanDatabase } from '@db/factories'
import { getNeode, getDriver } from '@db/neo4j'
import { CreateComment } from '@graphql/queries/CreateComment'
import { fileReport } from '@graphql/queries/fileReport'
import { review } from '@graphql/queries/review'
import { UpdateComment } from '@graphql/queries/UpdateComment'
import { UpdateUser } from '@graphql/queries/UpdateUser'
import createServer from '@src/server'
@ -22,32 +24,6 @@ let authenticatedUser,
moderatingUser,
commentingUser
const createCommentMutation = gql`
mutation ($id: ID, $postId: ID!, $content: String!) {
CreateComment(id: $id, postId: $postId, content: $content) {
id
}
}
`
const updateCommentMutation = gql`
mutation ($content: String!, $id: ID!) {
UpdateComment(content: $content, id: $id) {
id
}
}
`
const reportMutation = gql`
mutation ($resourceId: ID!, $reasonCategory: ReasonCategory!, $reasonDescription: String!) {
fileReport(
resourceId: $resourceId
reasonCategory: $reasonCategory
reasonDescription: $reasonDescription
) {
reportId
}
}
`
beforeAll(async () => {
await cleanDatabase()
@ -135,7 +111,7 @@ describe('validateCreateComment', () => {
it('throws an error if content is empty', async () => {
createCommentVariables = { ...createCommentVariables, postId: 'post-4-commenting' }
await expect(
mutate({ mutation: createCommentMutation, variables: createCommentVariables }),
mutate({ mutation: CreateComment, variables: createCommentVariables }),
).resolves.toMatchObject({
data: { CreateComment: null },
errors: [{ message: 'Comment must be at least 1 character long!' }],
@ -145,7 +121,7 @@ describe('validateCreateComment', () => {
it('sanitizes content and throws an error if not longer than 1 character', async () => {
createCommentVariables = { postId: 'post-4-commenting', content: '<a></a>' }
await expect(
mutate({ mutation: createCommentMutation, variables: createCommentVariables }),
mutate({ mutation: CreateComment, variables: createCommentVariables }),
).resolves.toMatchObject({
data: { CreateComment: null },
errors: [{ message: 'Comment must be at least 1 character long!' }],
@ -159,7 +135,7 @@ describe('validateCreateComment', () => {
content: 'valid content',
}
await expect(
mutate({ mutation: createCommentMutation, variables: createCommentVariables }),
mutate({ mutation: CreateComment, variables: createCommentVariables }),
).resolves.toMatchObject({
data: { CreateComment: null },
errors: [{ message: 'Comment cannot be created without a post!' }],
@ -188,7 +164,7 @@ describe('validateCreateComment', () => {
it('throws an error if content is empty', async () => {
updateCommentVariables = { ...updateCommentVariables, id: 'comment-id' }
await expect(
mutate({ mutation: updateCommentMutation, variables: updateCommentVariables }),
mutate({ mutation: UpdateComment, variables: updateCommentVariables }),
).resolves.toMatchObject({
data: { UpdateComment: null },
errors: [{ message: 'Comment must be at least 1 character long!' }],
@ -198,7 +174,7 @@ describe('validateCreateComment', () => {
it('sanitizes content and throws an error if not longer than 1 character', async () => {
updateCommentVariables = { id: 'comment-id', content: '<a></a>' }
await expect(
mutate({ mutation: updateCommentMutation, variables: updateCommentVariables }),
mutate({ mutation: UpdateComment, variables: updateCommentVariables }),
).resolves.toMatchObject({
data: { UpdateComment: null },
errors: [{ message: 'Comment must be at least 1 character long!' }],
@ -212,7 +188,7 @@ describe('validateReport', () => {
authenticatedUser = await reportingUser.toJson()
reportVariables = { ...reportVariables, resourceId: 'reporting-user' }
await expect(
mutate({ mutation: reportMutation, variables: reportVariables }),
mutate({ mutation: fileReport, variables: reportVariables }),
).resolves.toMatchObject({
data: { fileReport: null },
errors: [{ message: 'You cannot report yourself!' }],