diff --git a/backend/package.json b/backend/package.json
index 89fb87edf..80a611155 100644
--- a/backend/package.json
+++ b/backend/package.json
@@ -61,7 +61,7 @@
"dotenv": "~8.1.0",
"express": "^4.17.1",
"faker": "Marak/faker.js#master",
- "graphql": "^14.5.0",
+ "graphql": "^14.5.3",
"graphql-custom-directives": "~0.2.14",
"graphql-iso-date": "~3.6.1",
"graphql-middleware": "~3.0.5",
@@ -116,7 +116,7 @@
"babel-jest": "~24.9.0",
"chai": "~4.2.0",
"cucumber": "~5.1.0",
- "eslint": "~6.2.1",
+ "eslint": "~6.2.2",
"eslint-config-prettier": "~6.1.0",
"eslint-config-standard": "~14.0.1",
"eslint-plugin-import": "~2.18.2",
diff --git a/backend/src/middleware/handleHtmlContent/handleContentData.js b/backend/src/middleware/handleHtmlContent/handleContentData.js
deleted file mode 100644
index 403b2044e..000000000
--- a/backend/src/middleware/handleHtmlContent/handleContentData.js
+++ /dev/null
@@ -1,96 +0,0 @@
-import extractMentionedUsers from './notifications/extractMentionedUsers'
-import extractHashtags from './hashtags/extractHashtags'
-
-const notifyMentions = async (label, id, idsOfMentionedUsers, context) => {
- if (!idsOfMentionedUsers.length) return
-
- const session = context.driver.session()
- const createdAt = new Date().toISOString()
- let cypher
- if (label === 'Post') {
- cypher = `
- MATCH (post: Post { id: $id })<-[:WROTE]-(author: User)
- MATCH (user: User)
- WHERE user.id in $idsOfMentionedUsers
- AND NOT (user)<-[:BLOCKED]-(author)
- CREATE (notification: Notification {id: apoc.create.uuid(), read: false, createdAt: $createdAt })
- MERGE (post)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
- `
- } else {
- cypher = `
- MATCH (postAuthor: User)-[:WROTE]->(post: Post)<-[:COMMENTS]-(comment: Comment { id: $id })<-[:WROTE]-(author: User)
- MATCH (user: User)
- WHERE user.id in $idsOfMentionedUsers
- AND NOT (user)<-[:BLOCKED]-(author)
- AND NOT (user)<-[:BLOCKED]-(postAuthor)
- CREATE (notification: Notification {id: apoc.create.uuid(), read: false, createdAt: $createdAt })
- MERGE (comment)-[:NOTIFIED]->(notification)-[:NOTIFIED]->(user)
- `
- }
- await session.run(cypher, {
- idsOfMentionedUsers,
- label,
- createdAt,
- id,
- })
- session.close()
-}
-
-const updateHashtagsOfPost = async (postId, hashtags, context) => {
- if (!hashtags.length) return
-
- const session = context.driver.session()
- // We need two Cypher statements, because the 'MATCH' in the 'cypherDeletePreviousRelations' statement
- // functions as an 'if'. In case there is no previous relation, the rest of the commands are omitted
- // and no new Hashtags and relations will be created.
- const cypherDeletePreviousRelations = `
- MATCH (p: Post { id: $postId })-[previousRelations: TAGGED]->(t: Tag)
- DELETE previousRelations
- RETURN p, t
- `
- const cypherCreateNewTagsAndRelations = `
- MATCH (p: Post { id: $postId})
- UNWIND $hashtags AS tagName
- MERGE (t: Tag { id: tagName, disabled: false, deleted: false })
- MERGE (p)-[:TAGGED]->(t)
- RETURN p, t
- `
- await session.run(cypherDeletePreviousRelations, {
- postId,
- })
- await session.run(cypherCreateNewTagsAndRelations, {
- postId,
- hashtags,
- })
- session.close()
-}
-
-const handleContentDataOfPost = async (resolve, root, args, context, resolveInfo) => {
- const idsOfMentionedUsers = extractMentionedUsers(args.content)
- const hashtags = extractHashtags(args.content)
-
- const post = await resolve(root, args, context, resolveInfo)
-
- await notifyMentions('Post', post.id, idsOfMentionedUsers, context)
- await updateHashtagsOfPost(post.id, hashtags, context)
-
- return post
-}
-
-const handleContentDataOfComment = async (resolve, root, args, context, resolveInfo) => {
- const idsOfMentionedUsers = extractMentionedUsers(args.content)
- const comment = await resolve(root, args, context, resolveInfo)
-
- await notifyMentions('Comment', comment.id, idsOfMentionedUsers, context)
-
- return comment
-}
-
-export default {
- Mutation: {
- CreatePost: handleContentDataOfPost,
- UpdatePost: handleContentDataOfPost,
- CreateComment: handleContentDataOfComment,
- UpdateComment: handleContentDataOfComment,
- },
-}
diff --git a/backend/src/middleware/handleHtmlContent/handleContentData.spec.js b/backend/src/middleware/handleHtmlContent/handleContentData.spec.js
deleted file mode 100644
index 2925f92cf..000000000
--- a/backend/src/middleware/handleHtmlContent/handleContentData.spec.js
+++ /dev/null
@@ -1,392 +0,0 @@
-import { gql } from '../../jest/helpers'
-import Factory from '../../seed/factories'
-import { createTestClient } from 'apollo-server-testing'
-import { neode, getDriver } from '../../bootstrap/neo4j'
-import createServer from '../../server'
-
-let server
-let query
-let mutate
-let user
-let authenticatedUser
-const factory = Factory()
-const driver = getDriver()
-const instance = neode()
-const categoryIds = ['cat9']
-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 updatePostMutation = gql`
- mutation($id: ID!, $title: String!, $content: String!, $categoryIds: [ID]!) {
- UpdatePost(id: $id, content: $content, title: $title, categoryIds: $categoryIds) {
- title
- content
- }
- }
-`
-
-beforeAll(() => {
- const createServerResult = createServer({
- context: () => {
- return {
- user: authenticatedUser,
- neode: instance,
- driver,
- }
- },
- })
- server = createServerResult.server
- const createTestClientResult = createTestClient(server)
- query = createTestClientResult.query
- mutate = createTestClientResult.mutate
-})
-
-beforeEach(async () => {
- user = await instance.create('User', {
- id: 'you',
- name: 'Al Capone',
- slug: 'al-capone',
- email: 'test@example.org',
- password: '1234',
- })
- await instance.create('Category', {
- id: 'cat9',
- name: 'Democracy & Politics',
- icon: 'university',
- })
-})
-
-afterEach(async () => {
- await factory.cleanDatabase()
-})
-
-describe('notifications', () => {
- const notificationQuery = gql`
- query($read: Boolean) {
- currentUser {
- notifications(read: $read, orderBy: createdAt_desc) {
- read
- post {
- content
- }
- comment {
- content
- }
- }
- }
- }
- `
-
- describe('authenticated', () => {
- beforeEach(async () => {
- authenticatedUser = user
- })
-
- describe('given another user', () => {
- let postAuthor
- beforeEach(async () => {
- postAuthor = await instance.create('User', {
- email: 'post-author@example.org',
- password: '1234',
- id: 'postAuthor',
- })
- })
-
- describe('who mentions me in a post', () => {
- const title = 'Mentioning Al Capone'
- const content =
- 'Hey @al-capone how do you do?'
-
- const createPostAction = async () => {
- authenticatedUser = await postAuthor.toJson()
- await mutate({
- mutation: createPostMutation,
- variables: { id: 'p47', title, content, categoryIds },
- })
- authenticatedUser = await user.toJson()
- }
-
- it('sends you a notification', async () => {
- await createPostAction()
- const expectedContent =
- 'Hey @al-capone how do you do?'
- const expected = expect.objectContaining({
- data: {
- currentUser: {
- notifications: [
- {
- read: false,
- post: {
- content: expectedContent,
- },
- comment: null,
- },
- ],
- },
- },
- })
- const { query } = createTestClient(server)
- await expect(
- query({
- query: notificationQuery,
- variables: {
- read: false,
- },
- }),
- ).resolves.toEqual(expected)
- })
-
- describe('who mentions me many times', () => {
- const updatePostAction = async () => {
- const updatedContent = `
- One more mention to
-
- @al-capone
-
- and again:
-
- @al-capone
-
- and again
-
- @al-capone
-
- `
- authenticatedUser = await postAuthor.toJson()
- await mutate({
- mutation: updatePostMutation,
- variables: {
- id: 'p47',
- title,
- content: updatedContent,
- categoryIds,
- },
- })
- authenticatedUser = await user.toJson()
- }
-
- it('creates exactly one more notification', async () => {
- await createPostAction()
- await updatePostAction()
- const expectedContent =
- ' Hey Dude, #Democracy should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone. Hey Dude, #Elections should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone. Hey Dude, #Democracy should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone. Hey Dude, #Elections should work equal for everybody!? That seems to be the only way to have equal #Liberty for everyone.
One more mention to
@al-capone
and again:
@al-capone
and again
@al-capone
'
- const expected = expect.objectContaining({
- data: {
- currentUser: {
- notifications: [
- {
- read: false,
- post: {
- content: expectedContent,
- },
- comment: null,
- },
- {
- read: false,
- post: {
- content: expectedContent,
- },
- comment: null,
- },
- ],
- },
- },
- })
- await expect(
- query({
- query: notificationQuery,
- variables: {
- read: false,
- },
- }),
- ).resolves.toEqual(expected)
- })
- })
-
- describe('but the author of the post blocked me', () => {
- beforeEach(async () => {
- await postAuthor.relateTo(user, 'blocked')
- })
-
- it('sends no notification', async () => {
- await createPostAction()
- const expected = expect.objectContaining({
- data: {
- currentUser: {
- notifications: [],
- },
- },
- })
- const { query } = createTestClient(server)
- await expect(
- query({
- query: notificationQuery,
- variables: {
- read: false,
- },
- }),
- ).resolves.toEqual(expected)
- })
- })
-
- describe('but the author of the post blocked me and a mentioner mentions me in a comment', () => {
- const createCommentOnPostAction = async () => {
- await createPostAction()
- const createCommentMutation = gql`
- mutation($id: ID, $postId: ID!, $commentContent: String!) {
- CreateComment(id: $id, postId: $postId, content: $commentContent) {
- id
- content
- }
- }
- `
- authenticatedUser = await commentMentioner.toJson()
- await mutate({
- mutation: createCommentMutation,
- variables: {
- id: 'c47',
- postId: 'p47',
- commentContent:
- 'One mention of me with .',
- },
- })
- authenticatedUser = await user.toJson()
- }
- let commentMentioner
-
- beforeEach(async () => {
- await postAuthor.relateTo(user, 'blocked')
- commentMentioner = await instance.create('User', {
- id: 'mentioner',
- name: 'Mr Mentioner',
- slug: 'mr-mentioner',
- email: 'mentioner@example.org',
- password: '1234',
- })
- })
-
- it('sends no notification', async () => {
- await createCommentOnPostAction()
- const expected = expect.objectContaining({
- data: {
- currentUser: {
- notifications: [],
- },
- },
- })
- const { query } = createTestClient(server)
- await expect(
- query({
- query: notificationQuery,
- variables: {
- read: false,
- },
- }),
- ).resolves.toEqual(expected)
- })
- })
- })
- })
- })
-})
-
-describe('Hashtags', () => {
- const id = 'p135'
- const title = 'Two Hashtags'
- const content =
- '
One more mention to
@al-capone
and again:
@al-capone
and again
@al-capone
'
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [
+ {
+ read: false,
+ reason: 'mentioned_in_post',
+ post: {
+ content: expectedContent,
+ },
+ comment: null,
+ },
+ {
+ read: false,
+ reason: 'mentioned_in_post',
+ post: {
+ content: expectedContent,
+ },
+ comment: null,
+ },
+ ],
+ },
+ },
+ })
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+
+ describe('but the author of the post blocked me', () => {
+ beforeEach(async () => {
+ await postAuthor.relateTo(notifiedUser, 'blocked')
+ })
+
+ it('sends no notification', async () => {
+ await createPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+ })
+
+ describe('mentions me in a comment', () => {
+ beforeEach(async () => {
+ title = 'Post where I get mentioned in a comment'
+ postContent = 'Content of post where I get mentioned in a comment.'
+ })
+
+ describe('I am not blocked at all', () => {
+ beforeEach(async () => {
+ commentContent =
+ 'One mention about me with @al-capone.'
+ commentAuthor = await instance.create('User', {
+ id: 'commentAuthor',
+ name: 'Mrs Comment',
+ slug: 'mrs-comment',
+ email: 'comment-author@example.org',
+ password: '1234',
+ })
+ })
+
+ it('sends a notification', async () => {
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [
+ {
+ read: false,
+ reason: 'mentioned_in_comment',
+ post: null,
+ comment: {
+ content: commentContent,
+ },
+ },
+ ],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+
+ describe('but the author of the post blocked me', () => {
+ beforeEach(async () => {
+ await postAuthor.relateTo(notifiedUser, 'blocked')
+ commentContent =
+ 'One mention about me with @al-capone.'
+ commentAuthor = await instance.create('User', {
+ id: 'commentAuthor',
+ name: 'Mrs Comment',
+ slug: 'mrs-comment',
+ email: 'comment-author@example.org',
+ password: '1234',
+ })
+ })
+
+ it('sends no notification', async () => {
+ await createCommentOnPostAction()
+ const expected = expect.objectContaining({
+ data: {
+ currentUser: {
+ notifications: [],
+ },
+ },
+ })
+ const { query } = createTestClient(server)
+ await expect(
+ query({
+ query: notificationQuery,
+ variables: {
+ read: false,
+ },
+ }),
+ ).resolves.toEqual(expected)
+ })
+ })
+ })
+ })
+ })
+})
diff --git a/backend/src/models/Notification.js b/backend/src/models/Notification.js
index b8690b8c1..b54a99574 100644
--- a/backend/src/models/Notification.js
+++ b/backend/src/models/Notification.js
@@ -1,9 +1,26 @@
import uuid from 'uuid/v4'
module.exports = {
- id: { type: 'uuid', primary: true, default: uuid },
- createdAt: { type: 'string', isoDate: true, default: () => new Date().toISOString() },
- read: { type: 'boolean', default: false },
+ id: {
+ type: 'uuid',
+ primary: true,
+ default: uuid,
+ },
+ read: {
+ type: 'boolean',
+ default: false,
+ },
+ reason: {
+ type: 'string',
+ valid: ['mentioned_in_post', 'mentioned_in_comment', 'comment_on_post'],
+ invalid: [null],
+ default: 'mentioned_in_post',
+ },
+ createdAt: {
+ type: 'string',
+ isoDate: true,
+ default: () => new Date().toISOString(),
+ },
user: {
type: 'relationship',
relationship: 'NOTIFIED',
diff --git a/backend/src/schema/resolvers/notifications.spec.js b/backend/src/schema/resolvers/notifications.spec.js
index 6b173514f..3ca7727e4 100644
--- a/backend/src/schema/resolvers/notifications.spec.js
+++ b/backend/src/schema/resolvers/notifications.spec.js
@@ -69,23 +69,29 @@ describe('currentUser notifications', () => {
factory.create('User', neighborParams),
factory.create('Notification', {
id: 'post-mention-not-for-you',
+ reason: 'mentioned_in_post',
}),
factory.create('Notification', {
id: 'post-mention-already-seen',
read: true,
+ reason: 'mentioned_in_post',
}),
factory.create('Notification', {
id: 'post-mention-unseen',
+ reason: 'mentioned_in_post',
}),
factory.create('Notification', {
id: 'comment-mention-not-for-you',
+ reason: 'mentioned_in_comment',
}),
factory.create('Notification', {
id: 'comment-mention-already-seen',
read: true,
+ reason: 'mentioned_in_comment',
}),
factory.create('Notification', {
id: 'comment-mention-unseen',
+ reason: 'mentioned_in_comment',
}),
])
await factory.authenticateAs(neighborParams)
@@ -287,9 +293,11 @@ describe('UpdateNotification', () => {
factory.create('User', mentionedParams),
factory.create('Notification', {
id: 'post-mention-to-be-updated',
+ reason: 'mentioned_in_post',
}),
factory.create('Notification', {
id: 'comment-mention-to-be-updated',
+ reason: 'mentioned_in_comment',
}),
])
await factory.authenticateAs(userParams)
diff --git a/backend/src/schema/types/enum/ReasonNotification.gql b/backend/src/schema/types/enum/ReasonNotification.gql
new file mode 100644
index 000000000..a66c446be
--- /dev/null
+++ b/backend/src/schema/types/enum/ReasonNotification.gql
@@ -0,0 +1,5 @@
+enum ReasonNotification {
+ mentioned_in_post
+ mentioned_in_comment
+ comment_on_post
+}
\ No newline at end of file
diff --git a/backend/src/schema/types/type/Notification.gql b/backend/src/schema/types/type/Notification.gql
index 0f94c2301..a3543445f 100644
--- a/backend/src/schema/types/type/Notification.gql
+++ b/backend/src/schema/types/type/Notification.gql
@@ -1,8 +1,9 @@
type Notification {
id: ID!
read: Boolean
+ reason: ReasonNotification
+ createdAt: String
user: User @relation(name: "NOTIFIED", direction: "OUT")
post: Post @relation(name: "NOTIFIED", direction: "IN")
comment: Comment @relation(name: "NOTIFIED", direction: "IN")
- createdAt: String
}
diff --git a/backend/src/seed/factories/index.js b/backend/src/seed/factories/index.js
index df3886a6c..56518bd06 100644
--- a/backend/src/seed/factories/index.js
+++ b/backend/src/seed/factories/index.js
@@ -62,15 +62,26 @@ export default function Factory(options = {}) {
lastResponse: null,
neodeInstance,
async authenticateAs({ email, password }) {
- const headers = await authenticatedHeaders({ email, password }, seedServerHost)
+ const headers = await authenticatedHeaders(
+ {
+ email,
+ password,
+ },
+ seedServerHost,
+ )
this.lastResponse = headers
- this.graphQLClient = new GraphQLClient(seedServerHost, { headers })
+ this.graphQLClient = new GraphQLClient(seedServerHost, {
+ headers,
+ })
return this
},
async create(node, args = {}) {
const { factory, mutation, variables } = this.factories[node](args)
if (factory) {
- this.lastResponse = await factory({ args, neodeInstance })
+ this.lastResponse = await factory({
+ args,
+ neodeInstance,
+ })
return this.lastResponse
} else {
this.lastResponse = await this.graphQLClient.request(mutation, variables)
@@ -121,11 +132,15 @@ export default function Factory(options = {}) {
},
async invite({ email }) {
const mutation = ` mutation($email: String!) { invite( email: $email) } `
- this.lastResponse = await this.graphQLClient.request(mutation, { email })
+ this.lastResponse = await this.graphQLClient.request(mutation, {
+ email,
+ })
return this
},
async cleanDatabase() {
- this.lastResponse = await cleanDatabase({ driver: this.neo4jDriver })
+ this.lastResponse = await cleanDatabase({
+ driver: this.neo4jDriver,
+ })
return this
},
async emote({ to, data }) {
diff --git a/backend/yarn.lock b/backend/yarn.lock
index 2f6f02d8e..6abdfaf0c 100644
--- a/backend/yarn.lock
+++ b/backend/yarn.lock
@@ -1407,7 +1407,7 @@ acorn-globals@^4.1.0:
acorn "^6.0.1"
acorn-walk "^6.0.1"
-acorn-jsx@^5.0.0:
+acorn-jsx@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.0.2.tgz#84b68ea44b373c4f8686023a551f61a21b7c4a4f"
integrity sha512-tiNTrP1MP0QrChmD2DdupCr6HWSFeKVw5d/dHTu4Y7rkAkRhU/Dt7dphAfIUyxtHpl/eBVip5uTNSpQJHylpAw==
@@ -3395,10 +3395,10 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
-eslint@~6.2.1:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.1.tgz#66c2e4fe8b6356b9f01e828adc3ad04030122df1"
- integrity sha512-ES7BzEzr0Q6m5TK9i+/iTpKjclXitOdDK4vT07OqbkBT2/VcN/gO9EL1C4HlK3TAOXYv2ItcmbVR9jO1MR0fJg==
+eslint@~6.2.2:
+ version "6.2.2"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.2.2.tgz#03298280e7750d81fcd31431f3d333e43d93f24f"
+ integrity sha512-mf0elOkxHbdyGX1IJEUsNBzCDdyoUgljF3rRlgfyYh0pwGnreLc0jjD6ZuleOibjmnUWZLY2eXwSooeOgGJ2jw==
dependencies:
"@babel/code-frame" "^7.0.0"
ajv "^6.10.0"
@@ -3409,7 +3409,7 @@ eslint@~6.2.1:
eslint-scope "^5.0.0"
eslint-utils "^1.4.2"
eslint-visitor-keys "^1.1.0"
- espree "^6.1.0"
+ espree "^6.1.1"
esquery "^1.0.1"
esutils "^2.0.2"
file-entry-cache "^5.0.1"
@@ -3438,13 +3438,13 @@ eslint@~6.2.1:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
-espree@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.0.tgz#a1e8aa65bf29a331d70351ed814a80e7534e0884"
- integrity sha512-boA7CHRLlVWUSg3iL5Kmlt/xT3Q+sXnKoRYYzj1YeM10A76TEJBbotV5pKbnK42hEUIr121zTv+QLRM5LsCPXQ==
+espree@^6.1.1:
+ version "6.1.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.1.tgz#7f80e5f7257fc47db450022d723e356daeb1e5de"
+ integrity sha512-EYbr8XZUhWbYCqQRW0duU5LxzL5bETN6AjKBGy1302qqzPaCH10QbRg3Wvco79Z8x9WbiE8HYB4e75xl6qUYvQ==
dependencies:
acorn "^7.0.0"
- acorn-jsx "^5.0.0"
+ acorn-jsx "^5.0.2"
eslint-visitor-keys "^1.1.0"
esprima@^3.1.3:
@@ -4193,10 +4193,10 @@ graphql-upload@^8.0.2:
http-errors "^1.7.2"
object-path "^0.11.4"
-graphql@^14.2.1, graphql@^14.5.0:
- version "14.5.0"
- resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.0.tgz#4801e6460942c9c591944617f6dd224a9e531520"
- integrity sha512-wnGcTD181L2xPnIwHHjx/moV4ulxA2Kms9zcUY+B/SIrK+2N+iOC6WNgnR2zVTmg1Z8P+CZq5KXibTnatg3WUw==
+graphql@^14.2.1, graphql@^14.5.3:
+ version "14.5.3"
+ resolved "https://registry.yarnpkg.com/graphql/-/graphql-14.5.3.tgz#e025851cc413e153220f4edbbb25d49f55104fa0"
+ integrity sha512-W8A8nt9BsMg0ZK2qA3DJIVU6muWhxZRYLTmc+5XGwzWzVdUdPVlAAg5hTBjiTISEnzsKL/onasu6vl3kgGTbYg==
dependencies:
iterall "^1.2.2"
diff --git a/cypress/README.md b/cypress/README.md
index 92b1b8185..2dd662a66 100644
--- a/cypress/README.md
+++ b/cypress/README.md
@@ -1,6 +1,16 @@
# End-to-End Testing
-## Configure cypress
+## Setup with docker
+
+Are you running everything through docker? You're so lucky you don't have to
+setup anything!
+
+Just:
+```
+docker-compose up
+```
+
+## Setup without docker
First, you have to tell cypress how to connect to your local neo4j database
among other things. You can copy our template configuration and change the new
@@ -11,16 +21,15 @@ Make sure you are at the root level of the project. Then:
# in the top level folder Human-Connection/
$ cp cypress.env.template.json cypress.env.json
```
-
-## Run Tests
-
-To run the tests, do this:
+To start the services that are required for cypress testing, run this:
```bash
# in the top level folder Human-Connection/
$ yarn cypress:setup
```
+## Run cypress
+
After verifying that there are no errors with the servers starting, open another tab in your terminal and run the following command:
```bash
@@ -29,13 +38,12 @@ $ yarn cypress:run

-After the test runs, you will also get some video footage of the test run which you can then analyse in more detail.
-## Open Interactive Test Console
+### Open Interactive Test Console
If you are like me, you might want to see some visual output. The interactive cypress environment also helps at debugging your tests, you can even time travel between individual steps and see the exact state of the app.
-To use this feature, you will still run the `yarn cypress:setup` above, but instead of `yarn cypress:run` open another tab in your terminal and run the following command:
+To use this feature, instead of `yarn cypress:run` you would run the following command:
```bash
$ yarn cypress:open
diff --git a/deployment/digital-ocean/https/templates/ingress.template.yaml b/deployment/digital-ocean/https/templates/ingress.template.yaml
index 9d0068e08..a1af35bc7 100644
--- a/deployment/digital-ocean/https/templates/ingress.template.yaml
+++ b/deployment/digital-ocean/https/templates/ingress.template.yaml
@@ -7,20 +7,21 @@ metadata:
kubernetes.io/ingress.class: "nginx"
certmanager.k8s.io/issuer: "letsencrypt-staging"
certmanager.k8s.io/acme-challenge-type: http01
+ nginx.ingress.kubernetes.io/proxy-body-size: 6m
spec:
tls:
- - hosts:
- # - nitro-mailserver.human-connection.org
- - nitro-staging.human-connection.org
- secretName: tls
+ - hosts:
+ # - nitro-mailserver.human-connection.org
+ - nitro-staging.human-connection.org
+ secretName: tls
rules:
- - host: nitro-staging.human-connection.org
- http:
- paths:
- - path: /
- backend:
- serviceName: nitro-web
- servicePort: 3000
+ - host: nitro-staging.human-connection.org
+ http:
+ paths:
+ - path: /
+ backend:
+ serviceName: nitro-web
+ servicePort: 3000
# - host: nitro-mailserver.human-connection.org
# http:
# paths:
diff --git a/deployment/human-connection/deployment-neo4j.yaml b/deployment/human-connection/deployment-neo4j.yaml
index 2fcba9061..297f4b551 100644
--- a/deployment/human-connection/deployment-neo4j.yaml
+++ b/deployment/human-connection/deployment-neo4j.yaml
@@ -25,13 +25,20 @@
- name: nitro-neo4j
image: humanconnection/neo4j:latest
imagePullPolicy: Always
+ resources:
+ requests:
+ memory: "1G"
+ limits:
+ memory: "2G"
env:
- name: NEO4J_apoc_import_file_enabled
value: "true"
- name: NEO4J_dbms_memory_pagecache_size
- value: 1G
+ value: "490M"
- name: NEO4J_dbms_memory_heap_max__size
- value: 1G
+ value: "500M"
+ - name: NEO4J_dbms_memory_heap_initial__size
+ value: "500M"
- name: NEO4J_dbms_security_procedures_unrestricted
value: "algo.*,apoc.*"
envFrom:
diff --git a/deployment/legacy-migration/maintenance-worker/migration/mongo/.env b/deployment/legacy-migration/maintenance-worker/migration/mongo/.env
index 4c5f9e18c..13c36c143 100644
--- a/deployment/legacy-migration/maintenance-worker/migration/mongo/.env
+++ b/deployment/legacy-migration/maintenance-worker/migration/mongo/.env
@@ -12,6 +12,6 @@
# On Windows this resolves to C:\Users\dornhoeschen\AppData\Local\Temp\mongo-export (MinGW)
EXPORT_PATH='/tmp/mongo-export/'
EXPORT_MONGOEXPORT_BIN='mongoexport'
-MONGO_EXPORT_SPLIT_SIZE=100
+MONGO_EXPORT_SPLIT_SIZE=4000
# On Windows use something like this
# EXPORT_MONGOEXPORT_BIN='C:\Program Files\MongoDB\Server\3.6\bin\mongoexport.exe'
diff --git a/docker-compose.override.yml b/docker-compose.override.yml
index 016984d3b..41a88970f 100644
--- a/docker-compose.override.yml
+++ b/docker-compose.override.yml
@@ -16,6 +16,30 @@ services:
- webapp_node_modules:/nitro-web/node_modules
command: yarn run dev
user: root
+ factories:
+ image: humanconnection/nitro-backend:builder
+ build:
+ context: backend
+ target: builder
+ ports:
+ - 4001:4001
+ networks:
+ - hc-network
+ volumes:
+ - ./backend:/nitro-backend
+ - factories_node_modules:/nitro-backend/node_modules
+ - uploads:/nitro-backend/public/uploads
+ depends_on:
+ - neo4j
+ environment:
+ - NEO4J_URI=bolt://neo4j:7687
+ - GRAPHQL_PORT=4000
+ - GRAPHQL_URI=http://localhost:4000
+ - CLIENT_URI=http://localhost:3000
+ - JWT_SECRET=b/&&7b78BF&fv/Vd
+ - MAPBOX_TOKEN=pk.eyJ1IjoiaHVtYW4tY29ubmVjdGlvbiIsImEiOiJjajl0cnBubGoweTVlM3VwZ2lzNTNud3ZtIn0.KZ8KK9l70omjXbEkkbHGsQ
+ - PRIVATE_KEY_PASSPHRASE=a7dsf78sadg87ad87sfagsadg78
+ command: yarn run test:before:seeder
backend:
image: humanconnection/nitro-backend:builder
build:
@@ -42,5 +66,6 @@ services:
volumes:
webapp_node_modules:
backend_node_modules:
+ factories_node_modules:
neo4j-data:
uploads:
diff --git a/package.json b/package.json
index 30f122f08..31670214e 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
"codecov": "^3.5.0",
"cross-env": "^5.2.0",
"cypress": "^3.4.1",
- "cypress-cucumber-preprocessor": "^1.15.0",
+ "cypress-cucumber-preprocessor": "^1.15.1",
"cypress-file-upload": "^3.3.3",
"cypress-plugin-retries": "^1.2.2",
"dotenv": "^8.1.0",
@@ -34,4 +34,4 @@
"npm-run-all": "^4.1.5",
"slug": "^1.1.0"
}
-}
\ No newline at end of file
+}
diff --git a/webapp/components/Comment.spec.js b/webapp/components/Comment.spec.js
index 4fdc48bbd..b9be448e4 100644
--- a/webapp/components/Comment.spec.js
+++ b/webapp/components/Comment.spec.js
@@ -8,7 +8,7 @@ const localVue = createLocalVue()
localVue.use(Vuex)
localVue.use(Styleguide)
-config.stubs['no-ssr'] = '