Set up some backend tests for emotions

This commit is contained in:
Matt Rider 2019-07-29 17:08:07 +02:00
parent 322ec597a3
commit 3e43539e23
5 changed files with 154 additions and 141 deletions

View File

@ -184,6 +184,7 @@ const permissions = shield(
requestPasswordReset: allow,
resetPassword: allow,
AddPostEmotions: isAuthenticated,
RemovePostEmotions: isAuthenticated,
},
User: {
email: isMyOwn,

View File

@ -71,5 +71,39 @@ export default {
return post.properties
},
AddPostEmotions: async (object, params, context, resolveInfo) => {
const session = context.driver.session()
const { from, to, data } = params
const transactionRes = await session.run(
`MATCH (userFrom:User {id: $from.id}), (postTo:Post {id: $to.id})
MERGE (userFrom)-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo)
RETURN userFrom, postTo, emotedRelation`,
{ from, to, data },
)
session.close()
const [emoted] = transactionRes.records.map(record => {
return {
from: { id: record.get('userFrom').properties.id },
to: { id: record.get('postTo').properties.id },
emotion: record.get('emotedRelation').properties.emotion,
}
})
return emoted
},
RemovePostEmotions: async (object, params, context, resolveInfo) => {
const session = context.driver.session()
const { from, to, data } = params
const transactionRes = await session.run(
`MATCH (userFrom:User {id: $from.id})-[emotedRelation:EMOTED {emotion: $data.emotion}]->(postTo:Post {id: $to.id})
DELETE emotedRelation
RETURN emotedRelation`,
{ from, to, data },
)
session.close()
const [removed] = transactionRes.records.map(record => {
return record.get('emotedRelation')
})
return !!removed
},
},
}

View File

