From 86bcc50719d2a8c8a21b3bae59e6e657ef44e69a Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Tue, 28 Nov 2017 15:25:28 +0100 Subject: [PATCH 1/7] renaming a couple of things within mutation stuff. --- .gitignore | 2 ++ src/resolvers.js | 2 +- src/schema.js | 2 +- tests/integration.test.js | 35 +++++++++++++++++------------------ tests/unit.test.js | 4 ++-- 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 3c32c59..45c254c 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ typings/ .env .idea + +.serverless diff --git a/src/resolvers.js b/src/resolvers.js index 8ff607a..16844c2 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -5,7 +5,7 @@ module.exports = { } }, Mutation: { - value(obj, { key, value }, context, info) { + set(obj, { key, value }, context, info) { return context.setValue(key, value) } } diff --git a/src/schema.js b/src/schema.js index ddc97b8..77e3cd1 100644 --- a/src/schema.js +++ b/src/schema.js @@ -5,5 +5,5 @@ module.exports = `type Query { } type Mutation { - value(key: String!, value: String!): String + set(key: String!, value: String!): String }` diff --git a/tests/integration.test.js b/tests/integration.test.js index fc6adce..ee2f0fa 100644 --- a/tests/integration.test.js +++ b/tests/integration.test.js @@ -5,29 +5,28 @@ const supertest = require('supertest') describe('with graphql endpoint', function() { this.timeout(5 * 1000) - const request = () => { - const endpoint = utils.getServiceEndpoint() + const request = () => supertest(utils.getServiceEndpoint()) - return supertest(endpoint) - } - - it('read your write', () => { + it('writing a value', () => { const key = 'SET-KEY' const expected = 'some value' + + return request().get('/graphql') + .query({query: `mutation {set(key:"${key}", value:"${expected}")}`}) + .expect('Content-Type', /json/) + .expect(200) + .expect(r => { assert.equal(expected, r.body.data.set) }) + }) + + it('reading a value', () => { + const key = 'GET-KEY' + const expected = '' + return request().get('/graphql') - .query({query: `mutation {value(key:"${key}", value:"${expected}")}`}) + .query({query: `{value(key:"${key}")}`}) .expect('Content-Type', /json/) .expect(200) - .then(r => request().get('/graphql') - .query({query: `{value(key:"${key}")}`}) - .expect(res => { - assert.equal(expected, res.body.data.value) - })) - .catch(e => { - if (e) { - throw e - } - }) + .expect(r => { assert.equal(expected, r.body.data.value) }) }) it('getting an error', () => { @@ -35,6 +34,6 @@ describe('with graphql endpoint', function() { .query({query: '{value}'}) .expect('Content-Type', /json/) .expect(200) - .expect(res => { assert.equal(1, res.body.errors.length) }) + .expect(r => { assert.equal(1, r.body.errors.length) }) }) }) diff --git a/tests/unit.test.js b/tests/unit.test.js index 7e6a8e6..d70a5e1 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -68,11 +68,11 @@ describe('mutating', () => { stubDocumentClientWrite({ }) const evt = { queryStringParameters: { - query: `mutation {value(key: "Username", value: "${expected}")}` + query: `mutation {set(key: "Username", value: "${expected}")}` } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, JSON.parse(result.body).data.value) + assert.equal(expected, JSON.parse(result.body).data.set) done() }) }) From 5f1a5425d5296fcd506afd871a46f6b10268c105 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 08:17:10 +0100 Subject: [PATCH 2/7] removing ENV variables dependencies. --- src/db.js | 69 +++++++++++++++++++++++++------------------------- src/handler.js | 2 +- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/db.js b/src/db.js index 21f380a..856766f 100644 --- a/src/db.js +++ b/src/db.js @@ -1,44 +1,45 @@ 'use strict' const AWS = require('aws-sdk') -const config = require('./config.json') -const options = config[process.env.STAGE] || {} -const db = () => new AWS.DynamoDB.DocumentClient(options) -module.exports = { - getValue: key => { - const params = { - TableName: process.env.DB_TABLE, - Key: { key } - } +module.exports = (stage, tableName) => { + const client = stage => new AWS.DynamoDB.DocumentClient(require('./config.json')[stage] || {}) - return new Promise((resolve, reject) => { - db().get(params, (error, data) => { - if (error) { - reject(error) - } else { - resolve(typeof data.Item === 'undefined' ? '' : data.Item.info) - } - }) - }) - }, - setValue: (key, info) => { - const params = { - TableName: process.env.DB_TABLE, - Key: { key: key }, - UpdateExpression: 'SET info = :info', - ExpressionAttributeValues: { - ':info': info + return { + getValue: key => { + const params = { + TableName: tableName, + Key: { key } } - } - return new Promise((resolve, reject) => { - db().update(params, (error, data) => { - if (error) { - reject(error) - } else { - resolve(info) + return new Promise((resolve, reject) => { + client(stage).get(params, (error, data) => { + if (error) { + reject(error) + } else { + resolve(typeof data.Item === 'undefined' ? '' : data.Item.info) + } + }) + }) + }, + setValue: (key, info) => { + const params = { + TableName: tableName, + Key: { key: key }, + UpdateExpression: 'SET info = :info', + ExpressionAttributeValues: { + ':info': info } + } + + return new Promise((resolve, reject) => { + client(stage).update(params, (error, data) => { + if (error) { + reject(error) + } else { + resolve(info) + } + }) }) - }) + } } } diff --git a/src/handler.js b/src/handler.js index 86cd377..2baa0c7 100644 --- a/src/handler.js +++ b/src/handler.js @@ -1,11 +1,11 @@ 'use strict' const {graphql} = require('graphql') -const db = require('./db') const typeDefs = require('./schema') const resolvers = require('./resolvers') const {makeExecutableSchema} = require('graphql-tools') module.exports.graphql = (event, context, callback) => { + const db = require('./db')(process.env.STAGE, process.env.DB_TABLE) const source = event.queryStringParameters.query const contextValue = db const schema = makeExecutableSchema({typeDefs, resolvers}) From 8180cc7302e3a1daf4852194cb27997d6f2b06d1 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 09:43:44 +0100 Subject: [PATCH 3/7] making integration tests a bit less fragile. --- tests/integration.test.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/tests/integration.test.js b/tests/integration.test.js index ee2f0fa..f21a524 100644 --- a/tests/integration.test.js +++ b/tests/integration.test.js @@ -2,6 +2,8 @@ const assert = require('assert') const utils = require('./utils') const supertest = require('supertest') +const prop = (...arr) => obj => arr.reduce((acc, v) => acc && acc.hasOwnProperty(v) ? acc[v] : undefined, obj) + describe('with graphql endpoint', function() { this.timeout(5 * 1000) @@ -15,7 +17,10 @@ describe('with graphql endpoint', function() { .query({query: `mutation {set(key:"${key}", value:"${expected}")}`}) .expect('Content-Type', /json/) .expect(200) - .expect(r => { assert.equal(expected, r.body.data.set) }) + .expect(r => { + assert.equal(expected, + r.body.data.set, + JSON.stringify(prop('body', 'errors')(r))) }) }) it('reading a value', () => { @@ -26,7 +31,11 @@ describe('with graphql endpoint', function() { .query({query: `{value(key:"${key}")}`}) .expect('Content-Type', /json/) .expect(200) - .expect(r => { assert.equal(expected, r.body.data.value) }) + .expect(r => { + assert.equal(expected, + r.body.data.value, + JSON.stringify(prop('body', 'errors')(r))) + }) }) it('getting an error', () => { @@ -34,6 +43,10 @@ describe('with graphql endpoint', function() { .query({query: '{value}'}) .expect('Content-Type', /json/) .expect(200) - .expect(r => { assert.equal(1, r.body.errors.length) }) + .expect(r => { + assert.equal(1, + prop('body', 'errors', 'length')(r), + JSON.stringify(prop('body', 'errors')(r))) + }) }) }) From dc2c67496fbd63eef7e1a7abd3dbbc91dc506010 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 09:51:34 +0100 Subject: [PATCH 4/7] avoid 'undefined' references on test failures. --- tests/integration.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration.test.js b/tests/integration.test.js index f21a524..20dfaa9 100644 --- a/tests/integration.test.js +++ b/tests/integration.test.js @@ -19,7 +19,7 @@ describe('with graphql endpoint', function() { .expect(200) .expect(r => { assert.equal(expected, - r.body.data.set, + prop('body', 'data', 'set')(r), JSON.stringify(prop('body', 'errors')(r))) }) }) @@ -33,7 +33,7 @@ describe('with graphql endpoint', function() { .expect(200) .expect(r => { assert.equal(expected, - r.body.data.value, + prop('body', 'data', 'value')(r), JSON.stringify(prop('body', 'errors')(r))) }) }) From 195a811458803ee7f55e6bcdc114fb6c4cced158 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 10:03:36 +0100 Subject: [PATCH 5/7] using well-known syntax. --- src/resolvers.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/resolvers.js b/src/resolvers.js index 16844c2..6bcd824 100644 --- a/src/resolvers.js +++ b/src/resolvers.js @@ -1,11 +1,11 @@ module.exports = { Query: { - value(obj, { key }, context, info) { + value: (obj, { key }, context, info) => { return context.getValue(key) } }, Mutation: { - set(obj, { key, value }, context, info) { + set: (obj, { key, value }, context, info) => { return context.setValue(key, value) } } From cb7e08d2c53c0fb87004dac405ae8057f3db22e7 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 11:13:57 +0100 Subject: [PATCH 6/7] working with dynamodb return values. --- src/db.js | 13 +++++++------ src/handler.js | 2 +- tests/unit.test.js | 16 ++++++++++------ 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/db.js b/src/db.js index 856766f..b3076a4 100644 --- a/src/db.js +++ b/src/db.js @@ -16,19 +16,20 @@ module.exports = (stage, tableName) => { if (error) { reject(error) } else { - resolve(typeof data.Item === 'undefined' ? '' : data.Item.info) + resolve(typeof data.Item === 'undefined' ? '' : data.Item.val) } }) }) }, - setValue: (key, info) => { + setValue: (key, value) => { const params = { TableName: tableName, Key: { key: key }, - UpdateExpression: 'SET info = :info', + UpdateExpression: 'SET val = :value', ExpressionAttributeValues: { - ':info': info - } + ':value': value + }, + ReturnValues: 'ALL_NEW' } return new Promise((resolve, reject) => { @@ -36,7 +37,7 @@ module.exports = (stage, tableName) => { if (error) { reject(error) } else { - resolve(info) + resolve(data.Attributes.val) } }) }) diff --git a/src/handler.js b/src/handler.js index 2baa0c7..faff8bc 100644 --- a/src/handler.js +++ b/src/handler.js @@ -12,6 +12,6 @@ module.exports.graphql = (event, context, callback) => { graphql({schema, source, contextValue}) .then(result => callback(null, { statusCode: 200, - body: JSON.stringify(result) + body: result }), error => callback(error)) } diff --git a/tests/unit.test.js b/tests/unit.test.js index d70a5e1..4815d2f 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -17,7 +17,7 @@ describe('querying', () => { const expected = 'fake value' stubDocumentClientRead({ Item: { - info: expected + val: expected } }) const evt = { @@ -26,7 +26,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, JSON.parse(result.body).data.value) + assert.equal(expected, result.body.data.value) done() }) }) @@ -40,7 +40,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, JSON.parse(result.body).data.value) + assert.equal(expected, result.body.data.value) done() }) }) @@ -52,7 +52,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(1, JSON.parse(result.body).errors.length) + assert.equal(1, result.body.errors.length) done() }) }) @@ -65,14 +65,18 @@ describe('querying', () => { describe('mutating', () => { it('writing value for a key', done => { const expected = 'Mario' - stubDocumentClientWrite({ }) + stubDocumentClientWrite({ + Attributes: { + val: expected + } + }) const evt = { queryStringParameters: { query: `mutation {set(key: "Username", value: "${expected}")}` } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, JSON.parse(result.body).data.set) + assert.equal(expected, result.body.data.set) done() }) }) From ff0ce8a7a0fdc758013c574ca41f325cf90eb097 Mon Sep 17 00:00:00 2001 From: "nicola baldi (@naighes)" Date: Thu, 30 Nov 2017 16:17:09 +0100 Subject: [PATCH 7/7] latest minor adjustments. --- src/handler.js | 14 ++++++++++---- tests/integration.test.js | 2 +- tests/unit.test.js | 8 ++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/handler.js b/src/handler.js index faff8bc..6118add 100644 --- a/src/handler.js +++ b/src/handler.js @@ -10,8 +10,14 @@ module.exports.graphql = (event, context, callback) => { const contextValue = db const schema = makeExecutableSchema({typeDefs, resolvers}) graphql({schema, source, contextValue}) - .then(result => callback(null, { - statusCode: 200, - body: result - }), error => callback(error)) + .then(result => { + callback(null, { + statusCode: 200, + body: JSON.stringify(result) + }) + }) + .catch(error => { + console.error(JSON.stringify(error)) + callback(error) + }) } diff --git a/tests/integration.test.js b/tests/integration.test.js index 20dfaa9..3853aa7 100644 --- a/tests/integration.test.js +++ b/tests/integration.test.js @@ -5,7 +5,7 @@ const supertest = require('supertest') const prop = (...arr) => obj => arr.reduce((acc, v) => acc && acc.hasOwnProperty(v) ? acc[v] : undefined, obj) describe('with graphql endpoint', function() { - this.timeout(5 * 1000) + this.timeout(30 * 1000) const request = () => supertest(utils.getServiceEndpoint()) diff --git a/tests/unit.test.js b/tests/unit.test.js index 4815d2f..dccf501 100644 --- a/tests/unit.test.js +++ b/tests/unit.test.js @@ -26,7 +26,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, result.body.data.value) + assert.equal(expected, JSON.parse(result.body).data.value) done() }) }) @@ -40,7 +40,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, result.body.data.value) + assert.equal(expected, JSON.parse(result.body).data.value) done() }) }) @@ -52,7 +52,7 @@ describe('querying', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(1, result.body.errors.length) + assert.equal(1, JSON.parse(result.body).errors.length) done() }) }) @@ -76,7 +76,7 @@ describe('mutating', () => { } } handler.graphql(evt, null, (error, result) => { - assert.equal(expected, result.body.data.set) + assert.equal(expected, JSON.parse(result.body).data.set) done() }) })