mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge branch 'master' of https://github.com/Human-Connection/Human-Connection into 1062-notification-about-comment-on-post
# Conflicts: # backend/src/middleware/handleNotifications/handleNotificationsMiddleware.spec.js Refactored there tests a little
This commit is contained in:
commit
04fe6b0a8c
@ -56,7 +56,7 @@
|
|||||||
"cheerio": "~1.0.0-rc.3",
|
"cheerio": "~1.0.0-rc.3",
|
||||||
"cors": "~2.8.5",
|
"cors": "~2.8.5",
|
||||||
"cross-env": "~5.2.0",
|
"cross-env": "~5.2.0",
|
||||||
"date-fns": "2.0.0-beta.5",
|
"date-fns": "2.0.0",
|
||||||
"debug": "~4.1.1",
|
"debug": "~4.1.1",
|
||||||
"dotenv": "~8.1.0",
|
"dotenv": "~8.1.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
@ -110,7 +110,7 @@
|
|||||||
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
"@babel/plugin-proposal-throw-expressions": "^7.2.0",
|
||||||
"@babel/preset-env": "~7.5.5",
|
"@babel/preset-env": "~7.5.5",
|
||||||
"@babel/register": "~7.5.5",
|
"@babel/register": "~7.5.5",
|
||||||
"apollo-server-testing": "~2.8.1",
|
"apollo-server-testing": "~2.8.2",
|
||||||
"babel-core": "~7.0.0-0",
|
"babel-core": "~7.0.0-0",
|
||||||
"babel-eslint": "~10.0.2",
|
"babel-eslint": "~10.0.2",
|
||||||
"babel-jest": "~24.9.0",
|
"babel-jest": "~24.9.0",
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import { host, login } from '../../jest/helpers'
|
import { host, login } from '../../jest/helpers'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
|
||||||
const currentUserParams = {
|
const currentUserParams = {
|
||||||
id: 'u1',
|
id: 'u1',
|
||||||
@ -21,6 +23,7 @@ const randomAuthorParams = {
|
|||||||
name: 'Someone else',
|
name: 'Someone else',
|
||||||
password: 'else',
|
password: 'else',
|
||||||
}
|
}
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -28,14 +31,19 @@ beforeEach(async () => {
|
|||||||
factory.create('User', followedAuthorParams),
|
factory.create('User', followedAuthorParams),
|
||||||
factory.create('User', randomAuthorParams),
|
factory.create('User', randomAuthorParams),
|
||||||
])
|
])
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
const [asYourself, asFollowedUser, asSomeoneElse] = await Promise.all([
|
const [asYourself, asFollowedUser, asSomeoneElse] = await Promise.all([
|
||||||
Factory().authenticateAs(currentUserParams),
|
Factory().authenticateAs(currentUserParams),
|
||||||
Factory().authenticateAs(followedAuthorParams),
|
Factory().authenticateAs(followedAuthorParams),
|
||||||
Factory().authenticateAs(randomAuthorParams),
|
Factory().authenticateAs(randomAuthorParams),
|
||||||
])
|
])
|
||||||
await asYourself.follow({ id: 'u2', type: 'User' })
|
await asYourself.follow({ id: 'u2', type: 'User' })
|
||||||
await asFollowedUser.create('Post', { title: 'This is the post of a followed user' })
|
await asFollowedUser.create('Post', { title: 'This is the post of a followed user', categoryIds })
|
||||||
await asSomeoneElse.create('Post', { title: 'This is some random post' })
|
await asSomeoneElse.create('Post', { title: 'This is some random post', categoryIds })
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
|
|||||||
@ -1,17 +1,50 @@
|
|||||||
import { gql } from '../../jest/helpers'
|
import {
|
||||||
|
gql
|
||||||
|
} from '../../jest/helpers'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { createTestClient } from 'apollo-server-testing'
|
import {
|
||||||
import { neode, getDriver } from '../../bootstrap/neo4j'
|
createTestClient
|
||||||
|
} from 'apollo-server-testing'
|
||||||
|
import {
|
||||||
|
neode,
|
||||||
|
getDriver
|
||||||
|
} from '../../bootstrap/neo4j'
|
||||||
import createServer from '../../server'
|
import createServer from '../../server'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
const driver = getDriver()
|
|
||||||
const instance = neode()
|
|
||||||
let server
|
let server
|
||||||
let query
|
let query
|
||||||
let mutate
|
let mutate
|
||||||
let user
|
let notifiedUser
|
||||||
let authenticatedUser
|
let authenticatedUser
|
||||||
|
const factory = Factory()
|
||||||
|
const driver = getDriver()
|
||||||
|
const instance = neode()
|
||||||
|
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 updatePostMutation = gql `
|
||||||
|
mutation($id: ID!, $title: String!, $postContent: String!, $categoryIds: [ID]!) {
|
||||||
|
UpdatePost(id: $id, content: $postContent, title: $title, categoryIds: $categoryIds) {
|
||||||
|
title
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const createCommentMutation = gql `
|
||||||
|
mutation($id: ID, $postId: ID!, $commentContent: String!) {
|
||||||
|
CreateComment(id: $id, postId: $postId, content: $commentContent) {
|
||||||
|
id
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
const createServerResult = createServer({
|
const createServerResult = createServer({
|
||||||
@ -30,13 +63,18 @@ beforeAll(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await instance.create('User', {
|
notifiedUser = await instance.create('User', {
|
||||||
id: 'you',
|
id: 'you',
|
||||||
name: 'Al Capone',
|
name: 'Al Capone',
|
||||||
slug: 'al-capone',
|
slug: 'al-capone',
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
})
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -44,7 +82,7 @@ afterEach(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('notifications', () => {
|
describe('notifications', () => {
|
||||||
const notificationQuery = gql`
|
const notificationQuery = gql `
|
||||||
query($read: Boolean) {
|
query($read: Boolean) {
|
||||||
currentUser {
|
currentUser {
|
||||||
notifications(read: $read, orderBy: createdAt_desc) {
|
notifications(read: $read, orderBy: createdAt_desc) {
|
||||||
@ -63,47 +101,31 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await notifiedUser.toJson()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('given another user', () => {
|
describe('given another user', () => {
|
||||||
let postTitle
|
let title
|
||||||
let postContent
|
let postContent
|
||||||
let postAuthor
|
let postAuthor
|
||||||
const createPostAction = async () => {
|
const createPostAction = async () => {
|
||||||
const createPostMutation = gql`
|
|
||||||
mutation($id: ID, $postTitle: String!, $postContent: String!) {
|
|
||||||
CreatePost(id: $id, title: $postTitle, content: $postContent) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createPostMutation,
|
mutation: createPostMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p47',
|
id: 'p47',
|
||||||
postTitle,
|
title,
|
||||||
postContent,
|
postContent,
|
||||||
|
categoryIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await notifiedUser.toJson()
|
||||||
}
|
}
|
||||||
|
|
||||||
let commentContent
|
let commentContent
|
||||||
let commentAuthor
|
let commentAuthor
|
||||||
const createCommentOnPostAction = async () => {
|
const createCommentOnPostAction = async () => {
|
||||||
await createPostAction()
|
await createPostAction()
|
||||||
const createCommentMutation = gql`
|
|
||||||
mutation($id: ID, $postId: ID!, $commentContent: String!) {
|
|
||||||
CreateComment(id: $id, postId: $postId, content: $commentContent) {
|
|
||||||
id
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
authenticatedUser = await commentAuthor.toJson()
|
authenticatedUser = await commentAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: createCommentMutation,
|
mutation: createCommentMutation,
|
||||||
@ -113,14 +135,14 @@ describe('notifications', () => {
|
|||||||
commentContent,
|
commentContent,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await notifiedUser.toJson()
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('comments on my post', () => {
|
describe('comments on my post', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
postTitle = 'My post'
|
title = 'My post'
|
||||||
postContent = 'My post content.'
|
postContent = 'My post content.'
|
||||||
postAuthor = user
|
postAuthor = notifiedUser
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('commenter is not me', () => {
|
describe('commenter is not me', () => {
|
||||||
@ -140,20 +162,20 @@ describe('notifications', () => {
|
|||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
notifications: [
|
notifications: [{
|
||||||
{
|
read: false,
|
||||||
read: false,
|
reason: 'comment_on_post',
|
||||||
reason: 'comment_on_post',
|
post: null,
|
||||||
post: null,
|
comment: {
|
||||||
comment: {
|
content: commentContent,
|
||||||
content: commentContent,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
}, ],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -164,8 +186,8 @@ describe('notifications', () => {
|
|||||||
).resolves.toEqual(expected)
|
).resolves.toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends me no notification if I block the comment author', async () => {
|
it('sends me no notification if I have blocked the comment author', async () => {
|
||||||
await user.relateTo(commentAuthor, 'blocked')
|
await notifiedUser.relateTo(commentAuthor, 'blocked')
|
||||||
await createCommentOnPostAction()
|
await createCommentOnPostAction()
|
||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
@ -174,7 +196,9 @@ describe('notifications', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -189,11 +213,11 @@ describe('notifications', () => {
|
|||||||
describe('commenter is me', () => {
|
describe('commenter is me', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
commentContent = 'My comment.'
|
commentContent = 'My comment.'
|
||||||
commentAuthor = user
|
commentAuthor = notifiedUser
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends me no notification', async () => {
|
it('sends me no notification', async () => {
|
||||||
await user.relateTo(commentAuthor, 'blocked')
|
await notifiedUser.relateTo(commentAuthor, 'blocked')
|
||||||
await createCommentOnPostAction()
|
await createCommentOnPostAction()
|
||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
@ -202,7 +226,9 @@ describe('notifications', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -227,7 +253,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('mentions me in a post', () => {
|
describe('mentions me in a post', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
postTitle = 'Mentioning Al Capone'
|
title = 'Mentioning Al Capone'
|
||||||
postContent =
|
postContent =
|
||||||
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone">@al-capone</a> how do you do?'
|
'Hey <a class="mention" data-mention-id="you" href="/profile/you/al-capone">@al-capone</a> how do you do?'
|
||||||
})
|
})
|
||||||
@ -239,20 +265,20 @@ describe('notifications', () => {
|
|||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
notifications: [
|
notifications: [{
|
||||||
{
|
read: false,
|
||||||
read: false,
|
reason: 'mentioned_in_post',
|
||||||
reason: 'mentioned_in_post',
|
post: {
|
||||||
post: {
|
content: expectedContent,
|
||||||
content: expectedContent,
|
|
||||||
},
|
|
||||||
comment: null,
|
|
||||||
},
|
},
|
||||||
],
|
comment: null,
|
||||||
|
}, ],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -263,7 +289,7 @@ describe('notifications', () => {
|
|||||||
).resolves.toEqual(expected)
|
).resolves.toEqual(expected)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('who mentions me many times', () => {
|
describe('many times', () => {
|
||||||
const updatePostAction = async () => {
|
const updatePostAction = async () => {
|
||||||
const updatedContent = `
|
const updatedContent = `
|
||||||
One more mention to
|
One more mention to
|
||||||
@ -279,24 +305,17 @@ describe('notifications', () => {
|
|||||||
@al-capone
|
@al-capone
|
||||||
</a>
|
</a>
|
||||||
`
|
`
|
||||||
const updatePostMutation = gql`
|
|
||||||
mutation($id: ID!, $postTitle: String!, $postContent: String!) {
|
|
||||||
UpdatePost(id: $id, content: $postContent, title: $postTitle) {
|
|
||||||
title
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
authenticatedUser = await postAuthor.toJson()
|
authenticatedUser = await postAuthor.toJson()
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: updatePostMutation,
|
mutation: updatePostMutation,
|
||||||
variables: {
|
variables: {
|
||||||
id: 'p47',
|
id: 'p47',
|
||||||
postTitle,
|
title,
|
||||||
postContent: updatedContent,
|
postContent: updatedContent,
|
||||||
|
categoryIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await notifiedUser.toJson()
|
||||||
}
|
}
|
||||||
|
|
||||||
it('creates exactly one more notification', async () => {
|
it('creates exactly one more notification', async () => {
|
||||||
@ -307,8 +326,7 @@ describe('notifications', () => {
|
|||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
notifications: [
|
notifications: [{
|
||||||
{
|
|
||||||
read: false,
|
read: false,
|
||||||
reason: 'mentioned_in_post',
|
reason: 'mentioned_in_post',
|
||||||
post: {
|
post: {
|
||||||
@ -341,7 +359,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('but the author of the post blocked me', () => {
|
describe('but the author of the post blocked me', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await postAuthor.relateTo(user, 'blocked')
|
await postAuthor.relateTo(notifiedUser, 'blocked')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends no notification', async () => {
|
it('sends no notification', async () => {
|
||||||
@ -353,7 +371,9 @@ describe('notifications', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -368,7 +388,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('mentions me in a comment', () => {
|
describe('mentions me in a comment', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
postTitle = 'Post where I get mentioned in a comment'
|
title = 'Post where I get mentioned in a comment'
|
||||||
postContent = 'Content of post where I get mentioned in a comment.'
|
postContent = 'Content of post where I get mentioned in a comment.'
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -390,20 +410,20 @@ describe('notifications', () => {
|
|||||||
const expected = expect.objectContaining({
|
const expected = expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
notifications: [
|
notifications: [{
|
||||||
{
|
read: false,
|
||||||
read: false,
|
reason: 'mentioned_in_comment',
|
||||||
reason: 'mentioned_in_comment',
|
post: null,
|
||||||
post: null,
|
comment: {
|
||||||
comment: {
|
content: commentContent,
|
||||||
content: commentContent,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
],
|
}, ],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -417,7 +437,7 @@ describe('notifications', () => {
|
|||||||
|
|
||||||
describe('but the author of the post blocked me', () => {
|
describe('but the author of the post blocked me', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await postAuthor.relateTo(user, 'blocked')
|
await postAuthor.relateTo(notifiedUser, 'blocked')
|
||||||
commentContent =
|
commentContent =
|
||||||
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
'One mention about me with <a data-mention-id="you" class="mention" href="/profile/you" target="_blank">@al-capone</a>.'
|
||||||
commentAuthor = await instance.create('User', {
|
commentAuthor = await instance.create('User', {
|
||||||
@ -438,7 +458,9 @@ describe('notifications', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
const { query } = createTestClient(server)
|
const {
|
||||||
|
query
|
||||||
|
} = createTestClient(server)
|
||||||
await expect(
|
await expect(
|
||||||
query({
|
query({
|
||||||
query: notificationQuery,
|
query: notificationQuery,
|
||||||
@ -455,11 +477,11 @@ describe('notifications', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('Hashtags', () => {
|
describe('Hashtags', () => {
|
||||||
const postId = 'p135'
|
const id = 'p135'
|
||||||
const postTitle = 'Two Hashtags'
|
const title = 'Two Hashtags'
|
||||||
const postContent =
|
const postContent =
|
||||||
'<p>Hey Dude, <a class="hashtag" href="/search/hashtag/Democracy">#Democracy</a> should work equal for everybody!? That seems to be the only way to have equal <a class="hashtag" href="/search/hashtag/Liberty">#Liberty</a> for everyone.</p>'
|
'<p>Hey Dude, <a class="hashtag" href="/search/hashtag/Democracy">#Democracy</a> should work equal for everybody!? That seems to be the only way to have equal <a class="hashtag" href="/search/hashtag/Liberty">#Liberty</a> for everyone.</p>'
|
||||||
const postWithHastagsQuery = gql`
|
const postWithHastagsQuery = gql `
|
||||||
query($id: ID) {
|
query($id: ID) {
|
||||||
Post(id: $id) {
|
Post(id: $id) {
|
||||||
tags {
|
tags {
|
||||||
@ -469,21 +491,12 @@ describe('Hashtags', () => {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
const postWithHastagsVariables = {
|
const postWithHastagsVariables = {
|
||||||
id: postId,
|
id,
|
||||||
}
|
}
|
||||||
const createPostMutation = gql`
|
|
||||||
mutation($postId: ID, $postTitle: String!, $postContent: String!) {
|
|
||||||
CreatePost(id: $postId, title: $postTitle, content: $postContent) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
describe('authenticated', () => {
|
describe('authenticated', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
authenticatedUser = await user.toJson()
|
authenticatedUser = await notifiedUser.toJson()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('create a Post with Hashtags', () => {
|
describe('create a Post with Hashtags', () => {
|
||||||
@ -491,16 +504,16 @@ describe('Hashtags', () => {
|
|||||||
await mutate({
|
await mutate({
|
||||||
mutation: createPostMutation,
|
mutation: createPostMutation,
|
||||||
variables: {
|
variables: {
|
||||||
postId,
|
id,
|
||||||
postTitle,
|
title,
|
||||||
postContent,
|
postContent,
|
||||||
|
categoryIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('both Hashtags are created with the "id" set to their "name"', async () => {
|
it('both Hashtags are created with the "id" set to their "name"', async () => {
|
||||||
const expected = [
|
const expected = [{
|
||||||
{
|
|
||||||
id: 'Democracy',
|
id: 'Democracy',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -515,11 +528,9 @@ describe('Hashtags', () => {
|
|||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
Post: [
|
Post: [{
|
||||||
{
|
tags: expect.arrayContaining(expected),
|
||||||
tags: expect.arrayContaining(expected),
|
}, ],
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@ -527,30 +538,21 @@ describe('Hashtags', () => {
|
|||||||
|
|
||||||
describe('afterwards update the Post by removing a Hashtag, leaving a Hashtag and add a Hashtag', () => {
|
describe('afterwards update the Post by removing a Hashtag, leaving a Hashtag and add a Hashtag', () => {
|
||||||
// The already existing Hashtag has no class at this point.
|
// The already existing Hashtag has no class at this point.
|
||||||
const updatedPostContent =
|
const postContent =
|
||||||
'<p>Hey Dude, <a class="hashtag" href="/search/hashtag/Elections">#Elections</a> should work equal for everybody!? That seems to be the only way to have equal <a href="/search/hashtag/Liberty">#Liberty</a> for everyone.</p>'
|
'<p>Hey Dude, <a class="hashtag" href="/search/hashtag/Elections">#Elections</a> should work equal for everybody!? That seems to be the only way to have equal <a href="/search/hashtag/Liberty">#Liberty</a> for everyone.</p>'
|
||||||
const updatePostMutation = gql`
|
|
||||||
mutation($postId: ID!, $postTitle: String!, $updatedPostContent: String!) {
|
|
||||||
UpdatePost(id: $postId, title: $postTitle, content: $updatedPostContent) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
it('only one previous Hashtag and the new Hashtag exists', async () => {
|
it('only one previous Hashtag and the new Hashtag exists', async () => {
|
||||||
await mutate({
|
await mutate({
|
||||||
mutation: updatePostMutation,
|
mutation: updatePostMutation,
|
||||||
variables: {
|
variables: {
|
||||||
postId,
|
id,
|
||||||
postTitle,
|
title,
|
||||||
updatedPostContent,
|
postContent,
|
||||||
|
categoryIds,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
const expected = [
|
const expected = [{
|
||||||
{
|
|
||||||
id: 'Elections',
|
id: 'Elections',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -565,11 +567,9 @@ describe('Hashtags', () => {
|
|||||||
).resolves.toEqual(
|
).resolves.toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
data: {
|
data: {
|
||||||
Post: [
|
Post: [{
|
||||||
{
|
tags: expect.arrayContaining(expected),
|
||||||
tags: expect.arrayContaining(expected),
|
}, ],
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
@ -577,4 +577,4 @@ describe('Hashtags', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -1,13 +1,25 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../seed/factories'
|
import Factory from '../seed/factories'
|
||||||
import { host, login } from '../jest/helpers'
|
import { host, login, gql } from '../jest/helpers'
|
||||||
import { neode } from '../bootstrap/neo4j'
|
import { neode } from '../bootstrap/neo4j'
|
||||||
|
|
||||||
let authenticatedClient
|
let authenticatedClient
|
||||||
let headers
|
let headers
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
const instance = neode()
|
const instance = neode()
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
const createPostMutation = gql`
|
||||||
|
mutation($title: String!, $content: String!, $categoryIds: [ID]!, $slug: String) {
|
||||||
|
CreatePost(title: $title, content: $content, categoryIds: $categoryIds, slug: $slug) {
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
let createPostVariables = {
|
||||||
|
title: 'I am a brand new post',
|
||||||
|
content: 'Some content',
|
||||||
|
categoryIds,
|
||||||
|
}
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const adminParams = { role: 'admin', email: 'admin@example.org', password: '1234' }
|
const adminParams = { role: 'admin', email: 'admin@example.org', password: '1234' }
|
||||||
await factory.create('User', adminParams)
|
await factory.create('User', adminParams)
|
||||||
@ -15,6 +27,11 @@ beforeEach(async () => {
|
|||||||
email: 'someone@example.org',
|
email: 'someone@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
})
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
// we need to be an admin, otherwise we're not authorized to create a user
|
// we need to be an admin, otherwise we're not authorized to create a user
|
||||||
headers = await login(adminParams)
|
headers = await login(adminParams)
|
||||||
authenticatedClient = new GraphQLClient(host, { headers })
|
authenticatedClient = new GraphQLClient(host, { headers })
|
||||||
@ -27,12 +44,7 @@ afterEach(async () => {
|
|||||||
describe('slugify', () => {
|
describe('slugify', () => {
|
||||||
describe('CreatePost', () => {
|
describe('CreatePost', () => {
|
||||||
it('generates a slug based on title', async () => {
|
it('generates a slug based on title', async () => {
|
||||||
const response = await authenticatedClient.request(`mutation {
|
const response = await authenticatedClient.request(createPostMutation, createPostVariables)
|
||||||
CreatePost(
|
|
||||||
title: "I am a brand new post",
|
|
||||||
content: "Some content"
|
|
||||||
) { slug }
|
|
||||||
}`)
|
|
||||||
expect(response).toEqual({
|
expect(response).toEqual({
|
||||||
CreatePost: { slug: 'i-am-a-brand-new-post' },
|
CreatePost: { slug: 'i-am-a-brand-new-post' },
|
||||||
})
|
})
|
||||||
@ -47,16 +59,14 @@ describe('slugify', () => {
|
|||||||
await asSomeoneElse.create('Post', {
|
await asSomeoneElse.create('Post', {
|
||||||
title: 'Pre-existing post',
|
title: 'Pre-existing post',
|
||||||
slug: 'pre-existing-post',
|
slug: 'pre-existing-post',
|
||||||
|
content: 'as Someone else content',
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('chooses another slug', async () => {
|
it('chooses another slug', async () => {
|
||||||
const response = await authenticatedClient.request(`mutation {
|
createPostVariables = { title: 'Pre-existing post', content: 'Some content', categoryIds }
|
||||||
CreatePost(
|
const response = await authenticatedClient.request(createPostMutation, createPostVariables)
|
||||||
title: "Pre-existing post",
|
|
||||||
content: "Some content"
|
|
||||||
) { slug }
|
|
||||||
}`)
|
|
||||||
expect(response).toEqual({
|
expect(response).toEqual({
|
||||||
CreatePost: { slug: 'pre-existing-post-1' },
|
CreatePost: { slug: 'pre-existing-post-1' },
|
||||||
})
|
})
|
||||||
@ -64,14 +74,14 @@ describe('slugify', () => {
|
|||||||
|
|
||||||
describe('but if the client specifies a slug', () => {
|
describe('but if the client specifies a slug', () => {
|
||||||
it('rejects CreatePost', async () => {
|
it('rejects CreatePost', async () => {
|
||||||
|
createPostVariables = {
|
||||||
|
title: 'Pre-existing post',
|
||||||
|
content: 'Some content',
|
||||||
|
slug: 'pre-existing-post',
|
||||||
|
categoryIds,
|
||||||
|
}
|
||||||
await expect(
|
await expect(
|
||||||
authenticatedClient.request(`mutation {
|
authenticatedClient.request(createPostMutation, createPostVariables),
|
||||||
CreatePost(
|
|
||||||
title: "Pre-existing post",
|
|
||||||
content: "Some content",
|
|
||||||
slug: "pre-existing-post"
|
|
||||||
) { slug }
|
|
||||||
}`),
|
|
||||||
).rejects.toThrow('already exists')
|
).rejects.toThrow('already exists')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,11 +1,15 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../seed/factories'
|
import Factory from '../seed/factories'
|
||||||
import { host, login } from '../jest/helpers'
|
import { host, login } from '../jest/helpers'
|
||||||
|
import { neode } from '../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
|
||||||
let client
|
let client
|
||||||
let query
|
let query
|
||||||
let action
|
let action
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
// For performance reasons we do this only once
|
// For performance reasons we do this only once
|
||||||
@ -26,13 +30,23 @@ beforeAll(async () => {
|
|||||||
email: 'troll@example.org',
|
email: 'troll@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
}),
|
}),
|
||||||
|
instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
await factory.authenticateAs({ email: 'user@example.org', password: '1234' })
|
await factory.authenticateAs({ email: 'user@example.org', password: '1234' })
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
factory.follow({ id: 'u2', type: 'User' }),
|
factory.follow({ id: 'u2', type: 'User' }),
|
||||||
factory.create('Post', { id: 'p1', title: 'Deleted post', deleted: true }),
|
factory.create('Post', { id: 'p1', title: 'Deleted post', deleted: true, categoryIds }),
|
||||||
factory.create('Post', { id: 'p3', title: 'Publicly visible post', deleted: false }),
|
factory.create('Post', {
|
||||||
|
id: 'p3',
|
||||||
|
title: 'Publicly visible post',
|
||||||
|
deleted: false,
|
||||||
|
categoryIds,
|
||||||
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
@ -53,6 +67,7 @@ beforeAll(async () => {
|
|||||||
content: 'This is an offensive post content',
|
content: 'This is an offensive post content',
|
||||||
image: '/some/offensive/image.jpg',
|
image: '/some/offensive/image.jpg',
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
await asTroll.create('Comment', { id: 'c1', postId: 'p3', content: 'Disabled comment' })
|
await asTroll.create('Comment', { id: 'c1', postId: 'p3', content: 'Disabled comment' })
|
||||||
await Promise.all([asTroll.relate('Comment', 'Author', { from: 'u2', to: 'c1' })])
|
await Promise.all([asTroll.relate('Comment', 'Author', { from: 'u2', to: 'c1' })])
|
||||||
|
|||||||
@ -40,9 +40,21 @@ const validateUpdateComment = async (resolve, root, args, context, info) => {
|
|||||||
return resolve(root, args, context, info)
|
return resolve(root, args, context, info)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validatePost = async (resolve, root, args, context, info) => {
|
||||||
|
const { categoryIds } = args
|
||||||
|
if (!Array.isArray(categoryIds) || !categoryIds.length || categoryIds.length > 3) {
|
||||||
|
throw new UserInputError(
|
||||||
|
'You cannot save a post without at least one category or more than three',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return resolve(root, args, context, info)
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
Mutation: {
|
Mutation: {
|
||||||
CreateComment: validateCommentCreation,
|
CreateComment: validateCommentCreation,
|
||||||
UpdateComment: validateUpdateComment,
|
UpdateComment: validateUpdateComment,
|
||||||
|
CreatePost: validatePost,
|
||||||
|
UpdatePost: validatePost,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
21
backend/src/models/Category.js
Normal file
21
backend/src/models/Category.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import uuid from 'uuid/v4'
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
id: { type: 'string', primary: true, default: uuid },
|
||||||
|
name: { type: 'string', required: true, default: false },
|
||||||
|
slug: { type: 'string' },
|
||||||
|
icon: { type: 'string', required: true, default: false },
|
||||||
|
createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
|
||||||
|
updatedAt: {
|
||||||
|
type: 'string',
|
||||||
|
isoDate: true,
|
||||||
|
required: true,
|
||||||
|
default: () => new Date().toISOString(),
|
||||||
|
},
|
||||||
|
post: {
|
||||||
|
type: 'relationship',
|
||||||
|
relationship: 'CATEGORIZED',
|
||||||
|
target: 'Post',
|
||||||
|
direction: 'in',
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -8,4 +8,5 @@ export default {
|
|||||||
SocialMedia: require('./SocialMedia.js'),
|
SocialMedia: require('./SocialMedia.js'),
|
||||||
Post: require('./Post.js'),
|
Post: require('./Post.js'),
|
||||||
Notification: require('./Notification.js'),
|
Notification: require('./Notification.js'),
|
||||||
|
Category: require('./Category.js'),
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login, gql } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
let client
|
let client
|
||||||
let createCommentVariables
|
let createCommentVariables
|
||||||
let createCommentVariablesSansPostId
|
let createCommentVariablesSansPostId
|
||||||
let createCommentVariablesWithNonExistentPost
|
let createCommentVariablesWithNonExistentPost
|
||||||
let userParams
|
let userParams
|
||||||
let headers
|
let headers
|
||||||
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
mutation($id: ID!, $title: String!, $content: String!) {
|
mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) {
|
||||||
CreatePost(id: $id, title: $title, content: $content) {
|
CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,6 +32,7 @@ const createPostVariables = {
|
|||||||
id: 'p1',
|
id: 'p1',
|
||||||
title: 'post to comment on',
|
title: 'post to comment on',
|
||||||
content: 'please comment on me',
|
content: 'please comment on me',
|
||||||
|
categoryIds,
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
@ -38,6 +42,11 @@ beforeEach(async () => {
|
|||||||
password: '1234',
|
password: '1234',
|
||||||
}
|
}
|
||||||
await factory.create('User', userParams)
|
await factory.create('User', userParams)
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -199,6 +208,7 @@ describe('ManageComments', () => {
|
|||||||
await asAuthor.create('Post', {
|
await asAuthor.create('Post', {
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
content: 'Post to be commented',
|
content: 'Post to be commented',
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
await asAuthor.create('Comment', {
|
await asAuthor.create('Comment', {
|
||||||
id: 'c456',
|
id: 'c456',
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
let client
|
let client
|
||||||
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
const setupAuthenticateClient = params => {
|
const setupAuthenticateClient = params => {
|
||||||
const authenticateClient = async () => {
|
const authenticateClient = async () => {
|
||||||
@ -19,11 +22,16 @@ let authenticateClient
|
|||||||
let createPostVariables
|
let createPostVariables
|
||||||
let createCommentVariables
|
let createCommentVariables
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
createResource = () => {}
|
createResource = () => {}
|
||||||
authenticateClient = () => {
|
authenticateClient = () => {
|
||||||
client = new GraphQLClient(host)
|
client = new GraphQLClient(host)
|
||||||
}
|
}
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const setup = async () => {
|
const setup = async () => {
|
||||||
@ -36,7 +44,7 @@ afterEach(async () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('disable', () => {
|
describe('disable', () => {
|
||||||
const mutation = `
|
const mutation = gql`
|
||||||
mutation($id: ID!) {
|
mutation($id: ID!) {
|
||||||
disable(id: $id)
|
disable(id: $id)
|
||||||
}
|
}
|
||||||
@ -108,6 +116,7 @@ describe('disable', () => {
|
|||||||
id: 'p3',
|
id: 'p3',
|
||||||
title: 'post to comment on',
|
title: 'post to comment on',
|
||||||
content: 'please comment on me',
|
content: 'please comment on me',
|
||||||
|
categoryIds,
|
||||||
}
|
}
|
||||||
createCommentVariables = {
|
createCommentVariables = {
|
||||||
id: 'c47',
|
id: 'c47',
|
||||||
@ -173,6 +182,7 @@ describe('disable', () => {
|
|||||||
await factory.authenticateAs({ email: 'author@example.org', password: '1234' })
|
await factory.authenticateAs({ email: 'author@example.org', password: '1234' })
|
||||||
await factory.create('Post', {
|
await factory.create('Post', {
|
||||||
id: 'p9', // that's the ID we will look for
|
id: 'p9', // that's the ID we will look for
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -214,7 +224,7 @@ describe('disable', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('enable', () => {
|
describe('enable', () => {
|
||||||
const mutation = `
|
const mutation = gql`
|
||||||
mutation($id: ID!) {
|
mutation($id: ID!) {
|
||||||
enable(id: $id)
|
enable(id: $id)
|
||||||
}
|
}
|
||||||
@ -286,6 +296,7 @@ describe('enable', () => {
|
|||||||
id: 'p9',
|
id: 'p9',
|
||||||
title: 'post to comment on',
|
title: 'post to comment on',
|
||||||
content: 'please comment on me',
|
content: 'please comment on me',
|
||||||
|
categoryIds,
|
||||||
}
|
}
|
||||||
createCommentVariables = {
|
createCommentVariables = {
|
||||||
id: 'c456',
|
id: 'c456',
|
||||||
@ -305,7 +316,7 @@ describe('enable', () => {
|
|||||||
await asAuthenticatedUser.create('Post', createPostVariables)
|
await asAuthenticatedUser.create('Post', createPostVariables)
|
||||||
await asAuthenticatedUser.create('Comment', createCommentVariables)
|
await asAuthenticatedUser.create('Comment', createCommentVariables)
|
||||||
|
|
||||||
const disableMutation = `
|
const disableMutation = gql`
|
||||||
mutation {
|
mutation {
|
||||||
disable(id: "c456")
|
disable(id: "c456")
|
||||||
}
|
}
|
||||||
@ -362,9 +373,10 @@ describe('enable', () => {
|
|||||||
await factory.authenticateAs({ email: 'author@example.org', password: '1234' })
|
await factory.authenticateAs({ email: 'author@example.org', password: '1234' })
|
||||||
await factory.create('Post', {
|
await factory.create('Post', {
|
||||||
id: 'p9', // that's the ID we will look for
|
id: 'p9', // that's the ID we will look for
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
|
|
||||||
const disableMutation = `
|
const disableMutation = gql`
|
||||||
mutation {
|
mutation {
|
||||||
disable(id: "p9")
|
disable(id: "p9")
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,26 +1,34 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login, gql } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
let client
|
let client
|
||||||
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
const userParams = {
|
const userParams = {
|
||||||
id: 'you',
|
id: 'you',
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
}
|
}
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await factory.create('User', userParams)
|
await factory.create('User', userParams)
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await factory.cleanDatabase()
|
await factory.cleanDatabase()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('query for notification', () => {
|
describe('Notification', () => {
|
||||||
const notificationQuery = gql`
|
const notificationQuery = gql`
|
||||||
{
|
query {
|
||||||
Notification {
|
Notification {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@ -87,12 +95,7 @@ describe('currentUser notifications', () => {
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
await factory.authenticateAs(neighborParams)
|
await factory.authenticateAs(neighborParams)
|
||||||
// Post and its notifications
|
await factory.create('Post', { id: 'p1', categoryIds })
|
||||||
await Promise.all([
|
|
||||||
factory.create('Post', {
|
|
||||||
id: 'p1',
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
factory.relate('Notification', 'User', {
|
factory.relate('Notification', 'User', {
|
||||||
from: 'post-mention-not-for-you',
|
from: 'post-mention-not-for-you',
|
||||||
@ -170,9 +173,7 @@ describe('currentUser notifications', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const variables = {
|
const variables = { read: false }
|
||||||
read: false,
|
|
||||||
}
|
|
||||||
it('returns only unread notifications of current user', async () => {
|
it('returns only unread notifications of current user', async () => {
|
||||||
const expected = {
|
const expected = {
|
||||||
currentUser: {
|
currentUser: {
|
||||||
@ -202,7 +203,7 @@ describe('currentUser notifications', () => {
|
|||||||
|
|
||||||
describe('no filters', () => {
|
describe('no filters', () => {
|
||||||
const queryCurrentUserNotifications = gql`
|
const queryCurrentUserNotifications = gql`
|
||||||
{
|
query {
|
||||||
currentUser {
|
currentUser {
|
||||||
notifications(orderBy: createdAt_desc) {
|
notifications(orderBy: createdAt_desc) {
|
||||||
id
|
id
|
||||||
@ -300,12 +301,7 @@ describe('UpdateNotification', () => {
|
|||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
await factory.authenticateAs(userParams)
|
await factory.authenticateAs(userParams)
|
||||||
// Post and its notifications
|
await factory.create('Post', { id: 'p1', categoryIds })
|
||||||
await Promise.all([
|
|
||||||
factory.create('Post', {
|
|
||||||
id: 'p1',
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
factory.relate('Notification', 'User', {
|
factory.relate('Notification', 'User', {
|
||||||
from: 'post-mention-to-be-updated',
|
from: 'post-mention-to-be-updated',
|
||||||
|
|||||||
@ -83,17 +83,14 @@ export default {
|
|||||||
|
|
||||||
await session.run(cypherDeletePreviousRelations, { params })
|
await session.run(cypherDeletePreviousRelations, { params })
|
||||||
|
|
||||||
let updatePostCypher = `MATCH (post:Post {id: $params.id})
|
const updatePostCypher = `MATCH (post:Post {id: $params.id})
|
||||||
SET post = $params
|
SET post = $params
|
||||||
`
|
WITH post
|
||||||
if (categoryIds && categoryIds.length) {
|
|
||||||
updatePostCypher += `WITH post
|
|
||||||
UNWIND $categoryIds AS categoryId
|
UNWIND $categoryIds AS categoryId
|
||||||
MATCH (category:Category {id: categoryId})
|
MATCH (category:Category {id: categoryId})
|
||||||
MERGE (post)-[:CATEGORIZED]->(category)
|
MERGE (post)-[:CATEGORIZED]->(category)
|
||||||
`
|
RETURN post`
|
||||||
}
|
|
||||||
updatePostCypher += `RETURN post`
|
|
||||||
const updatePostVariables = { categoryIds, params }
|
const updatePostVariables = { categoryIds, params }
|
||||||
|
|
||||||
const transactionRes = await session.run(updatePostCypher, updatePostVariables)
|
const transactionRes = await session.run(updatePostCypher, updatePostVariables)
|
||||||
@ -112,19 +109,16 @@ export default {
|
|||||||
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
|
params = await fileUpload(params, { file: 'imageUpload', url: 'image' })
|
||||||
params.id = params.id || uuid()
|
params.id = params.id || uuid()
|
||||||
|
|
||||||
let createPostCypher = `CREATE (post:Post {params})
|
const createPostCypher = `CREATE (post:Post {params})
|
||||||
WITH post
|
WITH post
|
||||||
MATCH (author:User {id: $userId})
|
MATCH (author:User {id: $userId})
|
||||||
MERGE (post)<-[:WROTE]-(author)
|
MERGE (post)<-[:WROTE]-(author)
|
||||||
`
|
WITH post
|
||||||
if (categoryIds) {
|
|
||||||
createPostCypher += `WITH post
|
|
||||||
UNWIND $categoryIds AS categoryId
|
UNWIND $categoryIds AS categoryId
|
||||||
MATCH (category:Category {id: categoryId})
|
MATCH (category:Category {id: categoryId})
|
||||||
MERGE (post)-[:CATEGORIZED]->(category)
|
MERGE (post)-[:CATEGORIZED]->(category)
|
||||||
`
|
RETURN post`
|
||||||
}
|
|
||||||
createPostCypher += `RETURN post`
|
|
||||||
const createPostVariables = { userId: context.user.id, categoryIds, params }
|
const createPostVariables = { userId: context.user.id, categoryIds, params }
|
||||||
|
|
||||||
const session = context.driver.session()
|
const session = context.driver.session()
|
||||||
|
|||||||
@ -19,20 +19,10 @@ const oldTitle = 'Old title'
|
|||||||
const oldContent = 'Old content'
|
const oldContent = 'Old content'
|
||||||
const newTitle = 'New title'
|
const newTitle = 'New title'
|
||||||
const newContent = 'New content'
|
const newContent = 'New content'
|
||||||
const createPostVariables = { title: postTitle, content: postContent }
|
const postSaveError = 'You cannot save a post without at least one category or more than three'
|
||||||
const createPostWithCategoriesMutation = gql`
|
const categoryIds = ['cat9', 'cat4', 'cat15']
|
||||||
mutation($title: String!, $content: String!, $categoryIds: [ID]) {
|
let createPostVariables
|
||||||
CreatePost(title: $title, content: $content, categoryIds: $categoryIds) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
const createPostWithCategoriesVariables = {
|
|
||||||
title: postTitle,
|
|
||||||
content: postContent,
|
|
||||||
categoryIds: ['cat9', 'cat4', 'cat15'],
|
|
||||||
}
|
|
||||||
const postQueryWithCategories = gql`
|
const postQueryWithCategories = gql`
|
||||||
query($id: ID) {
|
query($id: ID) {
|
||||||
Post(id: $id) {
|
Post(id: $id) {
|
||||||
@ -42,11 +32,6 @@ const postQueryWithCategories = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const createPostWithoutCategoriesVariables = {
|
|
||||||
title: 'This is a post without categories',
|
|
||||||
content: 'I should be able to filter it out',
|
|
||||||
categoryIds: null,
|
|
||||||
}
|
|
||||||
const postQueryFilteredByCategory = gql`
|
const postQueryFilteredByCategory = gql`
|
||||||
query Post($filter: _PostFilter) {
|
query Post($filter: _PostFilter) {
|
||||||
Post(filter: $filter) {
|
Post(filter: $filter) {
|
||||||
@ -58,14 +43,14 @@ const postQueryFilteredByCategory = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const postCategoriesFilterParam = { categories_some: { id_in: ['cat4'] } }
|
const postCategoriesFilterParam = { categories_some: { id_in: categoryIds } }
|
||||||
const postQueryFilteredByCategoryVariables = {
|
const postQueryFilteredByCategoryVariables = {
|
||||||
filter: postCategoriesFilterParam,
|
filter: postCategoriesFilterParam,
|
||||||
}
|
}
|
||||||
|
|
||||||
const createPostMutation = gql`
|
const createPostMutation = gql`
|
||||||
mutation($title: String!, $content: String!) {
|
mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]) {
|
||||||
CreatePost(title: $title, content: $content) {
|
CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
content
|
content
|
||||||
@ -88,6 +73,34 @@ beforeEach(async () => {
|
|||||||
password: '1234',
|
password: '1234',
|
||||||
}
|
}
|
||||||
await factory.create('User', userParams)
|
await factory.create('User', userParams)
|
||||||
|
await Promise.all([
|
||||||
|
instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
}),
|
||||||
|
instance.create('Category', {
|
||||||
|
id: 'cat4',
|
||||||
|
name: 'Environment & Nature',
|
||||||
|
icon: 'tree',
|
||||||
|
}),
|
||||||
|
instance.create('Category', {
|
||||||
|
id: 'cat15',
|
||||||
|
name: 'Consumption & Sustainability',
|
||||||
|
icon: 'shopping-cart',
|
||||||
|
}),
|
||||||
|
instance.create('Category', {
|
||||||
|
id: 'cat27',
|
||||||
|
name: 'Animal Protection',
|
||||||
|
icon: 'paw',
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
createPostVariables = {
|
||||||
|
id: 'p3589',
|
||||||
|
title: postTitle,
|
||||||
|
content: postContent,
|
||||||
|
categoryIds,
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -152,8 +165,13 @@ describe('CreatePost', () => {
|
|||||||
describe('language', () => {
|
describe('language', () => {
|
||||||
it('allows a user to set the language of the post', async () => {
|
it('allows a user to set the language of the post', async () => {
|
||||||
const createPostWithLanguageMutation = gql`
|
const createPostWithLanguageMutation = gql`
|
||||||
mutation($title: String!, $content: String!, $language: String) {
|
mutation($title: String!, $content: String!, $language: String, $categoryIds: [ID]) {
|
||||||
CreatePost(title: $title, content: $content, language: $language) {
|
CreatePost(
|
||||||
|
title: $title
|
||||||
|
content: $content
|
||||||
|
language: $language
|
||||||
|
categoryIds: $categoryIds
|
||||||
|
) {
|
||||||
language
|
language
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,6 +180,7 @@ describe('CreatePost', () => {
|
|||||||
title: postTitle,
|
title: postTitle,
|
||||||
content: postContent,
|
content: postContent,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
categoryIds,
|
||||||
}
|
}
|
||||||
const expected = { CreatePost: { language: 'en' } }
|
const expected = { CreatePost: { language: 'en' } }
|
||||||
await expect(
|
await expect(
|
||||||
@ -171,51 +190,36 @@ describe('CreatePost', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
let postWithCategories
|
it('throws an error if categoryIds is not an array', async () => {
|
||||||
beforeEach(async () => {
|
createPostVariables.categoryIds = null
|
||||||
await Promise.all([
|
await expect(client.request(createPostMutation, createPostVariables)).rejects.toThrow(
|
||||||
factory.create('Category', {
|
postSaveError,
|
||||||
id: 'cat9',
|
|
||||||
name: 'Democracy & Politics',
|
|
||||||
icon: 'university',
|
|
||||||
}),
|
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat4',
|
|
||||||
name: 'Environment & Nature',
|
|
||||||
icon: 'tree',
|
|
||||||
}),
|
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat15',
|
|
||||||
name: 'Consumption & Sustainability',
|
|
||||||
icon: 'shopping-cart',
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
postWithCategories = await client.request(
|
|
||||||
createPostWithCategoriesMutation,
|
|
||||||
createPostWithCategoriesVariables,
|
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows a user to set the categories of the post', async () => {
|
it('requires at least one category for successful creation', async () => {
|
||||||
const expected = [{ id: 'cat9' }, { id: 'cat4' }, { id: 'cat15' }]
|
createPostVariables.categoryIds = []
|
||||||
const postQueryWithCategoriesVariables = {
|
await expect(client.request(createPostMutation, createPostVariables)).rejects.toThrow(
|
||||||
id: postWithCategories.CreatePost.id,
|
postSaveError,
|
||||||
}
|
)
|
||||||
|
})
|
||||||
|
|
||||||
await expect(
|
it('allows a maximum of three category for successful update', async () => {
|
||||||
client.request(postQueryWithCategories, postQueryWithCategoriesVariables),
|
createPostVariables.categoryIds = ['cat9', 'cat27', 'cat15', 'cat4']
|
||||||
).resolves.toEqual({ Post: [{ categories: expect.arrayContaining(expected) }] })
|
await expect(client.request(createPostMutation, createPostVariables)).rejects.toThrow(
|
||||||
|
postSaveError,
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('allows a user to filter for posts by category', async () => {
|
it('allows a user to filter for posts by category', async () => {
|
||||||
await client.request(createPostWithCategoriesMutation, createPostWithoutCategoriesVariables)
|
await client.request(createPostMutation, createPostVariables)
|
||||||
const categoryIds = [{ id: 'cat4' }, { id: 'cat15' }, { id: 'cat9' }]
|
const categoryIdsArray = [{ id: 'cat4' }, { id: 'cat15' }, { id: 'cat9' }]
|
||||||
const expected = {
|
const expected = {
|
||||||
Post: [
|
Post: [
|
||||||
{
|
{
|
||||||
title: postTitle,
|
title: postTitle,
|
||||||
id: postWithCategories.CreatePost.id,
|
id: 'p3589',
|
||||||
categories: expect.arrayContaining(categoryIds),
|
categories: expect.arrayContaining(categoryIdsArray),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
@ -228,8 +232,15 @@ describe('CreatePost', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('UpdatePost', () => {
|
describe('UpdatePost', () => {
|
||||||
let updatePostMutation
|
|
||||||
let updatePostVariables
|
let updatePostVariables
|
||||||
|
const updatePostMutation = gql`
|
||||||
|
mutation($id: ID!, $title: String!, $content: String!, $categoryIds: [ID]) {
|
||||||
|
UpdatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
||||||
|
id
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
const asAuthor = Factory()
|
const asAuthor = Factory()
|
||||||
await asAuthor.create('User', authorParams)
|
await asAuthor.create('User', authorParams)
|
||||||
@ -238,15 +249,8 @@ describe('UpdatePost', () => {
|
|||||||
id: 'p1',
|
id: 'p1',
|
||||||
title: oldTitle,
|
title: oldTitle,
|
||||||
content: oldContent,
|
content: oldContent,
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
updatePostMutation = gql`
|
|
||||||
mutation($id: ID!, $title: String!, $content: String!, $categoryIds: [ID]) {
|
|
||||||
UpdatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
|
||||||
id
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
updatePostVariables = {
|
updatePostVariables = {
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
@ -287,6 +291,7 @@ describe('UpdatePost', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('updates a post', async () => {
|
it('updates a post', async () => {
|
||||||
|
updatePostVariables.categoryIds = ['cat9']
|
||||||
const expected = { UpdatePost: { id: 'p1', content: newContent } }
|
const expected = { UpdatePost: { id: 'p1', content: newContent } }
|
||||||
await expect(client.request(updatePostMutation, updatePostVariables)).resolves.toEqual(
|
await expect(client.request(updatePostMutation, updatePostVariables)).resolves.toEqual(
|
||||||
expected,
|
expected,
|
||||||
@ -294,36 +299,10 @@ describe('UpdatePost', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
describe('categories', () => {
|
describe('categories', () => {
|
||||||
let postWithCategories
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await Promise.all([
|
await client.request(createPostMutation, createPostVariables)
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat9',
|
|
||||||
name: 'Democracy & Politics',
|
|
||||||
icon: 'university',
|
|
||||||
}),
|
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat4',
|
|
||||||
name: 'Environment & Nature',
|
|
||||||
icon: 'tree',
|
|
||||||
}),
|
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat15',
|
|
||||||
name: 'Consumption & Sustainability',
|
|
||||||
icon: 'shopping-cart',
|
|
||||||
}),
|
|
||||||
factory.create('Category', {
|
|
||||||
id: 'cat27',
|
|
||||||
name: 'Animal Protection',
|
|
||||||
icon: 'paw',
|
|
||||||
}),
|
|
||||||
])
|
|
||||||
postWithCategories = await client.request(
|
|
||||||
createPostWithCategoriesMutation,
|
|
||||||
createPostWithCategoriesVariables,
|
|
||||||
)
|
|
||||||
updatePostVariables = {
|
updatePostVariables = {
|
||||||
id: postWithCategories.CreatePost.id,
|
id: 'p3589',
|
||||||
title: newTitle,
|
title: newTitle,
|
||||||
content: newContent,
|
content: newContent,
|
||||||
categoryIds: ['cat27'],
|
categoryIds: ['cat27'],
|
||||||
@ -334,12 +313,33 @@ describe('UpdatePost', () => {
|
|||||||
await client.request(updatePostMutation, updatePostVariables)
|
await client.request(updatePostMutation, updatePostVariables)
|
||||||
const expected = [{ id: 'cat27' }]
|
const expected = [{ id: 'cat27' }]
|
||||||
const postQueryWithCategoriesVariables = {
|
const postQueryWithCategoriesVariables = {
|
||||||
id: postWithCategories.CreatePost.id,
|
id: 'p3589',
|
||||||
}
|
}
|
||||||
await expect(
|
await expect(
|
||||||
client.request(postQueryWithCategories, postQueryWithCategoriesVariables),
|
client.request(postQueryWithCategories, postQueryWithCategoriesVariables),
|
||||||
).resolves.toEqual({ Post: [{ categories: expect.arrayContaining(expected) }] })
|
).resolves.toEqual({ Post: [{ categories: expect.arrayContaining(expected) }] })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('throws an error if categoryIds is not an array', async () => {
|
||||||
|
updatePostVariables.categoryIds = null
|
||||||
|
await expect(client.request(updatePostMutation, updatePostVariables)).rejects.toThrow(
|
||||||
|
postSaveError,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('requires at least one category for successful update', async () => {
|
||||||
|
updatePostVariables.categoryIds = []
|
||||||
|
await expect(client.request(updatePostMutation, updatePostVariables)).rejects.toThrow(
|
||||||
|
postSaveError,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('allows a maximum of three category for a successful update', async () => {
|
||||||
|
updatePostVariables.categoryIds = ['cat9', 'cat27', 'cat15', 'cat4']
|
||||||
|
await expect(client.request(updatePostMutation, updatePostVariables)).rejects.toThrow(
|
||||||
|
postSaveError,
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -365,6 +365,7 @@ describe('DeletePost', () => {
|
|||||||
await asAuthor.create('Post', {
|
await asAuthor.create('Post', {
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
content: 'To be deleted',
|
content: 'To be deleted',
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -411,7 +412,7 @@ describe('emotions', () => {
|
|||||||
postQueryAction,
|
postQueryAction,
|
||||||
postToEmote,
|
postToEmote,
|
||||||
postToEmoteNode
|
postToEmoteNode
|
||||||
const PostsEmotionsCountQuery = `
|
const PostsEmotionsCountQuery = gql`
|
||||||
query($id: ID!) {
|
query($id: ID!) {
|
||||||
Post(id: $id) {
|
Post(id: $id) {
|
||||||
emotionsCount
|
emotionsCount
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login } from '../../jest/helpers'
|
import { host, login } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
|
||||||
describe('report', () => {
|
describe('report', () => {
|
||||||
let mutation
|
let mutation
|
||||||
@ -10,6 +12,7 @@ describe('report', () => {
|
|||||||
let returnedObject
|
let returnedObject
|
||||||
let variables
|
let variables
|
||||||
let createPostVariables
|
let createPostVariables
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
returnedObject = '{ description }'
|
returnedObject = '{ description }'
|
||||||
@ -28,6 +31,11 @@ describe('report', () => {
|
|||||||
role: 'user',
|
role: 'user',
|
||||||
email: 'abusive-user@example.org',
|
email: 'abusive-user@example.org',
|
||||||
})
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -126,6 +134,7 @@ describe('report', () => {
|
|||||||
await factory.create('Post', {
|
await factory.create('Post', {
|
||||||
id: 'p23',
|
id: 'p23',
|
||||||
title: 'Matt and Robert having a pair-programming',
|
title: 'Matt and Robert having a pair-programming',
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
variables = {
|
variables = {
|
||||||
id: 'p23',
|
id: 'p23',
|
||||||
@ -171,6 +180,7 @@ describe('report', () => {
|
|||||||
id: 'p1',
|
id: 'p1',
|
||||||
title: 'post to comment on',
|
title: 'post to comment on',
|
||||||
content: 'please comment on me',
|
content: 'please comment on me',
|
||||||
|
categoryIds,
|
||||||
}
|
}
|
||||||
const asAuthenticatedUser = await factory.authenticateAs({
|
const asAuthenticatedUser = await factory.authenticateAs({
|
||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
|
|||||||
@ -1,22 +1,39 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
let clientUser1, clientUser2
|
let clientUser1, clientUser2
|
||||||
let headersUser1, headersUser2
|
let headersUser1, headersUser2
|
||||||
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
const mutationShoutPost = id => `
|
const mutationShoutPost = gql`
|
||||||
mutation {
|
mutation($id: ID!) {
|
||||||
shout(id: "${id}", type: Post)
|
shout(id: $id, type: Post)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
const mutationUnshoutPost = id => `
|
const mutationUnshoutPost = gql`
|
||||||
mutation {
|
mutation($id: ID!) {
|
||||||
unshout(id: "${id}", type: Post)
|
unshout(id: $id, type: Post)
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
const createPostMutation = gql`
|
||||||
|
mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) {
|
||||||
|
CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
const createPostVariables = {
|
||||||
|
id: 'p1234',
|
||||||
|
title: 'Post Title 1234',
|
||||||
|
content: 'Some Post Content 1234',
|
||||||
|
categoryIds,
|
||||||
|
}
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await factory.create('User', {
|
await factory.create('User', {
|
||||||
id: 'u1',
|
id: 'u1',
|
||||||
@ -28,28 +45,23 @@ beforeEach(async () => {
|
|||||||
email: 'test2@example.org',
|
email: 'test2@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
})
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
headersUser1 = await login({ email: 'test@example.org', password: '1234' })
|
headersUser1 = await login({ email: 'test@example.org', password: '1234' })
|
||||||
headersUser2 = await login({ email: 'test2@example.org', password: '1234' })
|
headersUser2 = await login({ email: 'test2@example.org', password: '1234' })
|
||||||
clientUser1 = new GraphQLClient(host, { headers: headersUser1 })
|
clientUser1 = new GraphQLClient(host, { headers: headersUser1 })
|
||||||
clientUser2 = new GraphQLClient(host, { headers: headersUser2 })
|
clientUser2 = new GraphQLClient(host, { headers: headersUser2 })
|
||||||
|
|
||||||
await clientUser1.request(`
|
await clientUser1.request(createPostMutation, createPostVariables)
|
||||||
mutation {
|
await clientUser2.request(createPostMutation, {
|
||||||
CreatePost(id: "p1", title: "Post Title 1", content: "Some Post Content 1") {
|
id: 'p12345',
|
||||||
id
|
title: 'Post Title 12345',
|
||||||
title
|
content: 'Some Post Content 12345',
|
||||||
}
|
categoryIds,
|
||||||
}
|
})
|
||||||
`)
|
|
||||||
await clientUser2.request(`
|
|
||||||
mutation {
|
|
||||||
CreatePost(id: "p2", title: "Post Title 2", content: "Some Post Content 2") {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
@ -61,22 +73,26 @@ describe('shout', () => {
|
|||||||
describe('unauthenticated shout', () => {
|
describe('unauthenticated shout', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
const client = new GraphQLClient(host)
|
const client = new GraphQLClient(host)
|
||||||
await expect(client.request(mutationShoutPost('p1'))).rejects.toThrow('Not Authorised')
|
await expect(client.request(mutationShoutPost, { id: 'p1234' })).rejects.toThrow(
|
||||||
|
'Not Authorised',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I shout a post of another user', async () => {
|
it('I shout a post of another user', async () => {
|
||||||
const res = await clientUser1.request(mutationShoutPost('p2'))
|
const res = await clientUser1.request(mutationShoutPost, { id: 'p12345' })
|
||||||
const expected = {
|
const expected = {
|
||||||
shout: true,
|
shout: true,
|
||||||
}
|
}
|
||||||
expect(res).toMatchObject(expected)
|
expect(res).toMatchObject(expected)
|
||||||
|
|
||||||
const { Post } = await clientUser1.request(`{
|
const { Post } = await clientUser1.request(gql`
|
||||||
Post(id: "p2") {
|
query {
|
||||||
shoutedByCurrentUser
|
Post(id: "p12345") {
|
||||||
|
shoutedByCurrentUser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`)
|
`)
|
||||||
const expected2 = {
|
const expected2 = {
|
||||||
shoutedByCurrentUser: true,
|
shoutedByCurrentUser: true,
|
||||||
}
|
}
|
||||||
@ -84,17 +100,19 @@ describe('shout', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('I can`t shout my own post', async () => {
|
it('I can`t shout my own post', async () => {
|
||||||
const res = await clientUser1.request(mutationShoutPost('p1'))
|
const res = await clientUser1.request(mutationShoutPost, { id: 'p1234' })
|
||||||
const expected = {
|
const expected = {
|
||||||
shout: false,
|
shout: false,
|
||||||
}
|
}
|
||||||
expect(res).toMatchObject(expected)
|
expect(res).toMatchObject(expected)
|
||||||
|
|
||||||
const { Post } = await clientUser1.request(`{
|
const { Post } = await clientUser1.request(gql`
|
||||||
Post(id: "p1") {
|
query {
|
||||||
shoutedByCurrentUser
|
Post(id: "p1234") {
|
||||||
|
shoutedByCurrentUser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`)
|
`)
|
||||||
const expected2 = {
|
const expected2 = {
|
||||||
shoutedByCurrentUser: false,
|
shoutedByCurrentUser: false,
|
||||||
}
|
}
|
||||||
@ -106,28 +124,32 @@ describe('shout', () => {
|
|||||||
describe('unauthenticated shout', () => {
|
describe('unauthenticated shout', () => {
|
||||||
it('throws authorization error', async () => {
|
it('throws authorization error', async () => {
|
||||||
// shout
|
// shout
|
||||||
await clientUser1.request(mutationShoutPost('p2'))
|
await clientUser1.request(mutationShoutPost, { id: 'p12345' })
|
||||||
// unshout
|
// unshout
|
||||||
const client = new GraphQLClient(host)
|
const client = new GraphQLClient(host)
|
||||||
await expect(client.request(mutationUnshoutPost('p2'))).rejects.toThrow('Not Authorised')
|
await expect(client.request(mutationUnshoutPost, { id: 'p12345' })).rejects.toThrow(
|
||||||
|
'Not Authorised',
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('I unshout a post of another user', async () => {
|
it('I unshout a post of another user', async () => {
|
||||||
// shout
|
// shout
|
||||||
await clientUser1.request(mutationShoutPost('p2'))
|
await clientUser1.request(mutationShoutPost, { id: 'p12345' })
|
||||||
const expected = {
|
const expected = {
|
||||||
unshout: true,
|
unshout: true,
|
||||||
}
|
}
|
||||||
// unshout
|
// unshout
|
||||||
const res = await clientUser1.request(mutationUnshoutPost('p2'))
|
const res = await clientUser1.request(mutationUnshoutPost, { id: 'p12345' })
|
||||||
expect(res).toMatchObject(expected)
|
expect(res).toMatchObject(expected)
|
||||||
|
|
||||||
const { Post } = await clientUser1.request(`{
|
const { Post } = await clientUser1.request(gql`
|
||||||
Post(id: "p2") {
|
query {
|
||||||
shoutedByCurrentUser
|
Post(id: "p12345") {
|
||||||
|
shoutedByCurrentUser
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`)
|
`)
|
||||||
const expected2 = {
|
const expected2 = {
|
||||||
shoutedByCurrentUser: false,
|
shoutedByCurrentUser: false,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
import { GraphQLClient } from 'graphql-request'
|
import { GraphQLClient } from 'graphql-request'
|
||||||
import Factory from '../../seed/factories'
|
import Factory from '../../seed/factories'
|
||||||
import { host, login, gql } from '../../jest/helpers'
|
import { host, login, gql } from '../../jest/helpers'
|
||||||
|
import { neode } from '../../bootstrap/neo4j'
|
||||||
|
|
||||||
const factory = Factory()
|
|
||||||
let client
|
let client
|
||||||
|
const factory = Factory()
|
||||||
|
const instance = neode()
|
||||||
|
const categoryIds = ['cat9']
|
||||||
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
await factory.cleanDatabase()
|
await factory.cleanDatabase()
|
||||||
@ -195,9 +198,15 @@ describe('users', () => {
|
|||||||
email: 'test@example.org',
|
email: 'test@example.org',
|
||||||
password: '1234',
|
password: '1234',
|
||||||
})
|
})
|
||||||
|
await instance.create('Category', {
|
||||||
|
id: 'cat9',
|
||||||
|
name: 'Democracy & Politics',
|
||||||
|
icon: 'university',
|
||||||
|
})
|
||||||
await asAuthor.create('Post', {
|
await asAuthor.create('Post', {
|
||||||
id: 'p139',
|
id: 'p139',
|
||||||
content: 'Post by user u343',
|
content: 'Post by user u343',
|
||||||
|
categoryIds,
|
||||||
})
|
})
|
||||||
await asAuthor.create('Comment', {
|
await asAuthor.create('Comment', {
|
||||||
id: 'c155',
|
id: 'c155',
|
||||||
|
|||||||
@ -16,6 +16,7 @@ export default function(params) {
|
|||||||
image = faker.image.unsplash.imageUrl(),
|
image = faker.image.unsplash.imageUrl(),
|
||||||
visibility = 'public',
|
visibility = 'public',
|
||||||
deleted = false,
|
deleted = false,
|
||||||
|
categoryIds,
|
||||||
} = params
|
} = params
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -28,6 +29,7 @@ export default function(params) {
|
|||||||
$image: String
|
$image: String
|
||||||
$visibility: Visibility
|
$visibility: Visibility
|
||||||
$deleted: Boolean
|
$deleted: Boolean
|
||||||
|
$categoryIds: [ID]
|
||||||
) {
|
) {
|
||||||
CreatePost(
|
CreatePost(
|
||||||
id: $id
|
id: $id
|
||||||
@ -37,12 +39,13 @@ export default function(params) {
|
|||||||
image: $image
|
image: $image
|
||||||
visibility: $visibility
|
visibility: $visibility
|
||||||
deleted: $deleted
|
deleted: $deleted
|
||||||
|
categoryIds: $categoryIds
|
||||||
) {
|
) {
|
||||||
title
|
title
|
||||||
content
|
content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
variables: { id, slug, title, content, image, visibility, deleted },
|
variables: { id, slug, title, content, image, visibility, deleted, categoryIds },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -276,131 +276,82 @@ import Factory from './factories'
|
|||||||
asAdmin.create('Post', {
|
asAdmin.create('Post', {
|
||||||
id: 'p0',
|
id: 'p0',
|
||||||
image: faker.image.unsplash.food(),
|
image: faker.image.unsplash.food(),
|
||||||
|
categoryIds: ['cat16'],
|
||||||
}),
|
}),
|
||||||
asModerator.create('Post', {
|
asModerator.create('Post', {
|
||||||
id: 'p1',
|
id: 'p1',
|
||||||
image: faker.image.unsplash.technology(),
|
image: faker.image.unsplash.technology(),
|
||||||
|
categoryIds: ['cat1'],
|
||||||
}),
|
}),
|
||||||
asUser.create('Post', {
|
asUser.create('Post', {
|
||||||
id: 'p2',
|
id: 'p2',
|
||||||
title: `Nature Philosophy Yoga`,
|
title: `Nature Philosophy Yoga`,
|
||||||
content: `${hashtag1}`,
|
content: `${hashtag1}`,
|
||||||
|
categoryIds: ['cat2'],
|
||||||
}),
|
}),
|
||||||
asTick.create('Post', {
|
asTick.create('Post', {
|
||||||
id: 'p3',
|
id: 'p3',
|
||||||
|
categoryIds: ['cat3'],
|
||||||
}),
|
}),
|
||||||
asTrick.create('Post', {
|
asTrick.create('Post', {
|
||||||
id: 'p4',
|
id: 'p4',
|
||||||
|
categoryIds: ['cat4'],
|
||||||
}),
|
}),
|
||||||
asTrack.create('Post', {
|
asTrack.create('Post', {
|
||||||
id: 'p5',
|
id: 'p5',
|
||||||
|
categoryIds: ['cat5'],
|
||||||
}),
|
}),
|
||||||
asAdmin.create('Post', {
|
asAdmin.create('Post', {
|
||||||
id: 'p6',
|
id: 'p6',
|
||||||
image: faker.image.unsplash.buildings(),
|
image: faker.image.unsplash.buildings(),
|
||||||
|
categoryIds: ['cat6'],
|
||||||
}),
|
}),
|
||||||
asModerator.create('Post', {
|
asModerator.create('Post', {
|
||||||
id: 'p7',
|
id: 'p7',
|
||||||
content: `${mention1} ${faker.lorem.paragraph()}`,
|
content: `${mention1} ${faker.lorem.paragraph()}`,
|
||||||
|
categoryIds: ['cat7'],
|
||||||
}),
|
}),
|
||||||
asUser.create('Post', {
|
asUser.create('Post', {
|
||||||
id: 'p8',
|
id: 'p8',
|
||||||
image: faker.image.unsplash.nature(),
|
image: faker.image.unsplash.nature(),
|
||||||
title: `Quantum Flow Theory explains Quantum Gravity`,
|
title: `Quantum Flow Theory explains Quantum Gravity`,
|
||||||
content: `${hashtagAndMention1}`,
|
content: `${hashtagAndMention1}`,
|
||||||
|
categoryIds: ['cat8'],
|
||||||
}),
|
}),
|
||||||
asTick.create('Post', {
|
asTick.create('Post', {
|
||||||
id: 'p9',
|
id: 'p9',
|
||||||
|
categoryIds: ['cat9'],
|
||||||
}),
|
}),
|
||||||
asTrick.create('Post', {
|
asTrick.create('Post', {
|
||||||
id: 'p10',
|
id: 'p10',
|
||||||
|
categoryIds: ['cat10'],
|
||||||
}),
|
}),
|
||||||
asTrack.create('Post', {
|
asTrack.create('Post', {
|
||||||
id: 'p11',
|
id: 'p11',
|
||||||
image: faker.image.unsplash.people(),
|
image: faker.image.unsplash.people(),
|
||||||
|
categoryIds: ['cat11'],
|
||||||
}),
|
}),
|
||||||
asAdmin.create('Post', {
|
asAdmin.create('Post', {
|
||||||
id: 'p12',
|
id: 'p12',
|
||||||
content: `${mention2} ${faker.lorem.paragraph()}`,
|
content: `${mention2} ${faker.lorem.paragraph()}`,
|
||||||
|
categoryIds: ['cat12'],
|
||||||
}),
|
}),
|
||||||
asModerator.create('Post', {
|
asModerator.create('Post', {
|
||||||
id: 'p13',
|
id: 'p13',
|
||||||
|
categoryIds: ['cat13'],
|
||||||
}),
|
}),
|
||||||
asUser.create('Post', {
|
asUser.create('Post', {
|
||||||
id: 'p14',
|
id: 'p14',
|
||||||
image: faker.image.unsplash.objects(),
|
image: faker.image.unsplash.objects(),
|
||||||
|
categoryIds: ['cat14'],
|
||||||
}),
|
}),
|
||||||
asTick.create('Post', {
|
asTick.create('Post', {
|
||||||
id: 'p15',
|
id: 'p15',
|
||||||
|
categoryIds: ['cat15'],
|
||||||
}),
|
}),
|
||||||
])
|
])
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p0',
|
|
||||||
to: 'cat16',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p1',
|
|
||||||
to: 'cat1',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p2',
|
|
||||||
to: 'cat2',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p3',
|
|
||||||
to: 'cat3',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p4',
|
|
||||||
to: 'cat4',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p5',
|
|
||||||
to: 'cat5',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p6',
|
|
||||||
to: 'cat6',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p7',
|
|
||||||
to: 'cat7',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p8',
|
|
||||||
to: 'cat8',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p9',
|
|
||||||
to: 'cat9',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p10',
|
|
||||||
to: 'cat10',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p11',
|
|
||||||
to: 'cat11',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p12',
|
|
||||||
to: 'cat12',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p13',
|
|
||||||
to: 'cat13',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p14',
|
|
||||||
to: 'cat14',
|
|
||||||
}),
|
|
||||||
f.relate('Post', 'Categories', {
|
|
||||||
from: 'p15',
|
|
||||||
to: 'cat15',
|
|
||||||
}),
|
|
||||||
|
|
||||||
f.relate('Post', 'Tags', {
|
f.relate('Post', 'Tags', {
|
||||||
from: 'p0',
|
from: 'p0',
|
||||||
to: 'Freiheit',
|
to: 'Freiheit',
|
||||||
|
|||||||
@ -1826,12 +1826,12 @@ apollo-server-plugin-base@0.6.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-types "0.2.1"
|
apollo-server-types "0.2.1"
|
||||||
|
|
||||||
apollo-server-testing@~2.8.1:
|
apollo-server-testing@~2.8.2:
|
||||||
version "2.8.1"
|
version "2.8.2"
|
||||||
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.8.1.tgz#70026e1b6abab1ca51ffee21bfda61f5b5ad92c1"
|
resolved "https://registry.yarnpkg.com/apollo-server-testing/-/apollo-server-testing-2.8.2.tgz#8faa8f1778fa4893f5bf705f7cea84a69477aa3f"
|
||||||
integrity sha512-bWKczu9HPBWBOz3GDtPA1pykmIvK2TOTLaK03AVSZODvZX0YLWizB0bq5I5Ox6rG+wmW638v1Kq+BhADVHovdg==
|
integrity sha512-ccp1DpmjdmLT98ww4NtSiDPbeIPlVZJ5Iy408ToyhAGwNXRHk5f8Czf+JAgSayvgt4cxCm1fzxnVe1OjO8oIvA==
|
||||||
dependencies:
|
dependencies:
|
||||||
apollo-server-core "2.8.1"
|
apollo-server-core "2.8.2"
|
||||||
|
|
||||||
apollo-server-types@0.2.1:
|
apollo-server-types@0.2.1:
|
||||||
version "0.2.1"
|
version "0.2.1"
|
||||||
@ -2954,10 +2954,10 @@ data-urls@^1.0.0:
|
|||||||
whatwg-mimetype "^2.2.0"
|
whatwg-mimetype "^2.2.0"
|
||||||
whatwg-url "^7.0.0"
|
whatwg-url "^7.0.0"
|
||||||
|
|
||||||
date-fns@2.0.0-beta.5:
|
date-fns@2.0.0:
|
||||||
version "2.0.0-beta.5"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0-beta.5.tgz#90885db3772802d55519cd12acd49de56aca1059"
|
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.0.0.tgz#52f05c6ae1fe0e395670082c72b690ab781682d0"
|
||||||
integrity sha512-GS5yi964NDFNoja9yOdWFj9T97T67yLrUeJZgddHaVfc/6tHWtX7RXocuubmZkNzrZUZ9BqBOW7jTR5OoWjJ1w==
|
integrity sha512-nGZDA64Ktq5uTWV4LEH3qX+foV4AguT5qxwRlJDzJtf57d4xLNwtwrfb7SzKCoikoae8Bvxf0zdaEG/xWssp/w==
|
||||||
|
|
||||||
debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
|
|||||||
@ -24,8 +24,8 @@ Feature: Tags and Categories
|
|||||||
Then I can see the following table:
|
Then I can see the following table:
|
||||||
| | Name | Posts |
|
| | Name | Posts |
|
||||||
| | Just For Fun | 2 |
|
| | Just For Fun | 2 |
|
||||||
| | Happyness & Values | 1 |
|
| | Happiness & Values | 1 |
|
||||||
| | Health & Wellbeing | 0 |
|
| | Health & Wellbeing | 1 |
|
||||||
|
|
||||||
Scenario: See an overview of tags
|
Scenario: See an overview of tags
|
||||||
When I navigate to the administration dashboard
|
When I navigate to the administration dashboard
|
||||||
|
|||||||
@ -21,31 +21,17 @@ Given("I am logged in", () => {
|
|||||||
cy.login(loginCredentials);
|
cy.login(loginCredentials);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Given("we have a selection of categories", () => {
|
||||||
|
cy.createCategories("cat0", "just-for-fun");
|
||||||
|
});
|
||||||
|
|
||||||
Given("we have a selection of tags and categories as well as posts", () => {
|
Given("we have a selection of tags and categories as well as posts", () => {
|
||||||
cy.factory()
|
cy.createCategories("cat12")
|
||||||
|
.factory()
|
||||||
.authenticateAs(loginCredentials)
|
.authenticateAs(loginCredentials)
|
||||||
.create("Category", {
|
|
||||||
id: "cat1",
|
|
||||||
name: "Just For Fun",
|
|
||||||
slug: "justforfun",
|
|
||||||
icon: "smile"
|
|
||||||
})
|
|
||||||
.create("Category", {
|
|
||||||
id: "cat2",
|
|
||||||
name: "Happyness & Values",
|
|
||||||
slug: "happyness-values",
|
|
||||||
icon: "heart-o"
|
|
||||||
})
|
|
||||||
.create("Category", {
|
|
||||||
id: "cat3",
|
|
||||||
name: "Health & Wellbeing",
|
|
||||||
slug: "health-wellbeing",
|
|
||||||
icon: "medkit"
|
|
||||||
})
|
|
||||||
.create("Tag", { id: "Ecology" })
|
.create("Tag", { id: "Ecology" })
|
||||||
.create("Tag", { id: "Nature" })
|
.create("Tag", { id: "Nature" })
|
||||||
.create("Tag", { id: "Democracy" });
|
.create("Tag", { id: "Democracy" });
|
||||||
|
|
||||||
const someAuthor = {
|
const someAuthor = {
|
||||||
id: "authorId",
|
id: "authorId",
|
||||||
email: "author@example.org",
|
email: "author@example.org",
|
||||||
@ -59,18 +45,15 @@ Given("we have a selection of tags and categories as well as posts", () => {
|
|||||||
cy.factory()
|
cy.factory()
|
||||||
.create("User", someAuthor)
|
.create("User", someAuthor)
|
||||||
.authenticateAs(someAuthor)
|
.authenticateAs(someAuthor)
|
||||||
.create("Post", { id: "p0" })
|
.create("Post", { id: "p0", categoryIds: ["cat12"] })
|
||||||
.create("Post", { id: "p1" });
|
.create("Post", { id: "p1", categoryIds: ["cat121"] });
|
||||||
cy.factory()
|
cy.factory()
|
||||||
.create("User", yetAnotherAuthor)
|
.create("User", yetAnotherAuthor)
|
||||||
.authenticateAs(yetAnotherAuthor)
|
.authenticateAs(yetAnotherAuthor)
|
||||||
.create("Post", { id: "p2" });
|
.create("Post", { id: "p2", categoryIds: ["cat12"] });
|
||||||
cy.factory()
|
cy.factory()
|
||||||
.authenticateAs(loginCredentials)
|
.authenticateAs(loginCredentials)
|
||||||
.create("Post", { id: "p3" })
|
.create("Post", { id: "p3", categoryIds: ["cat122"] })
|
||||||
.relate("Post", "Categories", { from: "p0", to: "cat1" })
|
|
||||||
.relate("Post", "Categories", { from: "p1", to: "cat2" })
|
|
||||||
.relate("Post", "Categories", { from: "p2", to: "cat1" })
|
|
||||||
.relate("Post", "Tags", { from: "p0", to: "Ecology" })
|
.relate("Post", "Tags", { from: "p0", to: "Ecology" })
|
||||||
.relate("Post", "Tags", { from: "p0", to: "Nature" })
|
.relate("Post", "Tags", { from: "p0", to: "Nature" })
|
||||||
.relate("Post", "Tags", { from: "p0", to: "Democracy" })
|
.relate("Post", "Tags", { from: "p0", to: "Democracy" })
|
||||||
@ -182,9 +165,17 @@ Given("we have the following posts in our database:", table => {
|
|||||||
};
|
};
|
||||||
postAttributes.deleted = Boolean(postAttributes.deleted);
|
postAttributes.deleted = Boolean(postAttributes.deleted);
|
||||||
const disabled = Boolean(postAttributes.disabled);
|
const disabled = Boolean(postAttributes.disabled);
|
||||||
|
postAttributes.categoryIds = [`cat${i}`];
|
||||||
|
postAttributes;
|
||||||
cy.factory()
|
cy.factory()
|
||||||
.create("User", userAttributes)
|
.create("User", userAttributes)
|
||||||
.authenticateAs(userAttributes)
|
.authenticateAs(userAttributes)
|
||||||
|
.create("Category", {
|
||||||
|
id: `cat${i}`,
|
||||||
|
name: "Just For Fun",
|
||||||
|
slug: `just-for-fun-${i}`,
|
||||||
|
icon: "smile"
|
||||||
|
})
|
||||||
.create("Post", postAttributes);
|
.create("Post", postAttributes);
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
const moderatorParams = {
|
const moderatorParams = {
|
||||||
@ -218,6 +209,7 @@ When(
|
|||||||
Given("I previously created a post", () => {
|
Given("I previously created a post", () => {
|
||||||
lastPost.title = "previously created post";
|
lastPost.title = "previously created post";
|
||||||
lastPost.content = "with some content";
|
lastPost.content = "with some content";
|
||||||
|
lastPost.categoryIds = "cat0";
|
||||||
cy.factory()
|
cy.factory()
|
||||||
.authenticateAs(loginCredentials)
|
.authenticateAs(loginCredentials)
|
||||||
.create("Post", lastPost);
|
.create("Post", lastPost);
|
||||||
@ -233,6 +225,12 @@ When("I type in the following text:", text => {
|
|||||||
cy.get(".editor .ProseMirror").type(lastPost.content);
|
cy.get(".editor .ProseMirror").type(lastPost.content);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Then("I select a category", () => {
|
||||||
|
cy.get("span")
|
||||||
|
.contains("Just for Fun")
|
||||||
|
.click();
|
||||||
|
});
|
||||||
|
|
||||||
Then("the post shows up on the landing page at position {int}", index => {
|
Then("the post shows up on the landing page at position {int}", index => {
|
||||||
cy.openPage("landing");
|
cy.openPage("landing");
|
||||||
const selector = `.post-card:nth-child(${index}) > .ds-card-content`;
|
const selector = `.post-card:nth-child(${index}) > .ds-card-content`;
|
||||||
@ -260,7 +258,9 @@ Then("the first post on the landing page has the title:", title => {
|
|||||||
Then(
|
Then(
|
||||||
"the page {string} returns a 404 error with a message:",
|
"the page {string} returns a 404 error with a message:",
|
||||||
(route, message) => {
|
(route, message) => {
|
||||||
cy.request({ url: route, failOnStatusCode: false }).its('status').should('eq', 404)
|
cy.request({ url: route, failOnStatusCode: false })
|
||||||
|
.its("status")
|
||||||
|
.should("eq", 404);
|
||||||
cy.visit(route, { failOnStatusCode: false });
|
cy.visit(route, { failOnStatusCode: false });
|
||||||
cy.get(".error").should("contain", message);
|
cy.get(".error").should("contain", message);
|
||||||
}
|
}
|
||||||
@ -354,7 +354,7 @@ When("mention {string} in the text", mention => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Then("the notification gets marked as read", () => {
|
Then("the notification gets marked as read", () => {
|
||||||
cy.get(".notification")
|
cy.get(".post.createdAt")
|
||||||
.first()
|
.first()
|
||||||
.should("have.class", "read");
|
.should("have.class", "read");
|
||||||
});
|
});
|
||||||
@ -417,12 +417,13 @@ Given("I follow the user {string}", name => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Given('"Spammy Spammer" wrote a post {string}', title => {
|
Given('"Spammy Spammer" wrote a post {string}', title => {
|
||||||
cy.factory()
|
cy.createCategories("cat21")
|
||||||
|
.factory()
|
||||||
.authenticateAs({
|
.authenticateAs({
|
||||||
email: "spammy-spammer@example.org",
|
email: "spammy-spammer@example.org",
|
||||||
password: "1234"
|
password: "1234"
|
||||||
})
|
})
|
||||||
.create("Post", { title });
|
.create("Post", { title, categoryIds: ["cat21"] });
|
||||||
});
|
});
|
||||||
|
|
||||||
Then("the list of posts of this user is empty", () => {
|
Then("the list of posts of this user is empty", () => {
|
||||||
@ -439,9 +440,10 @@ Then("nobody is following the user profile anymore", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Given("I wrote a post {string}", title => {
|
Given("I wrote a post {string}", title => {
|
||||||
cy.factory()
|
cy.createCategories(`cat213`, title)
|
||||||
|
.factory()
|
||||||
.authenticateAs(loginCredentials)
|
.authenticateAs(loginCredentials)
|
||||||
.create("Post", { title });
|
.create("Post", { title, categoryIds: ["cat213"] });
|
||||||
});
|
});
|
||||||
|
|
||||||
When("I block the user {string}", name => {
|
When("I block the user {string}", name => {
|
||||||
|
|||||||
@ -7,20 +7,20 @@ Feature: Hide Posts
|
|||||||
Given we have the following posts in our database:
|
Given we have the following posts in our database:
|
||||||
| id | title | deleted | disabled |
|
| id | title | deleted | disabled |
|
||||||
| p1 | This post should be visible | | |
|
| p1 | This post should be visible | | |
|
||||||
| p2 | This post is disabled | | x |
|
| p2 | This post is disabled | | x |
|
||||||
| p3 | This post is deleted | x | |
|
| p3 | This post is deleted | x | |
|
||||||
|
|
||||||
Scenario: Disabled posts don't show up on the landing page
|
Scenario: Disabled posts don't show up on the landing page
|
||||||
Given I am logged in with a "user" role
|
Given I am logged in with a "user" role
|
||||||
Then I should see only 1 post on the landing page
|
Then I should see only 1 post on the landing page
|
||||||
And the first post on the landing page has the title:
|
And the first post on the landing page has the title:
|
||||||
"""
|
"""
|
||||||
This post should be visible
|
This post should be visible
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Scenario: Visiting a disabled post's page should return 404
|
Scenario: Visiting a disabled post's page should return 404
|
||||||
Given I am logged in with a "user" role
|
Given I am logged in with a "user" role
|
||||||
Then the page "/post/this-post-is-disabled" returns a 404 error with a message:
|
Then the page "/post/this-post-is-disabled" returns a 404 error with a message:
|
||||||
"""
|
"""
|
||||||
This post could not be found
|
This post could not be found
|
||||||
"""
|
"""
|
||||||
|
|||||||
@ -4,25 +4,27 @@ Feature: Notifications for a mentions
|
|||||||
In order join conversations about or related to me
|
In order join conversations about or related to me
|
||||||
|
|
||||||
Background:
|
Background:
|
||||||
Given we have the following user accounts:
|
Given we have a selection of categories
|
||||||
| name | slug | email | password |
|
And we have the following user accounts:
|
||||||
| Wolle aus Hamburg | wolle-aus-hamburg | wolle@example.org | 1234 |
|
| name | slug | email | password |
|
||||||
| Matt Rider | matt-rider | matt@example.org | 4321 |
|
| Wolle aus Hamburg | wolle-aus-hamburg | wolle@example.org | 1234 |
|
||||||
|
| Matt Rider | matt-rider | matt@example.org | 4321 |
|
||||||
|
|
||||||
Scenario: Mention another user, re-login as this user and see notifications
|
Scenario: Mention another user, re-login as this user and see notifications
|
||||||
Given I log in with the following credentials:
|
Given I log in with the following credentials:
|
||||||
| email | password |
|
| email | password |
|
||||||
| wolle@example.org | 1234 |
|
| wolle@example.org | 1234 |
|
||||||
And I start to write a new post with the title "Hey Matt" beginning with:
|
And I start to write a new post with the title "Hey Matt" beginning with:
|
||||||
"""
|
"""
|
||||||
Big shout to our fellow contributor
|
Big shout to our fellow contributor
|
||||||
"""
|
"""
|
||||||
And mention "@matt-rider" in the text
|
And mention "@matt-rider" in the text
|
||||||
|
And I select a category
|
||||||
And I click on "Save"
|
And I click on "Save"
|
||||||
When I log out
|
When I log out
|
||||||
And I log in with the following credentials:
|
And I log in with the following credentials:
|
||||||
| email | password |
|
| email | password |
|
||||||
| matt@example.org | 4321 |
|
| matt@example.org | 4321 |
|
||||||
And see 1 unread notifications in the top menu
|
And see 1 unread notifications in the top menu
|
||||||
And open the notification menu and click on the first item
|
And open the notification menu and click on the first item
|
||||||
Then I get to the post page of ".../hey-matt"
|
Then I get to the post page of ".../hey-matt"
|
||||||
|
|||||||
@ -6,6 +6,7 @@ Feature: Create a post
|
|||||||
Background:
|
Background:
|
||||||
Given I have a user account
|
Given I have a user account
|
||||||
And I am logged in
|
And I am logged in
|
||||||
|
And we have a selection of categories
|
||||||
And I am on the "landing" page
|
And I am on the "landing" page
|
||||||
|
|
||||||
Scenario: Create a post
|
Scenario: Create a post
|
||||||
@ -16,6 +17,7 @@ Feature: Create a post
|
|||||||
Human Connection is a free and open-source social network
|
Human Connection is a free and open-source social network
|
||||||
for active citizenship.
|
for active citizenship.
|
||||||
"""
|
"""
|
||||||
|
Then I select a category
|
||||||
And I click on "Save"
|
And I click on "Save"
|
||||||
Then I get redirected to ".../my-first-post"
|
Then I get redirected to ".../my-first-post"
|
||||||
And the post was saved successfully
|
And the post was saved successfully
|
||||||
|
|||||||
@ -7,6 +7,7 @@ Feature: Block a User
|
|||||||
Given I have a user account
|
Given I have a user account
|
||||||
And there is an annoying user called "Spammy Spammer"
|
And there is an annoying user called "Spammy Spammer"
|
||||||
And I am logged in
|
And I am logged in
|
||||||
|
And we have a selection of categories
|
||||||
|
|
||||||
Scenario: Block a user
|
Scenario: Block a user
|
||||||
Given I am on the profile page of the annoying user
|
Given I am on the profile page of the annoying user
|
||||||
|
|||||||
@ -13,55 +13,74 @@
|
|||||||
// Cypress.Commands.add('login', (email, password) => { ... })
|
// Cypress.Commands.add('login', (email, password) => { ... })
|
||||||
|
|
||||||
/* globals Cypress cy */
|
/* globals Cypress cy */
|
||||||
import 'cypress-file-upload'
|
import "cypress-file-upload";
|
||||||
import { getLangByName } from './helpers'
|
import { getLangByName } from "./helpers";
|
||||||
import users from '../fixtures/users.json'
|
import users from "../fixtures/users.json";
|
||||||
|
|
||||||
const switchLang = name => {
|
const switchLang = name => {
|
||||||
cy.get('.locale-menu').click()
|
cy.get(".locale-menu").click();
|
||||||
cy.contains('.locale-menu-popover a', name).click()
|
cy.contains(".locale-menu-popover a", name).click();
|
||||||
}
|
};
|
||||||
|
|
||||||
Cypress.Commands.add('switchLanguage', (name, force) => {
|
Cypress.Commands.add("switchLanguage", (name, force) => {
|
||||||
const code = getLangByName(name).code
|
const code = getLangByName(name).code;
|
||||||
if (force) {
|
if (force) {
|
||||||
switchLang(name)
|
switchLang(name);
|
||||||
} else {
|
} else {
|
||||||
cy.get('html').then($html => {
|
cy.get("html").then($html => {
|
||||||
if ($html && $html.attr('lang') !== code) {
|
if ($html && $html.attr("lang") !== code) {
|
||||||
switchLang(name)
|
switchLang(name);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("login", ({ email, password }) => {
|
||||||
|
cy.visit(`/login`);
|
||||||
|
cy.get("input[name=email]")
|
||||||
|
.trigger("focus")
|
||||||
|
.type(email);
|
||||||
|
cy.get("input[name=password]")
|
||||||
|
.trigger("focus")
|
||||||
|
.type(password);
|
||||||
|
cy.get("button[name=submit]")
|
||||||
|
.as("submitButton")
|
||||||
|
.click();
|
||||||
|
cy.get(".iziToast-message").should("contain", "You are logged in!");
|
||||||
|
cy.get(".iziToast-close").click();
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("logout", (email, password) => {
|
||||||
|
cy.visit(`/logout`);
|
||||||
|
cy.location("pathname").should("contain", "/login"); // we're out
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("openPage", page => {
|
||||||
|
if (page === "landing") {
|
||||||
|
page = "";
|
||||||
|
}
|
||||||
|
cy.visit(`/${page}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
Cypress.Commands.add("createCategories", (id, slug) => {
|
||||||
|
cy.neode()
|
||||||
|
.create("Category", {
|
||||||
|
id: `${id}`,
|
||||||
|
name: "Just For Fun",
|
||||||
|
slug: `${slug}`,
|
||||||
|
icon: "smile"
|
||||||
})
|
})
|
||||||
}
|
.create("Category", {
|
||||||
})
|
id: `${id}1`,
|
||||||
|
name: "Happiness & Values",
|
||||||
Cypress.Commands.add('login', ({ email, password }) => {
|
icon: "heart-o"
|
||||||
cy.visit(`/login`)
|
})
|
||||||
cy.get('input[name=email]')
|
.create("Category", {
|
||||||
.trigger('focus')
|
id: `${id}2`,
|
||||||
.type(email)
|
name: "Health & Wellbeing",
|
||||||
cy.get('input[name=password]')
|
icon: "medkit"
|
||||||
.trigger('focus')
|
});
|
||||||
.type(password)
|
});
|
||||||
cy.get('button[name=submit]')
|
|
||||||
.as('submitButton')
|
|
||||||
.click()
|
|
||||||
cy.get('.iziToast-message').should('contain', 'You are logged in!')
|
|
||||||
cy.get('.iziToast-close').click()
|
|
||||||
})
|
|
||||||
|
|
||||||
Cypress.Commands.add('logout', (email, password) => {
|
|
||||||
cy.visit(`/logout`)
|
|
||||||
cy.location('pathname').should('contain', '/login') // we're out
|
|
||||||
})
|
|
||||||
|
|
||||||
Cypress.Commands.add('openPage', page => {
|
|
||||||
if (page === 'landing') {
|
|
||||||
page = ''
|
|
||||||
}
|
|
||||||
cy.visit(`/${page}`)
|
|
||||||
})
|
|
||||||
|
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// -- This is a child command --
|
// -- This is a child command --
|
||||||
|
|||||||
@ -27,7 +27,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import CategoryQuery from '~/graphql/CategoryQuery.js'
|
import CategoryQuery from '~/graphql/CategoryQuery'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
@ -87,8 +87,8 @@ export default {
|
|||||||
query() {
|
query() {
|
||||||
return CategoryQuery()
|
return CategoryQuery()
|
||||||
},
|
},
|
||||||
result(result) {
|
result({ data: { Category } }) {
|
||||||
this.categories = result.data.Category
|
this.categories = Category
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -83,7 +83,7 @@ export default {
|
|||||||
update: (store, { data: { CreateComment } }) => {
|
update: (store, { data: { CreateComment } }) => {
|
||||||
const data = store.readQuery({
|
const data = store.readQuery({
|
||||||
query: PostQuery(this.$i18n),
|
query: PostQuery(this.$i18n),
|
||||||
variables: { slug: this.post.slug },
|
variables: { id: this.post.id },
|
||||||
})
|
})
|
||||||
data.Post[0].comments.push(CreateComment)
|
data.Post[0].comments.push(CreateComment)
|
||||||
store.writeQuery({ query: PostQuery(this.$i18n), data })
|
store.writeQuery({ query: PostQuery(this.$i18n), data })
|
||||||
|
|||||||
@ -28,6 +28,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
let cancelBtn
|
let cancelBtn
|
||||||
let mocks
|
let mocks
|
||||||
let propsData
|
let propsData
|
||||||
|
let categoryIds
|
||||||
const postTitle = 'this is a title for a post'
|
const postTitle = 'this is a title for a post'
|
||||||
const postTitleTooShort = 'xx'
|
const postTitleTooShort = 'xx'
|
||||||
let postTitleTooLong = ''
|
let postTitleTooLong = ''
|
||||||
@ -60,6 +61,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
content: postContent,
|
content: postContent,
|
||||||
contentExcerpt: postContent,
|
contentExcerpt: postContent,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
|
categoryIds,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -175,6 +177,23 @@ describe('ContributionForm.vue', () => {
|
|||||||
wrapper.find('.submit-button-for-test').trigger('click')
|
wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should have at least one category', async () => {
|
||||||
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
|
postTitleInput.setValue(postTitle)
|
||||||
|
await wrapper.vm.updateEditorContent(postContent)
|
||||||
|
wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
|
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should have not have more than three categories', async () => {
|
||||||
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
|
postTitleInput.setValue(postTitle)
|
||||||
|
await wrapper.vm.updateEditorContent(postContent)
|
||||||
|
wrapper.vm.form.categoryIds = ['cat4', 'cat9', 'cat15', 'cat27']
|
||||||
|
wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
|
expect(mocks.$apollo.mutate).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('valid form submission', () => {
|
describe('valid form submission', () => {
|
||||||
@ -186,7 +205,7 @@ describe('ContributionForm.vue', () => {
|
|||||||
content: postContent,
|
content: postContent,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
id: null,
|
id: null,
|
||||||
categoryIds: null,
|
categoryIds: ['cat12'],
|
||||||
imageUpload: null,
|
imageUpload: null,
|
||||||
image: null,
|
image: null,
|
||||||
},
|
},
|
||||||
@ -194,11 +213,13 @@ describe('ContributionForm.vue', () => {
|
|||||||
postTitleInput = wrapper.find('.ds-input')
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
postTitleInput.setValue(postTitle)
|
postTitleInput.setValue(postTitle)
|
||||||
await wrapper.vm.updateEditorContent(postContent)
|
await wrapper.vm.updateEditorContent(postContent)
|
||||||
|
categoryIds = ['cat12']
|
||||||
|
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('with title and content', () => {
|
it('creates a post with valid title, content, and at least one category', async () => {
|
||||||
wrapper.find('.submit-button-for-test').trigger('click')
|
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledTimes(1)
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
})
|
})
|
||||||
|
|
||||||
it("sends a fallback language based on a user's locale", () => {
|
it("sends a fallback language based on a user's locale", () => {
|
||||||
@ -214,14 +235,6 @@ describe('ContributionForm.vue', () => {
|
|||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
})
|
})
|
||||||
|
|
||||||
it('supports adding categories', async () => {
|
|
||||||
const categoryIds = ['cat12', 'cat15', 'cat37']
|
|
||||||
expectedParams.variables.categoryIds = categoryIds
|
|
||||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
|
||||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
|
||||||
})
|
|
||||||
|
|
||||||
it('supports adding a teaser image', async () => {
|
it('supports adding a teaser image', async () => {
|
||||||
expectedParams.variables.imageUpload = imageUpload
|
expectedParams.variables.imageUpload = imageUpload
|
||||||
wrapper.find(TeaserImage).vm.$emit('addTeaserImage', imageUpload)
|
wrapper.find(TeaserImage).vm.$emit('addTeaserImage', imageUpload)
|
||||||
@ -260,6 +273,8 @@ describe('ContributionForm.vue', () => {
|
|||||||
postTitleInput = wrapper.find('.ds-input')
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
postTitleInput.setValue(postTitle)
|
postTitleInput.setValue(postTitle)
|
||||||
await wrapper.vm.updateEditorContent(postContent)
|
await wrapper.vm.updateEditorContent(postContent)
|
||||||
|
categoryIds = ['cat12']
|
||||||
|
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows an error toaster when apollo mutation rejects', async () => {
|
it('shows an error toaster when apollo mutation rejects', async () => {
|
||||||
@ -307,35 +322,54 @@ describe('ContributionForm.vue', () => {
|
|||||||
expect(wrapper.vm.form.content).toEqual(propsData.contribution.content)
|
expect(wrapper.vm.form.content).toEqual(propsData.contribution.content)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('calls the UpdatePost apollo mutation', async () => {
|
describe('valid update', () => {
|
||||||
expectedParams = {
|
beforeEach(() => {
|
||||||
mutation: PostMutations().UpdatePost,
|
mocks.$apollo.mutate = jest.fn().mockResolvedValueOnce({
|
||||||
variables: {
|
data: {
|
||||||
title: postTitle,
|
UpdatePost: {
|
||||||
content: postContent,
|
title: postTitle,
|
||||||
language: propsData.contribution.language,
|
slug: 'this-is-a-title-for-a-post',
|
||||||
id: propsData.contribution.id,
|
content: postContent,
|
||||||
categoryIds: ['cat12'],
|
contentExcerpt: postContent,
|
||||||
image,
|
language: 'en',
|
||||||
imageUpload: null,
|
categoryIds,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
postTitleInput = wrapper.find('.ds-input')
|
})
|
||||||
postTitleInput.setValue(postTitle)
|
wrapper = Wrapper()
|
||||||
wrapper.vm.updateEditorContent(postContent)
|
expectedParams = {
|
||||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
mutation: PostMutations().UpdatePost,
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
variables: {
|
||||||
})
|
title: postTitle,
|
||||||
|
content: postContent,
|
||||||
|
language: propsData.contribution.language,
|
||||||
|
id: propsData.contribution.id,
|
||||||
|
categoryIds,
|
||||||
|
image,
|
||||||
|
imageUpload: null,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
it('supports updating categories', async () => {
|
it('calls the UpdatePost apollo mutation', async () => {
|
||||||
const categoryIds = ['cat3', 'cat51', 'cat37']
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
postTitleInput = wrapper.find('.ds-input')
|
postTitleInput.setValue(postTitle)
|
||||||
postTitleInput.setValue(postTitle)
|
wrapper.vm.updateEditorContent(postContent)
|
||||||
wrapper.vm.updateEditorContent(postContent)
|
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||||
expectedParams.variables.categoryIds = categoryIds
|
wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
await wrapper.find('.submit-button-for-test').trigger('click')
|
})
|
||||||
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
|
||||||
|
it('supports updating categories', async () => {
|
||||||
|
const categoryIds = ['cat3', 'cat51', 'cat37']
|
||||||
|
postTitleInput = wrapper.find('.ds-input')
|
||||||
|
postTitleInput.setValue(postTitle)
|
||||||
|
wrapper.vm.updateEditorContent(postContent)
|
||||||
|
expectedParams.variables.categoryIds = categoryIds
|
||||||
|
wrapper.find(CategoriesSelect).vm.$emit('updateCategories', categoryIds)
|
||||||
|
await wrapper.find('.submit-button-for-test').trigger('click')
|
||||||
|
expect(mocks.$apollo.mutate).toHaveBeenCalledWith(expect.objectContaining(expectedParams))
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -17,8 +17,8 @@
|
|||||||
<no-ssr>
|
<no-ssr>
|
||||||
<hc-editor
|
<hc-editor
|
||||||
:users="users"
|
:users="users"
|
||||||
:hashtags="hashtags"
|
|
||||||
:value="form.content"
|
:value="form.content"
|
||||||
|
:hashtags="hashtags"
|
||||||
@input="updateEditorContent"
|
@input="updateEditorContent"
|
||||||
/>
|
/>
|
||||||
<small class="smallTag">{{ form.contentLength }}/{{ contentMax }}</small>
|
<small class="smallTag">{{ form.contentLength }}/{{ contentMax }}</small>
|
||||||
@ -57,7 +57,7 @@
|
|||||||
type="submit"
|
type="submit"
|
||||||
icon="check"
|
icon="check"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
:disabled="disabledByContent || errors"
|
:disabled="failsValidations || errors"
|
||||||
primary
|
primary
|
||||||
@click.prevent="submit"
|
@click.prevent="submit"
|
||||||
>
|
>
|
||||||
@ -101,7 +101,7 @@ export default {
|
|||||||
image: null,
|
image: null,
|
||||||
language: null,
|
language: null,
|
||||||
languageOptions: [],
|
languageOptions: [],
|
||||||
categoryIds: null,
|
categoryIds: [],
|
||||||
},
|
},
|
||||||
formSchema: {
|
formSchema: {
|
||||||
title: { required: true, min: 3, max: 64 },
|
title: { required: true, min: 3, max: 64 },
|
||||||
@ -109,12 +109,11 @@ export default {
|
|||||||
},
|
},
|
||||||
id: null,
|
id: null,
|
||||||
loading: false,
|
loading: false,
|
||||||
disabledByContent: true,
|
|
||||||
slug: null,
|
slug: null,
|
||||||
users: [],
|
users: [],
|
||||||
contentMin: 3,
|
contentMin: 3,
|
||||||
contentMax: 2000,
|
contentMax: 2000,
|
||||||
|
failsValidations: true,
|
||||||
hashtags: [],
|
hashtags: [],
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -129,9 +128,9 @@ export default {
|
|||||||
this.slug = contribution.slug
|
this.slug = contribution.slug
|
||||||
this.form.title = contribution.title
|
this.form.title = contribution.title
|
||||||
this.form.content = contribution.content
|
this.form.content = contribution.content
|
||||||
this.manageContent(this.form.content)
|
|
||||||
this.form.image = contribution.image
|
this.form.image = contribution.image
|
||||||
this.form.categoryIds = this.categoryIds(contribution.categories)
|
this.form.categoryIds = this.categoryIds(contribution.categories)
|
||||||
|
this.manageContent(this.form.content)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -175,11 +174,11 @@ export default {
|
|||||||
imageUpload: teaserImage,
|
imageUpload: teaserImage,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.then(res => {
|
.then(({ data }) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$toast.success(this.$t('contribution.success'))
|
this.$toast.success(this.$t('contribution.success'))
|
||||||
this.disabledByContent = true
|
const result = data[this.id ? 'UpdatePost' : 'CreatePost']
|
||||||
const result = res.data[this.id ? 'UpdatePost' : 'CreatePost']
|
this.failedValidations = false
|
||||||
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: 'post-id-slug',
|
name: 'post-id-slug',
|
||||||
@ -189,7 +188,7 @@ export default {
|
|||||||
.catch(err => {
|
.catch(err => {
|
||||||
this.$toast.error(err.message)
|
this.$toast.error(err.message)
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.disabledByContent = false
|
this.failedValidations = true
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateEditorContent(value) {
|
updateEditorContent(value) {
|
||||||
@ -202,8 +201,7 @@ export default {
|
|||||||
const str = content.replace(/<\/?[^>]+(>|$)/gm, '')
|
const str = content.replace(/<\/?[^>]+(>|$)/gm, '')
|
||||||
// Set counter length of text
|
// Set counter length of text
|
||||||
this.form.contentLength = str.length
|
this.form.contentLength = str.length
|
||||||
// Enable save button if requirements are met
|
this.validatePost()
|
||||||
this.disabledByContent = !(this.contentMin <= str.length && str.length <= this.contentMax)
|
|
||||||
},
|
},
|
||||||
availableLocales() {
|
availableLocales() {
|
||||||
orderBy(locales, 'name').map(locale => {
|
orderBy(locales, 'name').map(locale => {
|
||||||
@ -212,6 +210,7 @@ export default {
|
|||||||
},
|
},
|
||||||
updateCategories(ids) {
|
updateCategories(ids) {
|
||||||
this.form.categoryIds = ids
|
this.form.categoryIds = ids
|
||||||
|
this.validatePost()
|
||||||
},
|
},
|
||||||
addTeaserImage(file) {
|
addTeaserImage(file) {
|
||||||
this.form.teaserImage = file
|
this.form.teaserImage = file
|
||||||
@ -223,12 +222,19 @@ export default {
|
|||||||
})
|
})
|
||||||
return categoryIds
|
return categoryIds
|
||||||
},
|
},
|
||||||
|
validatePost() {
|
||||||
|
const passesContentValidations =
|
||||||
|
this.form.contentLength >= this.contentMin && this.form.contentLength <= this.contentMax
|
||||||
|
const passesCategoryValidations =
|
||||||
|
this.form.categoryIds.length > 0 && this.form.categoryIds.length <= 3
|
||||||
|
this.failsValidations = !(passesContentValidations && passesCategoryValidations)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
User: {
|
User: {
|
||||||
query() {
|
query() {
|
||||||
return gql`
|
return gql`
|
||||||
{
|
query {
|
||||||
User(orderBy: slug_asc) {
|
User(orderBy: slug_asc) {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
@ -236,22 +242,22 @@ export default {
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
},
|
},
|
||||||
result(result) {
|
result({ data: { User } }) {
|
||||||
this.users = result.data.User
|
this.users = User
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Tag: {
|
Tag: {
|
||||||
query() {
|
query() {
|
||||||
return gql`
|
return gql`
|
||||||
{
|
query {
|
||||||
Tag(orderBy: id_asc) {
|
Tag(orderBy: id_asc) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
},
|
},
|
||||||
result(result) {
|
result({ data: { Tag } }) {
|
||||||
this.hashtags = result.data.Tag
|
this.hashtags = Tag
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1,22 +1,28 @@
|
|||||||
import { shallowMount } from '@vue/test-utils'
|
import { mount, createLocalVue } from '@vue/test-utils'
|
||||||
|
import Styleguide from '@human-connection/styleguide'
|
||||||
import MasonryGrid from './MasonryGrid'
|
import MasonryGrid from './MasonryGrid'
|
||||||
|
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
localVue.use(Styleguide)
|
||||||
|
|
||||||
describe('MasonryGrid', () => {
|
describe('MasonryGrid', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
let masonryGrid
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = shallowMount(MasonryGrid)
|
wrapper = mount(MasonryGrid, { localVue })
|
||||||
|
masonryGrid = wrapper.vm.$children[0]
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds the "reset-grid-height" class when one or more children are updating', () => {
|
it('adds the "reset-grid-height" class when one or more children are updating', () => {
|
||||||
wrapper.trigger('calculating-item-height')
|
masonryGrid.$emit('calculating-item-height')
|
||||||
|
|
||||||
expect(wrapper.classes()).toContain('reset-grid-height')
|
expect(wrapper.classes()).toContain('reset-grid-height')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('removes the "reset-grid-height" class when all children have completed updating', () => {
|
it('removes the "reset-grid-height" class when all children have completed updating', () => {
|
||||||
wrapper.setData({ itemsCalculating: 1 })
|
wrapper.setData({ itemsCalculating: 1 })
|
||||||
wrapper.trigger('finished-calculating-item-height')
|
masonryGrid.$emit('finished-calculating-item-height')
|
||||||
|
|
||||||
expect(wrapper.classes()).not.toContain('reset-grid-height')
|
expect(wrapper.classes()).not.toContain('reset-grid-height')
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import { shallowMount } from '@vue/test-utils'
|
import { config, shallowMount, createLocalVue } from '@vue/test-utils'
|
||||||
|
import Styleguide from '@human-connection/styleguide'
|
||||||
import MasonryGridItem from './MasonryGridItem'
|
import MasonryGridItem from './MasonryGridItem'
|
||||||
|
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
localVue.use(Styleguide)
|
||||||
|
|
||||||
|
config.stubs['ds-grid-item'] = '<span><slot /></span>'
|
||||||
|
|
||||||
describe('MasonryGridItem', () => {
|
describe('MasonryGridItem', () => {
|
||||||
let wrapper
|
let wrapper
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
wrapper = shallowMount(MasonryGridItem)
|
wrapper = shallowMount(MasonryGridItem, { localVue })
|
||||||
wrapper.vm.$parent.$emit = jest.fn()
|
wrapper.vm.$parent.$emit = jest.fn()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
return gql(`{
|
return gql`
|
||||||
Category {
|
query {
|
||||||
id
|
Category {
|
||||||
slug
|
id
|
||||||
icon
|
slug
|
||||||
|
icon
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}`)
|
`
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,16 +3,46 @@ import gql from 'graphql-tag'
|
|||||||
export default i18n => {
|
export default i18n => {
|
||||||
const lang = i18n.locale().toUpperCase()
|
const lang = i18n.locale().toUpperCase()
|
||||||
return gql`
|
return gql`
|
||||||
query Post($slug: String!) {
|
query Post($id: ID!) {
|
||||||
Post(slug: $slug) {
|
Post(id: $id) {
|
||||||
|
id
|
||||||
|
title
|
||||||
|
content
|
||||||
|
createdAt
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
slug
|
||||||
|
image
|
||||||
|
author {
|
||||||
id
|
id
|
||||||
title
|
slug
|
||||||
|
name
|
||||||
|
avatar
|
||||||
|
disabled
|
||||||
|
deleted
|
||||||
|
shoutedCount
|
||||||
|
contributionsCount
|
||||||
|
commentedCount
|
||||||
|
followedByCount
|
||||||
|
followedByCurrentUser
|
||||||
|
location {
|
||||||
|
name: name${lang}
|
||||||
|
}
|
||||||
|
badges {
|
||||||
|
id
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tags {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
comments(orderBy: createdAt_asc) {
|
||||||
|
id
|
||||||
|
contentExcerpt
|
||||||
content
|
content
|
||||||
createdAt
|
createdAt
|
||||||
disabled
|
disabled
|
||||||
deleted
|
deleted
|
||||||
slug
|
|
||||||
image
|
|
||||||
author {
|
author {
|
||||||
id
|
id
|
||||||
slug
|
slug
|
||||||
@ -33,48 +63,18 @@ export default i18n => {
|
|||||||
icon
|
icon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tags {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
comments(orderBy: createdAt_asc) {
|
|
||||||
id
|
|
||||||
contentExcerpt
|
|
||||||
content
|
|
||||||
createdAt
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
author {
|
|
||||||
id
|
|
||||||
slug
|
|
||||||
name
|
|
||||||
avatar
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
shoutedCount
|
|
||||||
contributionsCount
|
|
||||||
commentedCount
|
|
||||||
followedByCount
|
|
||||||
followedByCurrentUser
|
|
||||||
location {
|
|
||||||
name: name${lang}
|
|
||||||
}
|
|
||||||
badges {
|
|
||||||
id
|
|
||||||
icon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
categories {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
icon
|
|
||||||
}
|
|
||||||
shoutedCount
|
|
||||||
shoutedByCurrentUser
|
|
||||||
emotionsCount
|
|
||||||
}
|
}
|
||||||
|
categories {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
icon
|
||||||
|
}
|
||||||
|
shoutedCount
|
||||||
|
shoutedByCurrentUser
|
||||||
|
emotionsCount
|
||||||
}
|
}
|
||||||
`
|
}
|
||||||
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
export const filterPosts = i18n => {
|
export const filterPosts = i18n => {
|
||||||
|
|||||||
@ -52,7 +52,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@human-connection/styleguide": "0.5.19",
|
"@human-connection/styleguide": "0.5.19",
|
||||||
"@nuxtjs/apollo": "^4.0.0-rc11",
|
"@nuxtjs/apollo": "^4.0.0-rc11",
|
||||||
"@nuxtjs/axios": "~5.5.4",
|
"@nuxtjs/axios": "~5.6.0",
|
||||||
"@nuxtjs/dotenv": "~1.4.0",
|
"@nuxtjs/dotenv": "~1.4.0",
|
||||||
"@nuxtjs/sentry": "^3.0.0",
|
"@nuxtjs/sentry": "^3.0.0",
|
||||||
"@nuxtjs/style-resources": "~1.0.0",
|
"@nuxtjs/style-resources": "~1.0.0",
|
||||||
@ -68,13 +68,13 @@
|
|||||||
"jsonwebtoken": "~8.5.1",
|
"jsonwebtoken": "~8.5.1",
|
||||||
"linkify-it": "~2.2.0",
|
"linkify-it": "~2.2.0",
|
||||||
"node-fetch": "^2.6.0",
|
"node-fetch": "^2.6.0",
|
||||||
"nuxt": "~2.8.1",
|
"nuxt": "~2.9.1",
|
||||||
"nuxt-dropzone": "^1.0.2",
|
"nuxt-dropzone": "^1.0.3",
|
||||||
"nuxt-env": "~0.1.0",
|
"nuxt-env": "~0.1.0",
|
||||||
"stack-utils": "^1.0.2",
|
"stack-utils": "^1.0.2",
|
||||||
"string-hash": "^1.1.3",
|
"string-hash": "^1.1.3",
|
||||||
"tiptap": "~1.24.2",
|
"tiptap": "~1.25.0",
|
||||||
"tiptap-extensions": "~1.26.2",
|
"tiptap-extensions": "~1.27.0",
|
||||||
"v-tooltip": "~2.0.2",
|
"v-tooltip": "~2.0.2",
|
||||||
"vue-count-to": "~1.0.13",
|
"vue-count-to": "~1.0.13",
|
||||||
"vue-infinite-scroll": "^2.0.2",
|
"vue-infinite-scroll": "^2.0.2",
|
||||||
@ -100,7 +100,7 @@
|
|||||||
"babel-loader": "~8.0.6",
|
"babel-loader": "~8.0.6",
|
||||||
"babel-preset-vue": "~2.0.2",
|
"babel-preset-vue": "~2.0.2",
|
||||||
"core-js": "~2.6.9",
|
"core-js": "~2.6.9",
|
||||||
"css-loader": "~2.1.1",
|
"css-loader": "~3.2.0",
|
||||||
"eslint": "~5.16.0",
|
"eslint": "~5.16.0",
|
||||||
"eslint-config-prettier": "~6.1.0",
|
"eslint-config-prettier": "~6.1.0",
|
||||||
"eslint-config-standard": "~12.0.0",
|
"eslint-config-standard": "~12.0.0",
|
||||||
|
|||||||
@ -159,7 +159,7 @@ export default {
|
|||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
slug: this.$route.params.slug,
|
id: this.$route.params.id,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import gql from 'graphql-tag'
|
|
||||||
import HcContributionForm from '~/components/ContributionForm/ContributionForm'
|
import HcContributionForm from '~/components/ContributionForm/ContributionForm'
|
||||||
|
import PostQuery from '~/graphql/PostQuery'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@ -36,38 +36,11 @@ export default {
|
|||||||
apollo: {
|
apollo: {
|
||||||
Post: {
|
Post: {
|
||||||
query() {
|
query() {
|
||||||
return gql(`
|
return PostQuery(this.$i18n)
|
||||||
query($id: ID!) {
|
|
||||||
Post(id: $id) {
|
|
||||||
id
|
|
||||||
title
|
|
||||||
content
|
|
||||||
createdAt
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
slug
|
|
||||||
image
|
|
||||||
language
|
|
||||||
author {
|
|
||||||
id
|
|
||||||
disabled
|
|
||||||
deleted
|
|
||||||
}
|
|
||||||
tags {
|
|
||||||
name
|
|
||||||
}
|
|
||||||
categories {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
icon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`)
|
|
||||||
},
|
},
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
id: this.$route.params.id || 'p1',
|
id: this.$route.params.id,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
|
|||||||
993
webapp/yarn.lock
993
webapp/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user