Refactor tests with the new factory API

This commit is contained in:
Robert Schäfer 2019-02-21 15:40:31 +01:00
parent aa07a2a616
commit 132dba04dd
6 changed files with 84 additions and 63 deletions

View File

@ -1,17 +1,19 @@
import { create, cleanDatabase } from './seed/factories' import Factory from './seed/factories'
import jwt from 'jsonwebtoken' import jwt from 'jsonwebtoken'
import { testServerHost as host, authenticatedHeaders } from './jest/helpers' import { host, login } from './jest/helpers'
import { GraphQLClient, request } from 'graphql-request' import { GraphQLClient, request } from 'graphql-request'
const factory = Factory()
beforeEach(async () => { beforeEach(async () => {
await create('user', { await factory.create('user', {
email: 'test@example.org', email: 'test@example.org',
password: '1234' password: '1234'
}) })
}) })
afterEach(async () => { afterEach(async () => {
await cleanDatabase() await factory.cleanDatabase()
}) })
describe('login', () => { describe('login', () => {
@ -28,7 +30,10 @@ describe('login', () => {
describe('ask for a `token`', () => { describe('ask for a `token`', () => {
describe('with valid email/password combination', () => { describe('with valid email/password combination', () => {
it('responds with a JWT token', async () => { it('responds with a JWT token', async () => {
const data = await request(host, mutation({ email: 'test@example.org', password: '1234' })) const data = await request(host, mutation({
email: 'test@example.org',
password: '1234'
}))
const { token } = data.login const { token } = data.login
jwt.verify(token, process.env.JWT_SECRET, (err, data) => { jwt.verify(token, process.env.JWT_SECRET, (err, data) => {
expect(data.email).toEqual('test@example.org') expect(data.email).toEqual('test@example.org')
@ -39,21 +44,23 @@ describe('login', () => {
describe('with a valid email but incorrect password', () => { describe('with a valid email but incorrect password', () => {
it('responds with "Incorrect email address or password."', async () => { it('responds with "Incorrect email address or password."', async () => {
try { await expect(
await request(host, mutation({ email: 'test@example.org', password: 'wrong' })) request(host, mutation({
} catch (error) { email: 'test@example.org',
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.') password: 'wrong'
} }))
).rejects.toThrow('Incorrect email address or password.')
}) })
}) })
describe('with a non-existing email', () => { describe('with a non-existing email', () => {
it('responds with "Incorrect email address or password."', async () => { it('responds with "Incorrect email address or password."', async () => {
try { await expect(
await request(host, mutation({ email: 'non-existent@example.org', password: 'wrong' })) request(host, mutation({
} catch (error) { email: 'non-existent@example.org',
expect(error.response.errors[0].message).toEqual('Incorrect email address or password.') password: 'wrong'
} }))
).rejects.toThrow('Incorrect email address or password.')
}) })
}) })
}) })
@ -76,7 +83,7 @@ describe('CreatePost', () => {
let headers let headers
let response let response
beforeEach(async () => { beforeEach(async () => {
headers = await authenticatedHeaders({ email: 'test@example.org', password: '1234' }) headers = await login({ email: 'test@example.org', password: '1234' })
client = new GraphQLClient(host, { headers }) client = new GraphQLClient(host, { headers })
response = await client.request(`mutation { response = await client.request(`mutation {
CreatePost( CreatePost(

View File

@ -1,8 +1,10 @@
import { request } from 'graphql-request' import { request } from 'graphql-request'
export const testServerHost = 'http://127.0.0.1:4123' // 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 }, host = testServerHost) { export async function login ({ email, password }) {
const mutation = ` const mutation = `
mutation { mutation {
login(email:"${email}", password:"${password}"){ login(email:"${email}", password:"${password}"){

View File

@ -1,16 +1,18 @@
import { create, cleanDatabase } from '../seed/factories' import Factory from '../seed/factories'
import { testServerHost as host, authenticatedHeaders } from '../jest/helpers' import { host, login } from '../jest/helpers'
import { GraphQLClient } from 'graphql-request' import { GraphQLClient } from 'graphql-request'
const factory = Factory()
describe('authorization', () => { describe('authorization', () => {
describe('given two existing users', () => { describe('given two existing users', () => {
beforeEach(async () => { beforeEach(async () => {
await create('user', { await factory.create('user', {
email: 'owner@example.org', email: 'owner@example.org',
name: 'Owner', name: 'Owner',
password: 'iamtheowner' password: 'iamtheowner'
}) })
await create('user', { await factory.create('user', {
email: 'someone@example.org', email: 'someone@example.org',
name: 'Someone else', name: 'Someone else',
password: 'else' password: 'else'
@ -18,28 +20,28 @@ describe('authorization', () => {
}) })
afterEach(async () => { afterEach(async () => {
await cleanDatabase() await factory.cleanDatabase()
}) })
describe('access email address', () => { describe('access email address', () => {
let headers = {} let headers = {}
const action = async (headers) => { let loginCredentials = null
const action = async () => {
if (loginCredentials) {
headers = await login(loginCredentials)
}
const graphQLClient = new GraphQLClient(host, { headers }) const graphQLClient = new GraphQLClient(host, { headers })
return graphQLClient.request(`{ return graphQLClient.request('{User(name: "Owner") { email } }')
User(name: "Owner") {
email
}
}`)
} }
describe('not logged in', async () => { describe('not logged in', async () => {
it('rejects', async () => { it('rejects', async () => {
await expect(action(headers)).rejects.toThrow('Not Authorised!') await expect(action()).rejects.toThrow('Not Authorised!')
}) })
it('does not expose the owner\'s email address', async () => { it('does not expose the owner\'s email address', async () => {
try { try {
await action(headers) await action()
} catch (error) { } catch (error) {
expect(error.response.data).toEqual({ User: [ { email: null } ] }) expect(error.response.data).toEqual({ User: [ { email: null } ] })
} }
@ -47,30 +49,33 @@ describe('authorization', () => {
}) })
describe('as owner', () => { describe('as owner', () => {
it('exposes the owner\'s email address', async () => { beforeEach(() => {
headers = await authenticatedHeaders({ loginCredentials = {
email: 'owner@example.org', email: 'owner@example.org',
password: 'iamtheowner' password: 'iamtheowner'
}) }
expect(await action(headers)).toEqual({ User: [ { email: 'owner@example.org' } ] }) })
it('exposes the owner\'s email address', async () => {
await expect(action()).resolves.toEqual({ User: [ { email: 'owner@example.org' } ] })
}) })
}) })
describe('as someone else', () => { describe('authenticated as another user', () => {
beforeEach(async () => { beforeEach(async () => {
headers = await authenticatedHeaders({ loginCredentials = {
email: 'someone@example.org', email: 'someone@example.org',
password: 'else' password: 'else'
}) }
}) })
it('rejects', async () => { it('rejects', async () => {
await expect(action(headers)).rejects.toThrow('Not Authorised!') await expect(action()).rejects.toThrow('Not Authorised!')
}) })
it('does not expose the owner\'s email address', async () => { it('does not expose the owner\'s email address', async () => {
try { try {
await action(headers) await action()
} catch (error) { } catch (error) {
expect(error.response.data).toEqual({ User: [ { email: null } ] }) expect(error.response.data).toEqual({ User: [ { email: null } ] })
} }

View File

@ -1,41 +1,48 @@
import { create, cleanDatabase } from '../seed/factories' import Factory from '../seed/factories'
import { testServerHost as host, authenticatedHeaders } from '../jest/helpers' import { host, login } from '../jest/helpers'
import { GraphQLClient } from 'graphql-request' import { GraphQLClient } from 'graphql-request'
let client let authenticatedClient
let headers let headers
const factory = Factory()
beforeEach(async () => { beforeEach(async () => {
await create('user', { email: 'user@example.org', password: '1234' }) await factory.create('user', { email: 'user@example.org', password: '1234' })
headers = await authenticatedHeaders({ email: 'user@example.org', password: '1234' }) await factory.create('user', { email: 'someone@example.org', password: '1234' })
client = new GraphQLClient(host, { headers }) headers = await login({ email: 'user@example.org', password: '1234' })
authenticatedClient = new GraphQLClient(host, { headers })
}) })
afterEach(async () => { afterEach(async () => {
await cleanDatabase() await factory.cleanDatabase()
}) })
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 client.request(`mutation { const response = await authenticatedClient.request(`mutation {
CreatePost( CreatePost(
title: "I am a brand new post", title: "I am a brand new post",
content: "Some content" content: "Some content"
) { slug } ) { slug }
}`, { headers }) }`)
expect(response).toEqual({ CreatePost: { slug: 'i-am-a-brand-new-post' } }) expect(response).toEqual({ CreatePost: { slug: 'i-am-a-brand-new-post' } })
}) })
describe('if slug exists', () => { describe('if slug exists', () => {
beforeEach(async () => { beforeEach(async () => {
await create('post', { const asSomeoneElse = await Factory().authenticateAs({
email: 'someone@example.org',
password: '1234'
})
await asSomeoneElse.create('post', {
title: 'Pre-existing post', title: 'Pre-existing post',
slug: 'pre-existing-post' slug: 'pre-existing-post'
}, { headers }) })
}) })
it('chooses another slug', async () => { it('chooses another slug', async () => {
const response = await client.request(`mutation { const response = await authenticatedClient.request(`mutation {
CreatePost( CreatePost(
title: "Pre-existing post", title: "Pre-existing post",
content: "Some content" content: "Some content"
@ -46,7 +53,7 @@ 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 () => {
await expect(client.request(`mutation { await expect(authenticatedClient.request(`mutation {
CreatePost( CreatePost(
title: "Pre-existing post", title: "Pre-existing post",
content: "Some content", content: "Some content",
@ -61,9 +68,9 @@ describe('slugify', () => {
describe('CreateUser', () => { describe('CreateUser', () => {
const action = async (mutation, params) => { const action = async (mutation, params) => {
return client.request(`mutation { return authenticatedClient.request(`mutation {
${mutation}(password: "yo", ${params}) { slug } ${mutation}(password: "yo", ${params}) { slug }
}`, { headers }) }`)
} }
it('generates a slug based on name', async () => { it('generates a slug based on name', async () => {
await expect(action('CreateUser', 'name: "I am a user"')) await expect(action('CreateUser', 'name: "I am a user"'))

View File

@ -61,7 +61,7 @@ export const cleanDatabase = async (options = {}) => {
} }
} }
export default function factoryFun (options = {}) { export default function Factory (options = {}) {
const { const {
neo4jDriver = getDriver(), neo4jDriver = getDriver(),
seedServerHost = 'http://127.0.0.1:4001' seedServerHost = 'http://127.0.0.1:4001'

View File

@ -1,4 +1,4 @@
import factoryFun, { create, relate } from './factories' import Factory, { create, relate } from './factories'
/* eslint-disable no-multi-spaces */ /* eslint-disable no-multi-spaces */
(async function () { (async function () {
@ -70,12 +70,12 @@ import factoryFun, { create, relate } from './factories'
]) ])
const [ asAdmin, asModerator, asUser, asTick, asTrick, asTrack ] = await Promise.all([ const [ asAdmin, asModerator, asUser, asTick, asTrick, asTrack ] = await Promise.all([
factoryFun().authenticateAs({ email: 'admin@example.org', password: '1234' }), Factory().authenticateAs({ email: 'admin@example.org', password: '1234' }),
factoryFun().authenticateAs({ email: 'moderator@example.org', password: '1234' }), Factory().authenticateAs({ email: 'moderator@example.org', password: '1234' }),
factoryFun().authenticateAs({ email: 'user@example.org', password: '1234' }), Factory().authenticateAs({ email: 'user@example.org', password: '1234' }),
factoryFun().authenticateAs({ email: 'tick@example.org', password: '1234' }), Factory().authenticateAs({ email: 'tick@example.org', password: '1234' }),
factoryFun().authenticateAs({ email: 'trick@example.org', password: '1234' }), Factory().authenticateAs({ email: 'trick@example.org', password: '1234' }),
factoryFun().authenticateAs({ email: 'track@example.org', password: '1234' }) Factory().authenticateAs({ email: 'track@example.org', password: '1234' })
]) ])
await Promise.all([ await Promise.all([