From 202c3cfad241b2e2a2cd69b4b140405289d1342a Mon Sep 17 00:00:00 2001 From: Sharon Funke Date: Fri, 24 Mar 2017 17:03:10 +0100 Subject: [PATCH] Add migration endpoint including tests --- migration-scripts/to-v2.0.0.js | 19 +++++++ routes/migration.js | 39 ++++++++++++++ routes/routes.js | 4 +- test/dom-test.js | 2 +- test/e2e.js | 43 ++++++++++++++- test/resources/mock-data-v1.0.0.js | 53 +++++++++++++++++++ .../{mock-data.js => mock-data-v2.0.0.js} | 6 +-- 7 files changed, 157 insertions(+), 9 deletions(-) create mode 100644 migration-scripts/to-v2.0.0.js create mode 100644 routes/migration.js create mode 100644 test/resources/mock-data-v1.0.0.js rename test/resources/{mock-data.js => mock-data-v2.0.0.js} (89%) diff --git a/migration-scripts/to-v2.0.0.js b/migration-scripts/to-v2.0.0.js new file mode 100644 index 0000000..e2b9067 --- /dev/null +++ b/migration-scripts/to-v2.0.0.js @@ -0,0 +1,19 @@ +// contains all scripts which shall be executed to migrate to tool version 2.0.0 +// each module has to return a result object holding the modified item and a +// flag property indicating if item was changed or not +module.exports.migrate = function(item) { + let result = { + isChanged: false + } + if (item.parties) { + let truthyparties = item.parties.filter(party => { + return party.name !== undefined && party.name !== ''; + }); + if (truthyparties.length < item.parties.length) { + item.parties = truthyparties; + result.isChanged = true; + } + } + result.item = item; + return result; +} diff --git a/routes/migration.js b/routes/migration.js new file mode 100644 index 0000000..3b2ac91 --- /dev/null +++ b/routes/migration.js @@ -0,0 +1,39 @@ +const Joi = require('joi'); +const Boom = require('boom'); + +// register migration scripts here in order of version, +// i.e. list the smalles version first +const migrationScripts = [ + require('../migration-scripts/to-v2.0.0.js') +] + +module.exports = { + method: 'POST', + path:'/migration', + config: { + validate: { + payload: { + item: Joi.object().required() + } + } + }, + handler: (request, reply) => { + let item = request.payload.item; + const results = migrationScripts.map(script => { + const result = script.migrate(item); + if (result.isChanged) { + item = result.item; + } + return result; + }) + const isChanged = results.findIndex(result => { + return result.isChanged; + }); + if (isChanged >= 0) { + return reply({ + item: item + }) + } + return reply().code(304); + } +} diff --git a/routes/routes.js b/routes/routes.js index c2510d4..5d5aa95 100644 --- a/routes/routes.js +++ b/routes/routes.js @@ -1,9 +1,11 @@ const htmlStatic = require('./rendering-info/html-static.js'); const stylesheet = require('./stylesheet.js'); const schema = require('./schema.js'); +const migration = require('./migration.js'); module.exports = [ htmlStatic, stylesheet, - schema + schema, + migration ] diff --git a/test/dom-test.js b/test/dom-test.js index 15a9670..ff20485 100644 --- a/test/dom-test.js +++ b/test/dom-test.js @@ -1,7 +1,7 @@ const JsDom = require('jsdom'); const expect = require('chai').expect; -const mockData = require('./resources/mock-data'); +const mockData = require('./resources/mock-data-v2.0.0'); require('svelte/ssr/register'); const staticTpl = require('../views/html-static.html'); var markup = staticTpl.render(JSON.parse(JSON.stringify(mockData))); diff --git a/test/e2e.js b/test/e2e.js index 31f0e5e..21719e4 100644 --- a/test/e2e.js +++ b/test/e2e.js @@ -5,6 +5,16 @@ const expect = require('chai').expect; const server = require('../server.js'); const plugins = require('../server-plugins.js'); const routes = require('../routes/routes.js'); +const Joi = require('joi'); +const Enjoi = require('enjoi'); +const fs = require('fs'); + +const resourcesDir = __dirname + '/../resources/'; + +const schemaString = JSON.parse(fs.readFileSync(resourcesDir + 'schema.json', { + encoding: 'utf-8' +})); +const schema = Enjoi(schemaString); server.register(plugins, err => { Hoek.assert(!err, err); @@ -42,7 +52,8 @@ describe('Q required API', () => { }); -const mockData = JSON.parse(JSON.stringify(require('./resources/mock-data.js'))); +const mockDataV1 = JSON.parse(JSON.stringify(require('./resources/mock-data-v1.0.0'))); +const mockDataV2 = JSON.parse(JSON.stringify(require('./resources/mock-data-v2.0.0'))); describe('rendering-info endpoints', () => { @@ -50,7 +61,7 @@ describe('rendering-info endpoints', () => { const request = { method: 'POST', url: '/rendering-info/html-static', - payload: JSON.stringify({ item: mockData }) + payload: JSON.stringify({ item: mockDataV2 }) }; server.inject(request, (res) => { expect(res.statusCode).to.be.equal(200); @@ -59,3 +70,31 @@ describe('rendering-info endpoints', () => { }) }); + +describe('migration endpoint', () => { + + it('should pass validation against schema after migration via endpoint /migration', function(done) { + const request = { + method: 'POST', + url: '/migration', + payload: JSON.stringify({ item: mockDataV1 }) + } ; + server.inject(request, (res) => { + expect(Joi.validate(res.result.item, schema).error).to.be.null; + done(); + }) + }) + + it('should return 304 for /migration', function(done) { + const request = { + method: 'POST', + url: '/migration', + payload: JSON.stringify({ item: mockDataV2 }) + } ; + server.inject(request, (res) => { + expect(res.statusCode).to.be.equal(304); + done(); + }) + }) + +}) diff --git a/test/resources/mock-data-v1.0.0.js b/test/resources/mock-data-v1.0.0.js new file mode 100644 index 0000000..ea77ca0 --- /dev/null +++ b/test/resources/mock-data-v1.0.0.js @@ -0,0 +1,53 @@ +module.exports = { + title: "Sitzverteilung Parlament Frankreich", + sources: [ + { + "text": "asdjfh", + "link": { + "url": "www.nzz.ch", + "isValid": true + } + } + ], + subtitle: "Möglichkeit zusätzliche Informationen als Untertitel zu erfassen", + notes: "Jemand musste Josef K. verleumdet haben, denn ohne dass er etwas Böses getan hätte, wurde er eines Morgens verhaftet.", + totalSeats: 200, + parties: [ + { + color: + { + colorCode: "#0084c7" + }, + seats: 70, + previous: 71 + }, + { + name: "Sozialdemokratische Partei Deutschlands", + color: + { + colorCode: "#c31906", + classAttribute: "s-viz-color-party-sp-5" + }, + seats: 80, + previous: 75 + }, + { + name: "Bündnis 90/Die Grünen", + color: + { + colorCode: "#66a622" + }, + seats: 30, + previous: 24 + }, + { + name: "Die Linke", + color: + { + colorCode: "#a35fd1" + }, + seats: 20, + previous: 15 + } + ] +} diff --git a/test/resources/mock-data.js b/test/resources/mock-data-v2.0.0.js similarity index 89% rename from test/resources/mock-data.js rename to test/resources/mock-data-v2.0.0.js index a28e2b1..2644336 100644 --- a/test/resources/mock-data.js +++ b/test/resources/mock-data-v2.0.0.js @@ -13,9 +13,8 @@ module.exports = { notes: "Jemand musste Josef K. verleumdet haben, denn ohne dass er etwas Böses getan hätte, wurde er eines Morgens verhaftet.", totalSeats: 200, parties: [ - { + { name: "Die Union", - abbreviation: "CDU/CSU", color: { colorCode: "#0084c7" @@ -25,7 +24,6 @@ module.exports = { }, { name: "Sozialdemokratische Partei Deutschlands", - abbreviation: "SPD", color: { colorCode: "#c31906", @@ -36,7 +34,6 @@ module.exports = { }, { name: "Bündnis 90/Die Grünen", - abbreviation: "Die Grünen", color: { colorCode: "#66a622" @@ -46,7 +43,6 @@ module.exports = { }, { name: "Die Linke", - abbreviation: "Die Linke", color: { colorCode: "#a35fd1"