diff --git a/README.md b/README.md index 17a26caad..1eb8cc528 100644 --- a/README.md +++ b/README.md @@ -117,10 +117,8 @@ Optionally you can seed the GraphQL service by executing mutations that will write sample data to the database: ```bash -yarn run build yarn run db:seed # -or- -npm run build npm run db:seed ``` diff --git a/package.json b/package.json index 28c6b026f..d4690c37e 100644 --- a/package.json +++ b/package.json @@ -11,14 +11,15 @@ "start": "node dist/", "dev": "nodemon --exec babel-node src/index.js", "dev:debug": "nodemon --exec babel-node --inspect=0.0.0.0:9229 src/index.js", - "jest": "jest", "lint": "eslint src --config .eslintrc.js", - "test": "nyc --reporter=text-lcov jest", + "test": "nyc --reporter=text-lcov test:jest", + "test:jest": "$npm_package_config_no_auth run-p --race start test:cmd:jest", + "test:cmd:jest": "jest", "test:coverage": "nyc report --reporter=text-lcov > coverage.lcov", "db:script:seed": "wait-on tcp:4001 && babel-node src/seed/seed-db.js", "db:script:reset": "wait-on tcp:4001 && babel-node src/seed/reset-db.js", - "db:seed": "$npm_package_config_no_auth run-p --race start db:script:seed", - "db:reset": "$npm_package_config_no_auth run-p --race start db:script:reset" + "db:seed": "$npm_package_config_no_auth run-p --race dev db:script:seed", + "db:reset": "$npm_package_config_no_auth run-p --race dev db:script:reset" }, "author": "Human Connection gGmbH", "license": "MIT", @@ -58,7 +59,7 @@ "devDependencies": { "@babel/cli": "~7.2.0", "@babel/core": "^7.2.2", - "@babel/node": "~7.2.0", + "@babel/node": "~7.2.2", "@babel/preset-env": "~7.2.0", "@babel/register": "~7.0.0", "apollo-server-testing": "~2.2.6", diff --git a/src/graphql-schema.test.js b/src/graphql-schema.test.js index f9be026f5..d75095daa 100644 --- a/src/graphql-schema.test.js +++ b/src/graphql-schema.test.js @@ -1,12 +1,14 @@ import { request } from 'graphql-request' import createServer from './server' +import mocks from './mocks' +import { create, cleanDatabase } from './seed/factories' let getHost let app let port beforeEach(async () => { - const server = createServer() + const server = createServer({mocks}) app = await server.start({ port: 0 }) port = app.address().port getHost = () => `http://127.0.0.1:${port}` @@ -16,33 +18,62 @@ afterEach(async () => { await app.close() }) -describe('login', () => { - describe('asking for a `token`', () => { - describe('with valid email/password combination', () => { - xit('responds with a JWT token', () => {}) - }) - - describe('with a valid email but incorrect password', () => { - beforeEach(() => { - // create a user in the database - }) - xit('responds with "Wrong email/password combination"', () => {}) - }) - - describe('with a non-existing email', () => { - const mutation = ` +describe.only('login', () => { + let email + let password + const mutation = ` mutation { - login(email:"user@example.com", password:"asdfasd"){ + login(email:"${email}", password:"${password}"){ token } }` + describe('given an existing user', () => { + beforeEach(async () => { + await create('user', { + email: 'test@example.org', + password: '1234' + }) + }) - it('responds with "Wrong email/password combination"', async () => { - try { - await request(getHost(), mutation) - } catch (error) { - expect(error.response.errors[0].message).toEqual('Wrong email/password combination') - } + afterEach(async () => { + await cleanDatabase() + }) + + describe('asking for a `token`', () => { + describe('with valid email/password combination', () => { + it('responds with a JWT token', async () => { + email = 'user@example.org' + password = '1234' + try { + await request(getHost(), mutation) + } catch (error) { + expect(error.response.errors[0].message).toEqual('Wrong email/password combination') + } + }) + }) + + describe('with a valid email but incorrect password', () => { + it('responds with "Wrong email/password combination"', async () => { + email = 'user@example.org' + password = 'wrong' + try { + await request(getHost(), mutation) + } catch (error) { + expect(error.response.errors[0].message).toEqual('Wrong email/password combination') + } + }) + }) + + describe('with a non-existing email', () => { + it('responds with "Wrong email/password combination"', async () => { + email = 'non-existent@example.org' + password = '1234' + try { + await request(getHost(), mutation) + } catch (error) { + expect(error.response.errors[0].message).toEqual('Wrong email/password combination') + } + }) }) }) }) diff --git a/src/seed/factories/index.js b/src/seed/factories/index.js new file mode 100644 index 000000000..fa7e924b9 --- /dev/null +++ b/src/seed/factories/index.js @@ -0,0 +1,43 @@ +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 { query } from '../../graphql-schema' + +dotenv.config() + +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: process.env.GRAPHQL_URI, fetch }), + cache: new InMemoryCache() +}) + +const driver = neo4j().getDriver() +const session = driver.session() + +const builders = { + "user": require('./users.js').default, +} + +const buildMutation = (model, parameters) => { + return builders[model](parameters) +} + +const create = async (model, parameters) => { + await client.mutate({mutation: gql(buildMutation(model, parameters))}) +} + +const cleanDatabase = async () => { + await query('MATCH (n) DETACH DELETE n', session) +} + +export { + create, + buildMutation, + cleanDatabase +} diff --git a/src/seed/factories/users.js b/src/seed/factories/users.js new file mode 100644 index 000000000..6b63b32e9 --- /dev/null +++ b/src/seed/factories/users.js @@ -0,0 +1,36 @@ +import faker from 'faker' + +export default function (params) { + const defaults = { + name: faker.name.findName(), + email: faker.internet.email(), + password: '1234', + avatar: faker.internet.avatar() + } + const { + name, + email, + password, + avatar + } = Object.assign({}, defaults, params) + + return ` + mutation { + u1: CreateUser( + id: "u1", + name: "${name}", + password: "${password}", + email: "${email}", + avatar: "${avatar}", + role: admin, + disabled: false, + deleted: false) { + id + name + email + avatar + role + } + } + ` +} diff --git a/src/server.js b/src/server.js index 3b0e0a561..88d04a0ea 100644 --- a/src/server.js +++ b/src/server.js @@ -52,7 +52,7 @@ const createServer = (options) => { schema: schema, tracing: true, middlewares: middleware(schema), - mocks: (process.env.MOCK === 'true') ? mocks : false + mocks: true } const server = new GraphQLServer(Object.assign({}, defaults, options)) diff --git a/yarn.lock b/yarn.lock index 75748a7f3..d4d640efc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -262,10 +262,10 @@ esutils "^2.0.2" js-tokens "^4.0.0" -"@babel/node@~7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.2.0.tgz#0b601be8ef03897923e3908dc18129836d44e6fa" - integrity sha512-RFwVH5xWpwd4SfkOI0WsK9AnF5o+C9iMTvUkkTb7jUNaiDieV8BGK38t74bTPjgc4FCxSAWNKqaqgDW4fenkyA== +"@babel/node@~7.2.2": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.2.2.tgz#1557dd23545b38d7b1d030a9c0e8fb225dbf70ab" + integrity sha512-jPqgTycE26uFsuWpLika9Ohz9dmLQHWjOnMNxBOjYb1HXO+eLKxEr5FfKSXH/tBvFwwaw+pzke3gagnurGOfCA== dependencies: "@babel/polyfill" "^7.0.0" "@babel/register" "^7.0.0"