mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge pull request #171 from Human-Connection/123-unit-test-for-report-mutation
[WIP] Start unit testing report feature
This commit is contained in:
commit
ed5e206dc6
@ -1,20 +1,18 @@
|
||||
import { v1 as neo4j } from 'neo4j-driver'
|
||||
import dotenv from 'dotenv'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
let driver
|
||||
|
||||
export default function () {
|
||||
return {
|
||||
getDriver () {
|
||||
if (!driver) {
|
||||
driver = neo4j.driver(
|
||||
process.env.NEO4J_URI || 'bolt://localhost:7687',
|
||||
neo4j.auth.basic(
|
||||
process.env.NEO4J_USER || 'neo4j',
|
||||
process.env.NEO4J_PASSWORD || 'neo4j'
|
||||
)
|
||||
)
|
||||
}
|
||||
return driver
|
||||
}
|
||||
export function getDriver (options = {}) {
|
||||
const {
|
||||
uri = process.env.NEO4J_URI || 'bolt://localhost:7687',
|
||||
username = process.env.NEO4J_USERNAME || 'neo4j',
|
||||
password = process.env.NEO4J_PASSWORD || 'neo4j'
|
||||
} = options
|
||||
if (!driver) {
|
||||
driver = neo4j.driver(uri, neo4j.auth.basic(username, password))
|
||||
}
|
||||
return driver
|
||||
}
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import { request } from 'graphql-request'
|
||||
import { create, cleanDatabase } from './seed/factories'
|
||||
import { GraphQLClient, request } from 'graphql-request'
|
||||
import Factory from './seed/factories'
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { host } from './jest/helpers'
|
||||
import { host, login } from './jest/helpers'
|
||||
|
||||
const factory = Factory()
|
||||
|
||||
describe('login', () => {
|
||||
const mutation = (params) => {
|
||||
@ -16,14 +18,14 @@ describe('login', () => {
|
||||
|
||||
describe('given an existing user', () => {
|
||||
beforeEach(async () => {
|
||||
await create('user', {
|
||||
await factory.create('user', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await cleanDatabase()
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('asking for a `token`', () => {
|
||||
@ -60,3 +62,66 @@ describe('login', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('report', () => {
|
||||
beforeEach(async () => {
|
||||
await factory.create('user', {
|
||||
email: 'test@example.org',
|
||||
password: '1234'
|
||||
})
|
||||
await factory.create('user', {
|
||||
id: 'u2',
|
||||
name: 'abusive-user',
|
||||
role: 'user',
|
||||
email: 'abusive-user@example.org'
|
||||
})
|
||||
})
|
||||
|
||||
afterEach(async () => {
|
||||
await factory.cleanDatabase()
|
||||
})
|
||||
|
||||
describe('unauthenticated', () => {
|
||||
let client
|
||||
it('throws authorization error', async () => {
|
||||
client = new GraphQLClient(host)
|
||||
await expect(
|
||||
client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`)
|
||||
).rejects.toThrow('Not Authorised')
|
||||
})
|
||||
|
||||
describe('authenticated', () => {
|
||||
let headers
|
||||
let response
|
||||
beforeEach(async () => {
|
||||
headers = await login({ email: 'test@example.org', password: '1234' })
|
||||
client = new GraphQLClient(host, { headers })
|
||||
response = await client.request(`mutation {
|
||||
report(
|
||||
description: "I don't like this user",
|
||||
resource: {
|
||||
id: "u2",
|
||||
type: user
|
||||
}
|
||||
) { id, createdAt }
|
||||
}`,
|
||||
{ headers }
|
||||
)
|
||||
})
|
||||
it('creates a report', () => {
|
||||
let { id, createdAt } = response.report
|
||||
expect(response).toEqual({
|
||||
report: { id, createdAt }
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
import { request } from 'graphql-request'
|
||||
|
||||
// this is the to-be-tested server host
|
||||
// not to be confused with the seeder host
|
||||
export const host = 'http://127.0.0.1:4123'
|
||||
|
||||
export async function authenticatedHeaders ({ email, password }) {
|
||||
export async function login ({ email, password }) {
|
||||
const mutation = `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}"){
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { create, cleanDatabase } from '../seed/factories'
|
||||
import { host, authenticatedHeaders } from '../jest/helpers'
|
||||
import { host, login } from '../jest/helpers'
|
||||
import { GraphQLClient } from 'graphql-request'
|
||||
|
||||
describe('authorization', () => {
|
||||
@ -45,7 +45,7 @@ describe('authorization', () => {
|
||||
|
||||
describe('as owner', () => {
|
||||
it('exposes the owner\'s email address', async () => {
|
||||
headers = await authenticatedHeaders({
|
||||
headers = await login({
|
||||
email: 'owner@example.org',
|
||||
password: 'iamtheowner'
|
||||
})
|
||||
@ -55,7 +55,7 @@ describe('authorization', () => {
|
||||
|
||||
describe('as someone else', () => {
|
||||
it('does not expose the owner\'s email address', async () => {
|
||||
headers = await authenticatedHeaders({
|
||||
headers = await login({
|
||||
email: 'someone@example.org',
|
||||
password: 'else'
|
||||
})
|
||||
|
||||
23
src/seed/factories/badges.js
Normal file
23
src/seed/factories/badges.js
Normal file
@ -0,0 +1,23 @@
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
key,
|
||||
type = 'crowdfunding',
|
||||
status = 'permanent',
|
||||
icon
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateBadge(
|
||||
id: "${id}",
|
||||
key: "${key}",
|
||||
type: ${type},
|
||||
status: ${status},
|
||||
icon: "${icon}"
|
||||
) { id }
|
||||
}
|
||||
`
|
||||
}
|
||||
21
src/seed/factories/categories.js
Normal file
21
src/seed/factories/categories.js
Normal file
@ -0,0 +1,21 @@
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
name,
|
||||
slug,
|
||||
icon
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateCategory(
|
||||
id: "${id}",
|
||||
name: "${name}",
|
||||
slug: "${slug}",
|
||||
icon: "${icon}"
|
||||
) { id, name }
|
||||
}
|
||||
`
|
||||
}
|
||||
37
src/seed/factories/comments.js
Normal file
37
src/seed/factories/comments.js
Normal file
@ -0,0 +1,37 @@
|
||||
import faker from 'faker'
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
content = [
|
||||
faker.lorem.sentence(),
|
||||
faker.lorem.sentence()
|
||||
].join('. '),
|
||||
disabled = false,
|
||||
deleted = false
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateComment(
|
||||
id: "${id}",
|
||||
content: "${content}",
|
||||
disabled: ${disabled},
|
||||
deleted: ${deleted}
|
||||
) { id }
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export function relate (type, params) {
|
||||
const { from, to } = params
|
||||
return `
|
||||
mutation {
|
||||
${from}_${type}_${to}: AddComment${type}(
|
||||
from: { id: "${from}" },
|
||||
to: { id: "${to}" }
|
||||
) { from { id } }
|
||||
}
|
||||
`
|
||||
}
|
||||
@ -1,50 +1,103 @@
|
||||
import ApolloClient from 'apollo-client'
|
||||
import gql from 'graphql-tag'
|
||||
import dotenv from 'dotenv'
|
||||
import { HttpLink } from 'apollo-link-http'
|
||||
import { InMemoryCache } from 'apollo-cache-inmemory'
|
||||
import neo4j from '../../bootstrap/neo4j'
|
||||
import fetch from 'node-fetch'
|
||||
import { GraphQLClient, request } from 'graphql-request'
|
||||
import { getDriver } from '../../bootstrap/neo4j'
|
||||
|
||||
dotenv.config()
|
||||
export const seedServerHost = 'http://127.0.0.1:4001'
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
throw new Error('YOU CAN`T RUN FACTORIES IN PRODUCTION MODE')
|
||||
}
|
||||
|
||||
const client = new ApolloClient({
|
||||
link: new HttpLink({ uri: 'http://localhost:4001', fetch }),
|
||||
cache: new InMemoryCache()
|
||||
})
|
||||
|
||||
const driver = neo4j().getDriver()
|
||||
|
||||
const builders = {
|
||||
'user': require('./users.js').default
|
||||
}
|
||||
|
||||
const buildMutation = (model, parameters) => {
|
||||
return builders[model](parameters)
|
||||
}
|
||||
|
||||
const create = (model, parameters) => {
|
||||
return client.mutate({ mutation: gql(buildMutation(model, parameters)) })
|
||||
}
|
||||
|
||||
const cleanDatabase = async () => {
|
||||
const session = driver.session()
|
||||
const cypher = 'MATCH (n) DETACH DELETE n'
|
||||
try {
|
||||
const result = await session.run(cypher)
|
||||
session.close()
|
||||
return result
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
const authenticatedHeaders = async ({ email, password }, host) => {
|
||||
const mutation = `
|
||||
mutation {
|
||||
login(email:"${email}", password:"${password}"){
|
||||
token
|
||||
}
|
||||
}`
|
||||
const response = await request(host, mutation)
|
||||
return {
|
||||
authorization: `Bearer ${response.login.token}`
|
||||
}
|
||||
}
|
||||
|
||||
export {
|
||||
create,
|
||||
buildMutation,
|
||||
cleanDatabase
|
||||
const factories = {
|
||||
'badge': require('./badges.js').default,
|
||||
'user': require('./users.js').default,
|
||||
'organization': require('./organizations.js').default,
|
||||
'post': require('./posts.js').default,
|
||||
'comment': require('./comments.js').default,
|
||||
'category': require('./categories.js').default,
|
||||
'tag': require('./tags.js').default,
|
||||
'report': require('./reports.js').default
|
||||
}
|
||||
|
||||
const relationFactories = {
|
||||
'user': require('./users.js').relate,
|
||||
'organization': require('./organizations.js').relate,
|
||||
'post': require('./posts.js').relate,
|
||||
'comment': require('./comments.js').relate
|
||||
}
|
||||
|
||||
export const create = (model, parameters, options) => {
|
||||
const graphQLClient = new GraphQLClient(seedServerHost, options)
|
||||
const mutation = factories[model](parameters)
|
||||
return graphQLClient.request(mutation)
|
||||
}
|
||||
|
||||
export const relate = (model, type, parameters, options) => {
|
||||
const graphQLClient = new GraphQLClient(seedServerHost, options)
|
||||
const mutation = relationFactories[model](type, parameters)
|
||||
return graphQLClient.request(mutation)
|
||||
}
|
||||
|
||||
export const cleanDatabase = async (options = {}) => {
|
||||
const {
|
||||
driver = getDriver()
|
||||
} = options
|
||||
const session = driver.session()
|
||||
const cypher = 'MATCH (n) DETACH DELETE n'
|
||||
try {
|
||||
return await session.run(cypher)
|
||||
} catch (error) {
|
||||
throw (error)
|
||||
} finally {
|
||||
session.close()
|
||||
}
|
||||
}
|
||||
|
||||
export default function Factory (options = {}) {
|
||||
const {
|
||||
neo4jDriver = getDriver(),
|
||||
seedServerHost = 'http://127.0.0.1:4001'
|
||||
} = options
|
||||
|
||||
const graphQLClient = new GraphQLClient(seedServerHost)
|
||||
|
||||
const result = {
|
||||
neo4jDriver,
|
||||
seedServerHost,
|
||||
graphQLClient,
|
||||
lastResponse: null,
|
||||
async authenticateAs ({ email, password }) {
|
||||
const headers = await authenticatedHeaders({ email, password }, seedServerHost)
|
||||
this.lastResponse = headers
|
||||
this.graphQLClient = new GraphQLClient(seedServerHost, { headers })
|
||||
return this
|
||||
},
|
||||
async create (node, properties) {
|
||||
const mutation = factories[node](properties)
|
||||
this.lastResponse = await this.graphQLClient.request(mutation)
|
||||
return this
|
||||
},
|
||||
async relate (node, relationship, properties) {
|
||||
const mutation = relationFactories[node](relationship, properties)
|
||||
this.lastResponse = await this.graphQLClient.request(mutation)
|
||||
return this
|
||||
},
|
||||
async cleanDatabase () {
|
||||
this.lastResponse = await cleanDatabase({ driver: this.neo4jDriver })
|
||||
return this
|
||||
}
|
||||
}
|
||||
result.authenticateAs.bind(result)
|
||||
result.create.bind(result)
|
||||
result.relate.bind(result)
|
||||
result.cleanDatabase.bind(result)
|
||||
return result
|
||||
}
|
||||
|
||||
36
src/seed/factories/organizations.js
Normal file
36
src/seed/factories/organizations.js
Normal file
@ -0,0 +1,36 @@
|
||||
import faker from 'faker'
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function create (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
name = faker.comany.companyName(),
|
||||
description = faker.company.catchPhrase(),
|
||||
disabled = false,
|
||||
deleted = false
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateOrganization(
|
||||
id: "${id}",
|
||||
name: "${name}",
|
||||
description: "${description}",
|
||||
disabled: ${disabled},
|
||||
deleted: ${deleted}
|
||||
) { name }
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export function relate (type, params) {
|
||||
const { from, to } = params
|
||||
return `
|
||||
mutation {
|
||||
${from}_${type}_${to}: AddOrganization${type}(
|
||||
from: { id: "${from}" },
|
||||
to: { id: "${to}" }
|
||||
) { from { id } }
|
||||
}
|
||||
`
|
||||
}
|
||||
46
src/seed/factories/posts.js
Normal file
46
src/seed/factories/posts.js
Normal file
@ -0,0 +1,46 @@
|
||||
import faker from 'faker'
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
title = faker.lorem.sentence(),
|
||||
content = [
|
||||
faker.lorem.sentence(),
|
||||
faker.lorem.sentence(),
|
||||
faker.lorem.sentence(),
|
||||
faker.lorem.sentence(),
|
||||
faker.lorem.sentence()
|
||||
].join('. '),
|
||||
image = faker.image.image(),
|
||||
visibility = 'public',
|
||||
disabled = false,
|
||||
deleted = false
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreatePost(
|
||||
id: "${id}",
|
||||
title: "${title}",
|
||||
content: "${content}",
|
||||
image: "${image}",
|
||||
visibility: ${visibility},
|
||||
disabled: ${disabled},
|
||||
deleted: ${deleted}
|
||||
) { title, content }
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export function relate (type, params) {
|
||||
const { from, to } = params
|
||||
return `
|
||||
mutation {
|
||||
${from}_${type}_${to}: AddPost${type}(
|
||||
from: { id: "${from}" },
|
||||
to: { id: "${to}" }
|
||||
) { from { id } }
|
||||
}
|
||||
`
|
||||
}
|
||||
23
src/seed/factories/reports.js
Normal file
23
src/seed/factories/reports.js
Normal file
@ -0,0 +1,23 @@
|
||||
import faker from 'faker'
|
||||
|
||||
export default function create (params) {
|
||||
const {
|
||||
description = faker.lorem.sentence(),
|
||||
resource: { id: resourceId, type }
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
report(
|
||||
description: "${description}",
|
||||
resource: {
|
||||
id: "${resourceId}",
|
||||
type: ${type}
|
||||
}
|
||||
) {
|
||||
id,
|
||||
createdAt
|
||||
}
|
||||
}
|
||||
`
|
||||
}
|
||||
17
src/seed/factories/tags.js
Normal file
17
src/seed/factories/tags.js
Normal file
@ -0,0 +1,17 @@
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
name
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
CreateTag(
|
||||
id: "${id}",
|
||||
name: "${name}",
|
||||
) { name }
|
||||
}
|
||||
`
|
||||
}
|
||||
@ -1,25 +1,30 @@
|
||||
import faker from 'faker'
|
||||
import uuid from 'uuid/v4'
|
||||
|
||||
export default function (params) {
|
||||
export default function create (params) {
|
||||
const {
|
||||
id = uuid(),
|
||||
name = faker.name.findName(),
|
||||
email = faker.internet.email(),
|
||||
password = '1234',
|
||||
avatar = faker.internet.avatar()
|
||||
role = 'user',
|
||||
avatar = faker.internet.avatar(),
|
||||
disabled = false,
|
||||
deleted = false
|
||||
} = params
|
||||
|
||||
return `
|
||||
mutation {
|
||||
u1: CreateUser(
|
||||
id: "u1",
|
||||
CreateUser(
|
||||
id: "${id}",
|
||||
name: "${name}",
|
||||
password: "${password}",
|
||||
email: "${email}",
|
||||
avatar: "${avatar}",
|
||||
role: admin,
|
||||
disabled: false,
|
||||
deleted: false) {
|
||||
id
|
||||
role: ${role},
|
||||
disabled: ${disabled},
|
||||
deleted: ${deleted}
|
||||
) {
|
||||
name
|
||||
email
|
||||
avatar
|
||||
@ -28,3 +33,15 @@ export default function (params) {
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
export function relate (type, params) {
|
||||
const { from, to } = params
|
||||
return `
|
||||
mutation {
|
||||
${from}_${type}_${to}: AddUser${type}(
|
||||
from: { id: "${from}" },
|
||||
to: { id: "${to}" }
|
||||
) { from { id } }
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@ -1,30 +1,19 @@
|
||||
import { query } from '../graphql-schema'
|
||||
import { cleanDatabase } from './factories'
|
||||
import dotenv from 'dotenv'
|
||||
import neo4j from '../bootstrap/neo4j'
|
||||
|
||||
dotenv.config()
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
throw new Error('YOU CAN`T UNSEED IN PRODUCTION MODE')
|
||||
throw new Error(`YOU CAN'T CLEAN THE DATABASE WITH NODE_ENV=${process.env.NODE_ENV}`)
|
||||
}
|
||||
|
||||
const driver = neo4j().getDriver()
|
||||
const session = driver.session()
|
||||
|
||||
const deleteAll = `
|
||||
MATCH (n)
|
||||
OPTIONAL MATCH (n)-[r]-()
|
||||
DELETE n,r
|
||||
`
|
||||
query(deleteAll, session).then(() => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log('Successfully deleted all nodes and relations!')
|
||||
}).catch((err) => {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`)
|
||||
}).finally(() => {
|
||||
if (session) {
|
||||
session.close()
|
||||
(async function () {
|
||||
try {
|
||||
await cleanDatabase()
|
||||
console.log('Successfully deleted all nodes and relations!')
|
||||
process.exit(0)
|
||||
} catch (err) {
|
||||
console.log(`Error occurred deleting the nodes and relations (reset the db)\n\n${err}`)
|
||||
process.exit(1)
|
||||
}
|
||||
process.exit(0)
|
||||
})
|
||||
})()
|
||||
|
||||
@ -7,7 +7,7 @@ import mocks from './mocks'
|
||||
import middleware from './middleware'
|
||||
import applyDirectives from './bootstrap/directives'
|
||||
import applyScalars from './bootstrap/scalars'
|
||||
import neo4j from './bootstrap/neo4j'
|
||||
import { getDriver } from './bootstrap/neo4j'
|
||||
|
||||
import passport from 'passport'
|
||||
import jwtStrategy from './jwt/strategy'
|
||||
@ -22,7 +22,7 @@ requiredEnvVars.forEach(env => {
|
||||
}
|
||||
})
|
||||
|
||||
const driver = neo4j().getDriver()
|
||||
const driver = getDriver()
|
||||
const debug = process.env.NODE_ENV !== 'production' && process.env.DEBUG === 'true'
|
||||
|
||||
let schema = makeAugmentedSchema({
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user