@ -58,6 +58,7 @@ const postQueryFilteredByCategoryVariables = {
}
beforeEach(async () => {
userParams = {
id: 'u198',
name: 'TestUser',
email: 'test@example.org',
password: '1234',
@ -384,43 +385,59 @@ describe('DeletePost', () => {
})
})
describe('AddPostEmotions', () => {
describe('emotions', () => {
let addPostEmotionsVariables
const addPostEmotionsMutation = `
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
AddPostEmotions(from: $from, to: $to, data: $data) {
from {
id
}
to {
id
}
emotion
}
let postEmotionsVariables
beforeEach(async () => {
const asAuthor = Factory()
authorParams = {
id: 'u25',
email: 'wanna-add-emotions@example.org',
password: '1234',
}
`
describe('emotions', () => {
beforeEach(async () => {
const asAuthor = Factory()
authorParams = {
id: 'u25',
email: 'wanna-add-emotions@example.org',
password: '1234',
}
await asAuthor.create('User', authorParams)
await asAuthor.authenticateAs(authorParams)
await asAuthor.create('Post', {
id: 'p1376',
title: postTitle,
content: postContent,
})
addPostEmotionsVariables = {
from: { id: authorParams.id },
to: { id: 'p1376' },
data: { emotion: 'happy' },
}
await asAuthor.create('User', authorParams)
await asAuthor.authenticateAs(authorParams)
await asAuthor.create('Post', {
id: 'p1376',
title: postTitle,
content: postContent,
})
// it('supports setting emotions for a post', () => {})
addPostEmotionsVariables = {
from: { id: authorParams.id },
to: { id: 'p1376' },
data: { emotion: 'happy' },
}
postEmotionsVariables = {
id: 'p1376',
}
})
describe('AddPostEmotions', () => {
const addPostEmotionsMutation = `
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
AddPostEmotions(from: $from, to: $to, data: $data) {
from { id }
to { id }
emotion
}
}
`
const postEmotionsCountQuery = `
query($id: ID!) {
Post(id: $id) {
emotionsCount
}
}
`
const postEmotionsQuery = `
query($id: ID!) {
Post(id: $id) {
emotions {
emotion
}
}
}
`
describe('unauthenticated', () => {
it('throws authorization error', async () => {
@ -435,6 +452,52 @@ describe('AddPostEmotions', () => {
})
})
describe('authenticated and not the author', () => {
let headers
beforeEach(async () => {
headers = await login(userParams)
client = new GraphQLClient(host, { headers })
})
it('adds an emotion to the post', async () => {
addPostEmotionsVariables.from.id = userParams.id
const expected = {
AddPostEmotions: {
from: addPostEmotionsVariables.from,
to: addPostEmotionsVariables.to,
emotion: 'happy',
},
}
await expect(
client.request(addPostEmotionsMutation, addPostEmotionsVariables),
).resolves.toEqual(expected)
})
it('limits the addition of the same emotion to 1', async () => {
const expected = {
Post: [
{
emotionsCount: 1,
},
],
}
await client.request(addPostEmotionsMutation, addPostEmotionsVariables)
await client.request(addPostEmotionsMutation, addPostEmotionsVariables)
await expect(
client.request(postEmotionsCountQuery, postEmotionsVariables),
).resolves.toEqual(expected)
})
it('allows a user to add more than one emotion', async () => {
const expected = [{ emotion: 'happy' }, { emotion: 'surprised' }]
await client.request(addPostEmotionsMutation, addPostEmotionsVariables)
addPostEmotionsVariables.data.emotion = 'surprised'
await client.request(addPostEmotionsMutation, addPostEmotionsVariables)
await expect(client.request(postEmotionsQuery, postEmotionsVariables)).resolves.toEqual({
Post: [{ emotions: expect.arrayContaining(expected) }],
})
})
})
describe('authenticated as author', () => {
let headers
beforeEach(async () => {
@ -456,4 +519,24 @@ describe('AddPostEmotions', () => {
})
})
})
describe('RemovePostEmotions', () => {
const removePostEmotionsMutation = `
mutation($from: _UserInput!, $to: _PostInput!, $data: _EMOTEDInput!) {
RemovePostEmotions(from: $from, to: $to, data: $data)
}
`
describe('unauthenticated', () => {
it('throws authorization error', async () => {
client = new GraphQLClient(host)
await expect(
client.request(removePostEmotionsMutation, {
from: { id: 'u25' },
to: { id: 'p1376' },
data: { emotion: 'happy' },
}),
).rejects.toThrow('Not Authorised')
})
})
})
})

View File

@ -51,9 +51,7 @@ type Post {
emotions: [EMOTED]
emotionsCount: Int!
@cypher(
statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)"
)
@cypher(statement: "MATCH (this)<-[emoted:EMOTED]-(:User) RETURN COUNT(DISTINCT emoted)")
}
type Mutation {
@ -93,4 +91,5 @@ type Mutation {
language: String
categoryIds: [ID]
): Post
RemovePostEmotions(from: _UserInput!, to: _PostInput!, data: _EMOTEDInput!): Boolean!
}

View File

@ -2,13 +2,6 @@
# yarn lockfile v1
"@apollographql/apollo-tools@^0.3.6":
version "0.3.7"
resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.3.7.tgz#3bc9c35b9fff65febd4ddc0c1fc04677693a3d40"
integrity sha512-+ertvzAwzkYmuUtT8zH3Zi6jPdyxZwOgnYaZHY7iLnMVJDhQKWlkyjLMF8wyzlPiEdDImVUMm5lOIBZo7LkGlg==
dependencies:
apollo-env "0.5.1"
"@apollographql/apollo-tools@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@apollographql/apollo-tools/-/apollo-tools-0.4.0.tgz#8a1a0ab7a0bb12ccc03b72e4a104cfa5d969fd5f"
@ -1454,14 +1447,6 @@ anymatch@^2.0.0:
micromatch "^3.1.4"
normalize-path "^2.1.1"
apollo-cache-control@0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.0.tgz#08b157e5f8cd86f63608b05d45222de0725ebd5a"
integrity sha512-BBnfUmSWRws5dRSDD+R56RLJCE9v6xQuob+i/1Ju9EX4LZszU5JKVmxEvnkJ1bk/BkihjoQXTnP6fJCnt6fCmA==
dependencies:
apollo-server-env "2.4.0"
graphql-extensions "0.8.0"
apollo-cache-control@0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/apollo-cache-control/-/apollo-cache-control-0.8.1.tgz#707c0b958c02c5b47ddf49a02f60ea88a64783fb"
@ -1503,14 +1488,6 @@ apollo-client@~2.6.3:
tslib "^1.9.3"
zen-observable "^0.8.0"
apollo-datasource@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.6.0.tgz#823d6be8a3804613b5c56d2972c07db662293fc6"
integrity sha512-DOzzYWEOReYRu2vWPKEulqlTb9Xjg67sjVCzve5MXa7GUXjfr8IKioljvfoBMlqm/PpbJVk2ci4n5NIFqoYsrQ==
dependencies:
apollo-server-caching "0.5.0"
apollo-server-env "2.4.0"
apollo-datasource@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/apollo-datasource/-/apollo-datasource-0.6.1.tgz#697870f564da90bee53fa30d07875cb46c4d6b06"
@ -1526,18 +1503,6 @@ apollo-engine-reporting-protobuf@0.4.0:
dependencies:
protobufjs "^6.8.6"
apollo-engine-reporting@1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.0.tgz#3a9bd011b271593e16d7057044898d0a817b197d"
integrity sha512-NMiO3h1cuEBt6QZNGHxivwuyZQnoU/2MMx0gUA8Gyy1ERBhK6P235qoMnvoi34rLmqJuyGPX6tXcab8MpMIzYQ==
dependencies:
apollo-engine-reporting-protobuf "0.4.0"
apollo-graphql "^0.3.3"
apollo-server-env "2.4.0"
apollo-server-types "0.2.0"
async-retry "^1.2.1"
graphql-extensions "0.8.0"
apollo-engine-reporting@1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/apollo-engine-reporting/-/apollo-engine-reporting-1.4.2.tgz#f6c1e964c3c2c09bdb25c449f6b7ab05952ff459"
@ -1618,34 +1583,6 @@ apollo-server-caching@0.5.0:
dependencies:
lru-cache "^5.0.0"
apollo-server-core@2.7.0:
version "2.7.0"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.7.0.tgz#c444347dea11149b5b453890506e43dc7e711257"
integrity sha512-CXjXAkgcMBCJZpsZgfAY5W7f5thdxUhn75UgzeH28RTUZ2aKi/LjoCixPWRSF1lU4vuEWneAnM8Vg/KCD+29lQ==
dependencies:
"@apollographql/apollo-tools" "^0.3.6"
"@apollographql/graphql-playground-html" "1.6.24"
"@types/ws" "^6.0.0"
apollo-cache-control "0.8.0"
apollo-datasource "0.6.0"
apollo-engine-reporting "1.4.0"
apollo-engine-reporting-protobuf "0.4.0"
apollo-server-caching "0.5.0"
apollo-server-env "2.4.0"
apollo-server-errors "2.3.1"
apollo-server-plugin-base "0.6.0"
apollo-server-types "0.2.0"
apollo-tracing "0.8.0"
fast-json-stable-stringify "^2.0.0"
graphql-extensions "0.8.0"
graphql-subscriptions "^1.0.0"
graphql-tag "^2.9.2"
graphql-tools "^4.0.0"
graphql-upload "^8.0.2"
sha.js "^2.4.11"
subscriptions-transport-ws "^0.9.11"
ws "^6.0.0"
apollo-server-core@2.7.2:
version "2.7.2"
resolved "https://registry.yarnpkg.com/apollo-server-core/-/apollo-server-core-2.7.2.tgz#4acd9f4d0d235bef0e596e2a821326dfc07ae7b2"
@ -1672,14 +1609,6 @@ apollo-server-core@2.7.2:
subscriptions-transport-ws "^0.9.11"
ws "^6.0.0"
apollo-server-env@2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.0.tgz#6611556c6b627a1636eed31317d4f7ea30705872"
integrity sha512-7ispR68lv92viFeu5zsRUVGP+oxsVI3WeeBNniM22Cx619maBUwcYTIC3+Y3LpXILhLZCzA1FASZwusgSlyN9w==
dependencies:
node-fetch "^2.1.2"
util.promisify "^1.0.0"
apollo-server-env@2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/apollo-server-env/-/apollo-server-env-2.4.1.tgz#58264ecfeb151919e0f480320b4e3769be9f18f3"
@ -1713,13 +1642,6 @@ apollo-server-express@2.7.2, apollo-server-express@^2.7.2:
subscriptions-transport-ws "^0.9.16"
type-is "^1.6.16"
apollo-server-plugin-base@0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.0.tgz#4186296ea5d52cfe613961d252a8a2f9e13e6ba6"
integrity sha512-BjfyWpHyKwHOe819gk3wEFwbnVp9Xvos03lkkYTTcXS/8G7xO78aUcE65mmyAC56/ZQ0aodNFkFrhwNtWBQWUQ==
dependencies:
apollo-server-types "0.2.0"
apollo-server-plugin-base@0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/apollo-server-plugin-base/-/apollo-server-plugin-base-0.6.1.tgz#b9c209aa2102a26c6134f51bfa1e4a8307b63b11"
@ -1734,15 +1656,6 @@ apollo-server-testing@~2.7.2:
dependencies:
apollo-server-core "2.7.2"
apollo-server-types@0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.0.tgz#270d7298f709fd8237ebfa48753249e5286df5f2"
integrity sha512-5dgiyXsM90vnfmdXO1ixHvsLn0d9NP4tWufmr3ZmjKv00r4JAQNUaUdgOSGbRIKoHELQGwxUuTySTZ/tYfGaNQ==
dependencies:
apollo-engine-reporting-protobuf "0.4.0"
apollo-server-caching "0.5.0"
apollo-server-env "2.4.0"
apollo-server-types@0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-0.2.1.tgz#553da40ea1ad779ef0390c250ddad7eb782fdf64"
@ -1763,14 +1676,6 @@ apollo-server@~2.7.2:
graphql-subscriptions "^1.0.0"
graphql-tools "^4.0.0"
apollo-tracing@0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.0.tgz#28cd9c61a4db12b2c24dad67fdedd309806c1650"
integrity sha512-cNOtOlyZ56iJRsCjnxjM1V0SnQ2ZZttuyoeOejdat6llPfk5bfYTVOKMjdbSfDvU33LS9g9sqNJCT0MwrEPFKQ==
dependencies:
apollo-server-env "2.4.0"
graphql-extensions "0.8.0"
apollo-tracing@0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/apollo-tracing/-/apollo-tracing-0.8.1.tgz#220aeac6ad598c67f9333739155b7a56bd63ccab"
@ -4071,15 +3976,6 @@ graphql-custom-directives@~0.2.14:
moment "^2.22.2"
numeral "^2.0.6"
graphql-extensions@0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.8.0.tgz#b3fe7915aa84eef5a39135840840cc4d2e700c46"
integrity sha512-zV9RefkusIXqi9ZJtl7IJ5ecjDKdb7PLAb5E3CmxX3OK1GwNCIubp0vE7Fp4fXlCUKgTB1Woubs0zj71JT8o0A==
dependencies:
"@apollographql/apollo-tools" "^0.3.6"
apollo-server-env "2.4.0"
apollo-server-types "0.2.0"
graphql-extensions@0.8.1:
version "0.8.1"
resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.8.1.tgz#f5f1fed5fe49620c4e70c5d08bdbd0039e91c402"