mirror of
https://github.com/Unleash/unleash.git
synced 2025-02-04 00:18:01 +01:00
use ava as testrunner
This commit is contained in:
parent
8e9166add7
commit
ce056df8b6
1
.gitignore
vendored
1
.gitignore
vendored
@ -39,3 +39,4 @@ unleash-server.tar.gz
|
|||||||
jsconfig.json
|
jsconfig.json
|
||||||
typings
|
typings
|
||||||
.vscode
|
.vscode
|
||||||
|
.nyc_output
|
||||||
|
19
package.json
19
package.json
@ -39,14 +39,13 @@
|
|||||||
"start:dev:pg-chain": "export DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; db-migrate up && npm run start:dev",
|
"start:dev:pg-chain": "export DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; db-migrate up && npm run start:dev",
|
||||||
"db-migrate": "db-migrate up",
|
"db-migrate": "db-migrate up",
|
||||||
"db-migrate:down": "db-migrate down",
|
"db-migrate:down": "db-migrate down",
|
||||||
"test": "export PORT=4243 ; mocha --recursive test",
|
"test": "PORT=4243 ava **/**test.js",
|
||||||
"test:unit": "mocha test/unit/**/*.js ",
|
|
||||||
"test:docker": "./scripts/docker-postgres.sh",
|
"test:docker": "./scripts/docker-postgres.sh",
|
||||||
"test:watch": "mocha --watch test test/*",
|
"test:watch": "npm run test -- --watch",
|
||||||
"test:pg-virtualenv": "pg_virtualenv npm run test:pg-virtualenv-chai",
|
"test:pg-virtualenv": "pg_virtualenv npm run test:pg-virtualenv-chai",
|
||||||
"test:pg-virtualenv-chain": "export TEST_DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; npm run db-migrate-testdb && npm test",
|
"test:pg-virtualenv-chain": "export TEST_DATABASE_URL=postgres://$PGUSER:$PGPASSWORD@localhost:$PGPORT/postgres ; npm run db-migrate-testdb && npm test",
|
||||||
"test:coverage": "istanbul cover ./node_modules/mocha/bin/_mocha test --report lcovonly -- -R spec --recursive",
|
"test:coverage": "nyc npm run test",
|
||||||
"test:coverage-report": "cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js && rm -rf ./coverage"
|
"test:coverage-report": "nyc report --reporter=text-lcov | coveralls && rm -rf ./coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "1.15.2",
|
"body-parser": "1.15.2",
|
||||||
@ -70,13 +69,13 @@
|
|||||||
"yallist": "^2.0.0"
|
"yallist": "^2.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/node": "^6.0.46",
|
||||||
"ava": "^0.16.0",
|
"ava": "^0.16.0",
|
||||||
"coveralls": "^2.11.14",
|
"coveralls": "^2.11.15",
|
||||||
"istanbul": "^0.4.5",
|
"nyc": "^8.4.0",
|
||||||
"mocha": "^3.0.2",
|
|
||||||
"mocha-lcov-reporter": "1.2.0",
|
|
||||||
"sinon": "^1.17.5",
|
"sinon": "^1.17.5",
|
||||||
"supertest": "^2.0.0",
|
"superagent": "^2.3.0",
|
||||||
|
"supertest": "^2.0.1",
|
||||||
"supervisor": "^0.11.0",
|
"supervisor": "^0.11.0",
|
||||||
"unleash-frontend": "1.0.0-alpha.2"
|
"unleash-frontend": "1.0.0-alpha.2"
|
||||||
}
|
}
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"mocha": true
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +1,27 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const specHelper = require('./util/test-helper');
|
const test = require('ava');
|
||||||
let request;
|
const { setupApp } = require('./util/test-helper');
|
||||||
|
const logger = require('../../lib/logger');
|
||||||
|
|
||||||
describe('The event api', () => {
|
test.beforeEach(() => {
|
||||||
beforeEach(done => {
|
logger.setLevel('FATAL');
|
||||||
specHelper.setupApp().then((app) => {
|
});
|
||||||
request = app.request;
|
|
||||||
done();
|
test.serial('returns events', async (t) => {
|
||||||
});
|
const { request, destroy } = await setupApp('event_api_serial');
|
||||||
});
|
return request
|
||||||
|
.get('/api/events')
|
||||||
it('returns events', done => {
|
.expect('Content-Type', /json/)
|
||||||
request
|
.expect(200)
|
||||||
.get('/api/events')
|
.then(destroy);
|
||||||
.expect('Content-Type', /json/)
|
});
|
||||||
.expect(200, done);
|
|
||||||
});
|
test.serial('returns events given a name', async (t) => {
|
||||||
|
const { request, destroy } = await setupApp('event_api_serial');
|
||||||
it('returns events given a name', done => {
|
return request
|
||||||
request
|
.get('/api/events/myname')
|
||||||
.get('/api/events/myname')
|
.expect('Content-Type', /json/)
|
||||||
.expect('Content-Type', /json/)
|
.expect(200)
|
||||||
.expect(200, done);
|
.then(destroy);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -1,176 +1,190 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const { test } = require('ava');
|
||||||
|
const { setupApp } = require('./util/test-helper');
|
||||||
const logger = require('../../lib/logger');
|
const logger = require('../../lib/logger');
|
||||||
const assert = require('assert');
|
|
||||||
const specHelper = require('./util/test-helper');
|
|
||||||
const stringify = function (o) {
|
|
||||||
return JSON.stringify(o, null, ' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
let request;
|
test.beforeEach(() => {
|
||||||
|
logger.setLevel('FATAL');
|
||||||
describe('The features api', () => {
|
|
||||||
beforeEach(done => {
|
|
||||||
specHelper.setupApp().then((app) => {
|
|
||||||
request = app.request;
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns three feature toggles', done => {
|
|
||||||
request
|
|
||||||
.get('/features')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert(res.body.features.length === 3, `expected 3 features, got ${stringify(res.body)}`);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('gets a feature by name', done => {
|
|
||||||
request
|
|
||||||
.get('/features/featureX')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('cant get feature that dose not exist', done => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.get('/features/myfeature')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(404, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates new feature toggle', done => {
|
|
||||||
request
|
|
||||||
.post('/features')
|
|
||||||
.send({ name: 'com.test.feature', enabled: false })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(201, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('creates new feature toggle with createdBy', done => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.post('/features')
|
|
||||||
.send({ name: 'com.test.Username', enabled: false })
|
|
||||||
.set('Cookie', ['username=ivaosthu'])
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.end(() => {
|
|
||||||
request
|
|
||||||
.get('/api/events')
|
|
||||||
.end((err, res) => {
|
|
||||||
assert.equal(res.body.events[0].createdBy, 'ivaosthu');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('require new feature toggle to have a name', done => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.post('/features')
|
|
||||||
.send({ name: '' })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(400, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can not change status of feature toggle that does not exist', done => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.put('/features/should-not-exist')
|
|
||||||
.send({ name: 'should-not-exist', enabled: false })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(404, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can change status of feature toggle that does exist', done => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.put('/features/featureY')
|
|
||||||
.send({ name: 'featureY', enabled: true })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(200, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('archives a feature by name', done => {
|
|
||||||
request
|
|
||||||
.delete('/features/featureX')
|
|
||||||
.expect(200, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can not archive unknown feature', done => {
|
|
||||||
request
|
|
||||||
.delete('/features/featureUnknown')
|
|
||||||
.expect(404, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('refuses to create a feature with an existing name', done => {
|
|
||||||
request
|
|
||||||
.post('/features')
|
|
||||||
.send({ name: 'featureX' })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(403, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('refuses to validate a feature with an existing name', done => {
|
|
||||||
request
|
|
||||||
.post('/features-validate')
|
|
||||||
.send({ name: 'featureX' })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(403, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('new strategies api', () => {
|
|
||||||
it('automatically map existing strategy to strategies array', (done) => {
|
|
||||||
request
|
|
||||||
.get('/features/featureY')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert.equal(res.body.strategies.length, 1, 'expected strategy added to strategies');
|
|
||||||
assert.equal(res.body.strategy, res.body.strategies[0].name);
|
|
||||||
assert.deepEqual(res.body.parameters, res.body.strategies[0].parameters);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('can add two strategies to a feature toggle', (done) => {
|
|
||||||
request
|
|
||||||
.put('/features/featureY')
|
|
||||||
.send({
|
|
||||||
name: 'featureY',
|
|
||||||
description: 'soon to be the #14 feature',
|
|
||||||
enabled: false,
|
|
||||||
strategies: [
|
|
||||||
{
|
|
||||||
name: 'baz',
|
|
||||||
parameters: { foo: 'bar' },
|
|
||||||
},
|
|
||||||
] })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(200, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not be allowed to post both strategy and strategies', (done) => {
|
|
||||||
logger.setLevel('FATAL');
|
|
||||||
request
|
|
||||||
.post('/features')
|
|
||||||
.send({
|
|
||||||
name: 'featureConfusing',
|
|
||||||
description: 'soon to be the #14 feature',
|
|
||||||
enabled: false,
|
|
||||||
strategy: 'baz',
|
|
||||||
parameters: {},
|
|
||||||
strategies: [
|
|
||||||
{
|
|
||||||
name: 'baz',
|
|
||||||
parameters: { foo: 'bar' },
|
|
||||||
},
|
|
||||||
] })
|
|
||||||
.set('Content-Type', 'application/json')
|
|
||||||
.expect(400, done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.serial('returns three feature toggles', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.get('/features')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.features.length === 3);
|
||||||
|
})
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('gets a feature by name', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.get('/features/featureX')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('cant get feature that dose not exist', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
return request
|
||||||
|
.get('/features/myfeature')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(404)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('creates new feature toggle', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.post('/features')
|
||||||
|
.send({ name: 'com.test.feature', enabled: false })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(201)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('creates new feature toggle with createdBy', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
request
|
||||||
|
.post('/features')
|
||||||
|
.send({ name: 'com.test.Username', enabled: false })
|
||||||
|
.set('Cookie', ['username=ivaosthu'])
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.end(() => {
|
||||||
|
return request
|
||||||
|
.get('/api/events')
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.events[0].createdBy === 'ivaosthu');
|
||||||
|
})
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('require new feature toggle to have a name', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
return request
|
||||||
|
.post('/features')
|
||||||
|
.send({ name: '' })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(400)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('can not change status of feature toggle that does not exist', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
return request
|
||||||
|
.put('/features/should-not-exist')
|
||||||
|
.send({ name: 'should-not-exist', enabled: false })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(404).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('can change status of feature toggle that does exist', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
return request
|
||||||
|
.put('/features/featureY')
|
||||||
|
.send({ name: 'featureY', enabled: true })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(200).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('archives a feature by name', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.delete('/features/featureX')
|
||||||
|
.expect(200).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('can not archive unknown feature', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.delete('/features/featureUnknown')
|
||||||
|
.expect(404).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('refuses to create a feature with an existing name', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.post('/features')
|
||||||
|
.send({ name: 'featureX' })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(403).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('refuses to validate a feature with an existing name', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.post('/features-validate')
|
||||||
|
.send({ name: 'featureX' })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(403).then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test.serial('new strategies api automatically map existing strategy to strategies array', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
t.plan(3);
|
||||||
|
return request
|
||||||
|
.get('/features/featureY')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.strategies.length === 1, 'expected strategy added to strategies');
|
||||||
|
t.true(res.body.strategy === res.body.strategies[0].name);
|
||||||
|
t.deepEqual(res.body.parameters, res.body.strategies[0].parameters);
|
||||||
|
})
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('new strategies api can add two strategies to a feature toggle', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
return request
|
||||||
|
.put('/features/featureY')
|
||||||
|
.send({
|
||||||
|
name: 'featureY',
|
||||||
|
description: 'soon to be the #14 feature',
|
||||||
|
enabled: false,
|
||||||
|
strategies: [
|
||||||
|
{
|
||||||
|
name: 'baz',
|
||||||
|
parameters: { foo: 'bar' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(200)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('new strategies api should not be allowed to post both strategy and strategies', async t => {
|
||||||
|
const { request, destroy } = await setupApp('feature_api_serial');
|
||||||
|
logger.setLevel('FATAL');
|
||||||
|
return request
|
||||||
|
.post('/features')
|
||||||
|
.send({
|
||||||
|
name: 'featureConfusing',
|
||||||
|
description: 'soon to be the #14 feature',
|
||||||
|
enabled: false,
|
||||||
|
strategy: 'baz',
|
||||||
|
parameters: {},
|
||||||
|
strategies: [
|
||||||
|
{
|
||||||
|
name: 'baz',
|
||||||
|
parameters: { foo: 'bar' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
|
.expect(400)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -1,45 +1,40 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const test = require('ava');
|
||||||
const specHelper = require('./util/test-helper');
|
const { setupApp } = require('./util/test-helper');
|
||||||
const stringify = function (o) {
|
const logger = require('../../lib/logger');
|
||||||
return JSON.stringify(o, null, ' ');
|
|
||||||
};
|
|
||||||
|
|
||||||
let request;
|
test.beforeEach(() => {
|
||||||
|
logger.setLevel('FATAL');
|
||||||
describe('The archive features api', () => {
|
});
|
||||||
beforeEach(done => {
|
|
||||||
specHelper.setupApp().then((app) => {
|
test.serial('returns three archived toggles', async t => {
|
||||||
request = app.request;
|
const { request, destroy } = await setupApp('archive_serial');
|
||||||
done();
|
return request
|
||||||
});
|
.get('/api/archive/features')
|
||||||
});
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
it('returns three archived toggles', done => {
|
t.true(res.body.features.length === 3);
|
||||||
request
|
})
|
||||||
.get('/api/archive/features')
|
.then(destroy);
|
||||||
.expect('Content-Type', /json/)
|
});
|
||||||
.expect(200)
|
|
||||||
.end((err, res) => {
|
test.serial('revives a feature by name', async t => {
|
||||||
assert(res.body.features.length === 3, `expected 3 features, got ${stringify(res.body)}`);
|
const { request, destroy } = await setupApp('archive_serial');
|
||||||
done();
|
return request
|
||||||
});
|
.post('/api/archive/revive')
|
||||||
});
|
.send({ name: 'featureArchivedX' })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
it('revives a feature by name', done => {
|
.expect(200)
|
||||||
request
|
.then(destroy);
|
||||||
.post('/api/archive/revive')
|
});
|
||||||
.send({ name: 'featureArchivedX' })
|
|
||||||
.set('Content-Type', 'application/json')
|
test.serial('must set name when reviving toggle', async t => {
|
||||||
.expect(200, done);
|
const { request, destroy } = await setupApp('archive_serial');
|
||||||
});
|
return request
|
||||||
|
.post('/api/archive/revive')
|
||||||
it('must set name when reviving toggle', done => {
|
.send({ name: '' })
|
||||||
request
|
.expect(400)
|
||||||
.post('/api/archive/revive')
|
.then(destroy);
|
||||||
.send({ name: '' })
|
|
||||||
.expect(400, done);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -1,64 +1,65 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
const test = require('ava');
|
||||||
|
const { setupApp } = require('./util/test-helper');
|
||||||
|
const logger = require('../../lib/logger');
|
||||||
|
|
||||||
const specHelper = require('./util/test-helper');
|
test.beforeEach(() => {
|
||||||
const assert = require('assert');
|
logger.setLevel('FATAL');
|
||||||
let request;
|
|
||||||
|
|
||||||
describe('The metrics api', () => {
|
|
||||||
beforeEach(done => {
|
|
||||||
specHelper.setupApp().then((app) => {
|
|
||||||
request = app.request;
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should register client', (done) => {
|
|
||||||
request
|
|
||||||
.post('/api/client/register')
|
|
||||||
.send({
|
|
||||||
appName: 'demo',
|
|
||||||
instanceId: 'test',
|
|
||||||
strategies: ['default'],
|
|
||||||
started: Date.now(),
|
|
||||||
interval: 10
|
|
||||||
})
|
|
||||||
.expect(202, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should accept client metrics', (done) => {
|
|
||||||
request
|
|
||||||
.post('/api/client/metrics')
|
|
||||||
.send({
|
|
||||||
appName: 'demo',
|
|
||||||
instanceId: '1',
|
|
||||||
bucket: {
|
|
||||||
start: Date.now(),
|
|
||||||
stop: Date.now(),
|
|
||||||
toggles: {}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.expect(202, done)
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get client strategies', done => {
|
|
||||||
request
|
|
||||||
.get('/api/client/strategies')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert(res.status, 200);
|
|
||||||
assert(res.body.length === 1, `expected 1 registerd client, got ${res.body}`);
|
|
||||||
done();
|
|
||||||
});;
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get client instances', done => {
|
|
||||||
request
|
|
||||||
.get('/api/client/instances')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert(res.status, 200);
|
|
||||||
assert(res.body.length === 1, `expected 1 registerd client, got ${res.body}`);
|
|
||||||
done();
|
|
||||||
});;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test.serial('should register client', async (t) => {
|
||||||
|
const { request, destroy } = await setupApp('metrics_serial');
|
||||||
|
return request
|
||||||
|
.post('/api/client/register')
|
||||||
|
.send({
|
||||||
|
appName: 'demo',
|
||||||
|
instanceId: 'test',
|
||||||
|
strategies: ['default'],
|
||||||
|
started: Date.now(),
|
||||||
|
interval: 10
|
||||||
|
})
|
||||||
|
.expect(202)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('should accept client metrics', async t => {
|
||||||
|
const { request, destroy } = await setupApp('metrics_serial');
|
||||||
|
return request
|
||||||
|
.post('/api/client/metrics')
|
||||||
|
.send({
|
||||||
|
appName: 'demo',
|
||||||
|
instanceId: '1',
|
||||||
|
bucket: {
|
||||||
|
start: Date.now(),
|
||||||
|
stop: Date.now(),
|
||||||
|
toggles: {}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.expect(202)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('should get client strategies', async t => {
|
||||||
|
const { request, destroy } = await setupApp('metrics_serial');
|
||||||
|
return request
|
||||||
|
.get('/api/client/strategies')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.status === 200);
|
||||||
|
t.true(res.body.length === 1);
|
||||||
|
})
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('should get client instances', async t => {
|
||||||
|
const { request, destroy } = await setupApp('metrics_serial');
|
||||||
|
return request
|
||||||
|
.get('/api/client/instances')
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.status === 200);
|
||||||
|
t.true(res.body.length === 1);
|
||||||
|
})
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const specHelper = require('./util/test-helper');
|
const test = require('ava');
|
||||||
|
const { setupApp } = require('./util/test-helper');
|
||||||
|
const logger = require('../../lib/logger');
|
||||||
|
|
||||||
let request;
|
test.beforeEach(() => {
|
||||||
|
logger.setLevel('FATAL');
|
||||||
describe('The routes', () => {
|
});
|
||||||
beforeEach(done => {
|
|
||||||
specHelper.setupApp().then((app) => {
|
test('returns health good', async (t) => {
|
||||||
request = app.request;
|
const { request, destroy } = await setupApp('health');
|
||||||
done();
|
return request.get('/health')
|
||||||
});
|
.expect('Content-Type', /json/)
|
||||||
});
|
.expect(200)
|
||||||
|
.expect('{"health":"GOOD"}')
|
||||||
describe('healthcheck', () => {
|
.then(destroy);
|
||||||
it('returns health good', done => {
|
|
||||||
request.get('/health')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.expect('{"health":"GOOD"}', done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -1,70 +1,81 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const specHelper = require('./util/test-helper');
|
const test = require('ava');
|
||||||
let request;
|
const { setupApp } = require('./util/test-helper');
|
||||||
|
const logger = require('../../lib/logger');
|
||||||
|
|
||||||
describe('The strategy api', () => {
|
test.beforeEach(() => {
|
||||||
beforeEach(done => {
|
logger.setLevel('FATAL');
|
||||||
specHelper.setupApp().then((app) => {
|
});
|
||||||
request = app.request;
|
|
||||||
done();
|
test.serial('gets all strategies', async (t) => {
|
||||||
});
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
});
|
return request
|
||||||
|
.get('/api/strategies')
|
||||||
it('gets all strategies', done => {
|
.expect('Content-Type', /json/)
|
||||||
request
|
.expect(200)
|
||||||
.get('/api/strategies')
|
.then(destroy);
|
||||||
.expect('Content-Type', /json/)
|
});
|
||||||
.expect(200, done);
|
|
||||||
});
|
test.serial('gets a strategy by name', async (t) => {
|
||||||
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
it('gets a strategy by name', done => {
|
return request
|
||||||
request
|
.get('/api/strategies/default')
|
||||||
.get('/api/strategies/default')
|
.expect('Content-Type', /json/)
|
||||||
.expect('Content-Type', /json/)
|
.expect(200)
|
||||||
.expect(200, done);
|
.then(destroy);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('cant get a strategy by name that dose not exist', done => {
|
test.serial('cant get a strategy by name that dose not exist', async (t) => {
|
||||||
request
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
.get('/api/strategies/mystrategy')
|
return request
|
||||||
.expect('Content-Type', /json/)
|
.get('/api/strategies/mystrategy')
|
||||||
.expect(404, done);
|
.expect('Content-Type', /json/)
|
||||||
});
|
.expect(404)
|
||||||
|
.then(destroy);
|
||||||
it('creates a new strategy', done => {
|
});
|
||||||
request
|
|
||||||
.post('/api/strategies')
|
test.serial('creates a new strategy', async (t) => {
|
||||||
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.' })
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
.set('Content-Type', 'application/json')
|
return request
|
||||||
.expect(201, done);
|
.post('/api/strategies')
|
||||||
});
|
.send({ name: 'myCustomStrategy', description: 'Best strategy ever.' })
|
||||||
|
.set('Content-Type', 'application/json')
|
||||||
it('requires new strategies to have a name', done => {
|
.expect(201)
|
||||||
request
|
.then(destroy);
|
||||||
.post('/api/strategies')
|
});
|
||||||
.send({ name: '' })
|
|
||||||
.set('Content-Type', 'application/json')
|
test.serial('requires new strategies to have a name', async (t) => {
|
||||||
.expect(400, done);
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
});
|
return request
|
||||||
|
.post('/api/strategies')
|
||||||
it('refuses to create a strategy with an existing name', done => {
|
.send({ name: '' })
|
||||||
request
|
.set('Content-Type', 'application/json')
|
||||||
.post('/api/strategies')
|
.expect(400)
|
||||||
.send({ name: 'default' })
|
.then(destroy);
|
||||||
.set('Content-Type', 'application/json')
|
});
|
||||||
.expect(403, done);
|
|
||||||
});
|
test.serial('refuses to create a strategy with an existing name', async (t) => {
|
||||||
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
it('deletes a new strategy', done => {
|
return request
|
||||||
request
|
.post('/api/strategies')
|
||||||
.delete('/api/strategies/usersWithEmail')
|
.send({ name: 'default' })
|
||||||
.expect(200, done);
|
.set('Content-Type', 'application/json')
|
||||||
});
|
.expect(403)
|
||||||
|
.then(destroy);
|
||||||
it('can\'t delete a strategy that dose not exist', done => {
|
});
|
||||||
request
|
|
||||||
.delete('/api/strategies/unknown')
|
test.serial('deletes a new strategy', async (t) => {
|
||||||
.expect(404, done);
|
const { request, destroy } = await setupApp('strategy_api_serial');
|
||||||
});
|
return request
|
||||||
|
.delete('/api/strategies/usersWithEmail')
|
||||||
|
.expect(200)
|
||||||
|
.then(destroy);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.serial('can\'t delete a strategy that dose not exist', async (t) => {
|
||||||
|
const { request, destroy } = await setupApp('strategy_api_serial', false);
|
||||||
|
return request
|
||||||
|
.delete('/api/strategies/unknown')
|
||||||
|
.expect(404);
|
||||||
});
|
});
|
||||||
|
@ -2,28 +2,39 @@
|
|||||||
|
|
||||||
process.env.NODE_ENV = 'test';
|
process.env.NODE_ENV = 'test';
|
||||||
|
|
||||||
let supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
|
|
||||||
const options = {
|
|
||||||
databaseUri: require('./database-config').getDatabaseUri(),
|
|
||||||
databaseSchema: 'test'
|
|
||||||
};
|
|
||||||
|
|
||||||
const migrator = require('../../../migrator');
|
const migrator = require('../../../migrator');
|
||||||
const { createStores } = require('../../../lib/db');
|
const { createStores } = require('../../../lib/db');
|
||||||
|
const { createDb } = require('../../../lib/db/db-pool');
|
||||||
|
const _app = require('../../../app');
|
||||||
|
|
||||||
// because of migrator bug
|
// because of migrator bug
|
||||||
delete process.env.DATABASE_URL;
|
delete process.env.DATABASE_URL;
|
||||||
|
|
||||||
const db = require('../../../lib/db/db-pool').createDb(options.databaseUri);
|
function createApp (databaseSchema = 'test') {
|
||||||
|
const options = {
|
||||||
|
databaseUri: require('./database-config').getDatabaseUri(),
|
||||||
|
databaseSchema,
|
||||||
|
minPool: 0,
|
||||||
|
maxPool: 0,
|
||||||
|
};
|
||||||
|
const db = createDb({ databaseUri: options.databaseUri, minPool: 0, maxPool: 0 });
|
||||||
|
|
||||||
const createApp = db.raw(`DROP SCHEMA IF EXISTS ${options.databaseSchema} CASCADE; CREATE SCHEMA ${options.databaseSchema}`)
|
return db.raw(`DROP SCHEMA IF EXISTS ${options.databaseSchema} CASCADE; CREATE SCHEMA ${options.databaseSchema}`)
|
||||||
.then(() => migrator(options.databaseUri, options.databaseSchema))
|
.then(() => migrator(options))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const stores = createStores(options);
|
db.destroy();
|
||||||
const app = require('../../../app')({stores});
|
const stores = createStores(options);
|
||||||
return { stores, request: supertest(app) };
|
const app = _app({ stores });
|
||||||
});
|
return {
|
||||||
|
stores,
|
||||||
|
request: supertest(app),
|
||||||
|
destroy () {
|
||||||
|
return stores.db.destroy();
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createStrategies (stores) {
|
function createStrategies (stores) {
|
||||||
return [
|
return [
|
||||||
@ -49,7 +60,7 @@ function createClientStrategy (stores) {
|
|||||||
instanceId: 'test-1',
|
instanceId: 'test-1',
|
||||||
strategies: ['default'],
|
strategies: ['default'],
|
||||||
started: Date.now(),
|
started: Date.now(),
|
||||||
interval: 10
|
interval: 10,
|
||||||
},
|
},
|
||||||
].map(client => stores.clientStrategyStore.insert(client));
|
].map(client => stores.clientStrategyStore.insert(client));
|
||||||
}
|
}
|
||||||
@ -61,7 +72,7 @@ function createClientInstance (stores) {
|
|||||||
instanceId: 'test-1',
|
instanceId: 'test-1',
|
||||||
strategies: ['default'],
|
strategies: ['default'],
|
||||||
started: Date.now(),
|
started: Date.now(),
|
||||||
interval: 10
|
interval: 10,
|
||||||
},
|
},
|
||||||
].map(client => stores.clientInstanceStore.insert(client));
|
].map(client => stores.clientInstanceStore.insert(client));
|
||||||
}
|
}
|
||||||
@ -132,10 +143,10 @@ function createFeatures (stores) {
|
|||||||
|
|
||||||
function resetDatabase (stores) {
|
function resetDatabase (stores) {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
stores.db('strategies').del(),
|
stores.db('strategies').del(),
|
||||||
stores.db('features').del(),
|
stores.db('features').del(),
|
||||||
stores.db('client_strategies').del(),
|
stores.db('client_strategies').del(),
|
||||||
stores.db('client_instances').del()
|
stores.db('client_instances').del(),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,15 +155,15 @@ function setupDatabase (stores) {
|
|||||||
createStrategies(stores)
|
createStrategies(stores)
|
||||||
.concat(createFeatures(stores)
|
.concat(createFeatures(stores)
|
||||||
.concat(createClientInstance(stores))
|
.concat(createClientInstance(stores))
|
||||||
.concat(createClientStrategy(stores))))
|
.concat(createClientStrategy(stores))));
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
setupApp () {
|
setupApp (name) {
|
||||||
return createApp.then((app) => {
|
return createApp(name).then((app) => {
|
||||||
return resetDatabase(app.stores)
|
return resetDatabase(app.stores)
|
||||||
.then(() => setupDatabase(app.stores))
|
.then(() => setupDatabase(app.stores))
|
||||||
.then(() => app);
|
.then(() => app);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
@ -1,99 +1,103 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const test = require('ava');
|
||||||
const eventDiffer = require('../../lib/event-differ');
|
const eventDiffer = require('../../lib/event-differ');
|
||||||
const eventType = require('../../lib/event-type');
|
const eventType = require('../../lib/event-type');
|
||||||
const assert = require('assert');
|
const logger = require('../../lib/logger');
|
||||||
|
|
||||||
describe('eventDiffer', () => {
|
test.beforeEach(() => {
|
||||||
it('fails if events include an unknown event type', () => {
|
logger.setLevel('FATAL');
|
||||||
const events = [
|
});
|
||||||
{ type: eventType.featureCreated, data: {} },
|
|
||||||
{ type: 'unknown-type', data: {} },
|
|
||||||
];
|
|
||||||
|
|
||||||
assert.throws(() => {
|
test('fails if events include an unknown event type', t => {
|
||||||
eventDiffer.addDiffs(events);
|
const events = [
|
||||||
});
|
{ type: eventType.featureCreated, data: {} },
|
||||||
});
|
{ type: 'unknown-type', data: {} },
|
||||||
|
];
|
||||||
it('diffs a feature-update event', () => {
|
|
||||||
const feature = 'foo';
|
|
||||||
const desc = 'bar';
|
|
||||||
|
|
||||||
const events = [
|
|
||||||
{
|
|
||||||
type: eventType.featureUpdated,
|
|
||||||
data: { name: feature, description: desc, strategy: 'default', enabled: true, parameters: { value: 2 } },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: eventType.featureCreated,
|
|
||||||
data: { name: feature, description: desc, strategy: 'default', enabled: false, parameters: { value: 1 } },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
|
t.throws(() => {
|
||||||
eventDiffer.addDiffs(events);
|
eventDiffer.addDiffs(events);
|
||||||
|
|
||||||
assert.deepEqual(events[0].diffs, [
|
|
||||||
{ kind: 'E', path: ['enabled'], lhs: false, rhs: true },
|
|
||||||
{ kind: 'E', path: ['parameters', 'value'], lhs: 1, rhs: 2 },
|
|
||||||
]);
|
|
||||||
|
|
||||||
assert.strictEqual(events[1].diffs, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('diffs only against features with the same name', () => {
|
|
||||||
const events = [
|
|
||||||
{
|
|
||||||
type: eventType.featureUpdated,
|
|
||||||
data: { name: 'bar', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: eventType.featureUpdated,
|
|
||||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: false, parameters: {} },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: eventType.featureCreated,
|
|
||||||
data: { name: 'bar', description: 'desc', strategy: 'default', enabled: false, parameters: {} },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: eventType.featureCreated,
|
|
||||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
eventDiffer.addDiffs(events);
|
|
||||||
|
|
||||||
assert.strictEqual(events[0].diffs[0].rhs, true);
|
|
||||||
assert.strictEqual(events[1].diffs[0].rhs, false);
|
|
||||||
assert.strictEqual(events[2].diffs, null);
|
|
||||||
assert.strictEqual(events[3].diffs, null);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets an empty array of diffs if nothing was changed', () => {
|
|
||||||
const events = [
|
|
||||||
{
|
|
||||||
type: eventType.featureUpdated,
|
|
||||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: eventType.featureCreated,
|
|
||||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
eventDiffer.addDiffs(events);
|
|
||||||
assert.deepEqual(events[0].diffs, []);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sets diffs to null if there was nothing to diff against', () => {
|
|
||||||
const events = [
|
|
||||||
{
|
|
||||||
type: eventType.featureUpdated,
|
|
||||||
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
eventDiffer.addDiffs(events);
|
|
||||||
assert.strictEqual(events[0].diffs, null);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('diffs a feature-update event', t => {
|
||||||
|
const feature = 'foo';
|
||||||
|
const desc = 'bar';
|
||||||
|
|
||||||
|
const events = [
|
||||||
|
{
|
||||||
|
type: eventType.featureUpdated,
|
||||||
|
data: { name: feature, description: desc, strategy: 'default', enabled: true, parameters: { value: 2 } },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: eventType.featureCreated,
|
||||||
|
data: { name: feature, description: desc, strategy: 'default', enabled: false, parameters: { value: 1 } },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
eventDiffer.addDiffs(events);
|
||||||
|
|
||||||
|
t.deepEqual(events[0].diffs, [
|
||||||
|
{ kind: 'E', path: ['enabled'], lhs: false, rhs: true },
|
||||||
|
{ kind: 'E', path: ['parameters', 'value'], lhs: 1, rhs: 2 },
|
||||||
|
]);
|
||||||
|
|
||||||
|
t.true(events[1].diffs === null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('diffs only against features with the same name', t => {
|
||||||
|
const events = [
|
||||||
|
{
|
||||||
|
type: eventType.featureUpdated,
|
||||||
|
data: { name: 'bar', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: eventType.featureUpdated,
|
||||||
|
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: false, parameters: {} },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: eventType.featureCreated,
|
||||||
|
data: { name: 'bar', description: 'desc', strategy: 'default', enabled: false, parameters: {} },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: eventType.featureCreated,
|
||||||
|
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
eventDiffer.addDiffs(events);
|
||||||
|
|
||||||
|
t.true(events[0].diffs[0].rhs === true);
|
||||||
|
t.true(events[1].diffs[0].rhs === false);
|
||||||
|
t.true(events[2].diffs === null);
|
||||||
|
t.true(events[3].diffs === null);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sets an empty array of diffs if nothing was changed', t => {
|
||||||
|
const events = [
|
||||||
|
{
|
||||||
|
type: eventType.featureUpdated,
|
||||||
|
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: eventType.featureCreated,
|
||||||
|
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
eventDiffer.addDiffs(events);
|
||||||
|
t.deepEqual(events[0].diffs, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('sets diffs to null if there was nothing to diff against', t => {
|
||||||
|
const events = [
|
||||||
|
{
|
||||||
|
type: eventType.featureUpdated,
|
||||||
|
data: { name: 'foo', description: 'desc', strategy: 'default', enabled: true, parameters: {} },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
eventDiffer.addDiffs(events);
|
||||||
|
t.true(events[0].diffs === null);
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -1,66 +1,63 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const assert = require('assert');
|
const test = require('ava');
|
||||||
|
|
||||||
const mapper = require('../../../lib/helper/legacy-feature-mapper');
|
const mapper = require('../../../lib/helper/legacy-feature-mapper');
|
||||||
|
|
||||||
describe('legacy-feature-mapper', () => {
|
test('adds old fields to feature', t => {
|
||||||
it('adds old fields to feature', () => {
|
const feature = {
|
||||||
const feature = {
|
name: 'test',
|
||||||
name: 'test',
|
enabled: 0,
|
||||||
enabled: 0,
|
strategies: [{
|
||||||
strategies: [{
|
name: 'default',
|
||||||
name: 'default',
|
|
||||||
parameters: {
|
|
||||||
val: 'bar',
|
|
||||||
},
|
|
||||||
}],
|
|
||||||
};
|
|
||||||
|
|
||||||
const mappedFeature = mapper.addOldFields(feature);
|
|
||||||
|
|
||||||
assert.equal(mappedFeature.name, feature.name);
|
|
||||||
assert.equal(mappedFeature.enabled, feature.enabled);
|
|
||||||
assert.equal(mappedFeature.strategy, feature.strategies[0].name);
|
|
||||||
assert.notEqual(mappedFeature.parameters, feature.strategies[0].parameters);
|
|
||||||
assert.deepEqual(mappedFeature.parameters, feature.strategies[0].parameters);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('transforms fields to new format', () => {
|
|
||||||
const feature = {
|
|
||||||
name: 'test',
|
|
||||||
enabled: 0,
|
|
||||||
strategy: 'default',
|
|
||||||
parameters: {
|
parameters: {
|
||||||
val: 'bar',
|
val: 'bar',
|
||||||
},
|
},
|
||||||
};
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
const mappedFeature = mapper.toNewFormat(feature);
|
const mappedFeature = mapper.addOldFields(feature);
|
||||||
|
|
||||||
assert.equal(mappedFeature.name, feature.name);
|
t.true(mappedFeature.name === feature.name);
|
||||||
assert.equal(mappedFeature.enabled, feature.enabled);
|
t.true(mappedFeature.enabled === feature.enabled);
|
||||||
assert.equal(mappedFeature.strategies.length, 1);
|
t.true(mappedFeature.strategy === feature.strategies[0].name);
|
||||||
assert.equal(mappedFeature.strategies[0].name, feature.strategy);
|
t.true(mappedFeature.parameters !== feature.strategies[0].parameters);
|
||||||
assert.deepEqual(mappedFeature.strategies[0].parameters, feature.parameters);
|
t.deepEqual(mappedFeature.parameters, feature.strategies[0].parameters);
|
||||||
assert(mappedFeature.strategy === undefined);
|
});
|
||||||
assert(mappedFeature.parameters === undefined);
|
|
||||||
});
|
test('transforms fields to new format', t => {
|
||||||
|
const feature = {
|
||||||
it('should not transform if it already is the new format', () => {
|
name: 'test',
|
||||||
const feature = {
|
enabled: 0,
|
||||||
name: 'test',
|
strategy: 'default',
|
||||||
enabled: 0,
|
parameters: {
|
||||||
strategies: [{
|
val: 'bar',
|
||||||
name: 'default',
|
},
|
||||||
parameters: {
|
};
|
||||||
val: 'bar',
|
|
||||||
},
|
const mappedFeature = mapper.toNewFormat(feature);
|
||||||
}],
|
|
||||||
};
|
t.true(mappedFeature.name === feature.name);
|
||||||
|
t.true(mappedFeature.enabled === feature.enabled);
|
||||||
const mappedFeature = mapper.toNewFormat(feature);
|
t.true(mappedFeature.strategies.length === 1);
|
||||||
|
t.true(mappedFeature.strategies[0].name === feature.strategy);
|
||||||
assert.equal(mappedFeature, feature);
|
t.deepEqual(mappedFeature.strategies[0].parameters, feature.parameters);
|
||||||
});
|
t.true(mappedFeature.strategy === undefined);
|
||||||
|
t.true(mappedFeature.parameters === undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not transform if it already is the new format', t => {
|
||||||
|
const feature = {
|
||||||
|
name: 'test',
|
||||||
|
enabled: 0,
|
||||||
|
strategies: [{
|
||||||
|
name: 'default',
|
||||||
|
parameters: {
|
||||||
|
val: 'bar',
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
||||||
|
const mappedFeature = mapper.toNewFormat(feature);
|
||||||
|
|
||||||
|
t.true(mappedFeature === feature);
|
||||||
});
|
});
|
||||||
|
@ -1,61 +1,63 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const test = require('ava');
|
||||||
const store = require('./mocks/store');
|
const store = require('./mocks/store');
|
||||||
|
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const logger = require('../../../lib/logger');
|
||||||
|
|
||||||
|
test.beforeEach(() => {
|
||||||
let request;
|
logger.setLevel('FATAL');
|
||||||
let featureToggleStore;
|
|
||||||
|
|
||||||
describe('Unit: The features api', () => {
|
|
||||||
beforeEach(done => {
|
|
||||||
const stores = store.createStores();
|
|
||||||
const app = require('../../../app')({
|
|
||||||
baseUriPath: '',
|
|
||||||
stores: stores,
|
|
||||||
});
|
|
||||||
|
|
||||||
featureToggleStore = stores.featureToggleStore;
|
|
||||||
request = supertest(app);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get empty getFeatures', (done) => {
|
|
||||||
request
|
|
||||||
.get('/features')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert(res.body.features.length === 0);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should get one getFeature', (done) => {
|
|
||||||
featureToggleStore.addFeature( { name: 'test', strategies: [{ name: 'default' }] } );
|
|
||||||
|
|
||||||
request
|
|
||||||
.get('/features')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert(res.body.features.length === 1);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should add version numbers for /features', (done) => {
|
|
||||||
featureToggleStore.addFeature( { name: 'test', strategies: [{ name: 'default' }] } );
|
|
||||||
|
|
||||||
request
|
|
||||||
.get('/features')
|
|
||||||
.expect('Content-Type', /json/)
|
|
||||||
.expect(200)
|
|
||||||
.end((err, res) => {
|
|
||||||
assert.equal(res.body.version, 1);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getSetup () {
|
||||||
|
const base = `/random${Math.round(Math.random() * 1000)}`;
|
||||||
|
const stores = store.createStores();
|
||||||
|
const app = require('../../../app')({
|
||||||
|
baseUriPath: base,
|
||||||
|
stores,
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
base,
|
||||||
|
featureToggleStore: stores.featureToggleStore,
|
||||||
|
request: supertest(app),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('should get empty getFeatures', t => {
|
||||||
|
const { request, base } = getSetup();
|
||||||
|
return request
|
||||||
|
.get(`${base}/features`)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.features.length === 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should get one getFeature', t => {
|
||||||
|
const { request, featureToggleStore, base } = getSetup();
|
||||||
|
featureToggleStore.addFeature({ name: 'test_', strategies: [{ name: 'default_' }] });
|
||||||
|
|
||||||
|
return request
|
||||||
|
.get(`${base}/features`)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.features.length === 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should add version numbers for /features', t => {
|
||||||
|
const { request, featureToggleStore, base } = getSetup();
|
||||||
|
featureToggleStore.addFeature({ name: 'test2', strategies: [{ name: 'default' }] });
|
||||||
|
|
||||||
|
return request
|
||||||
|
.get(`${base}/features`)
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
.expect((res) => {
|
||||||
|
t.true(res.body.version === 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -1,68 +1,74 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const test = require('ava');
|
||||||
const store = require('./mocks/store');
|
const store = require('./mocks/store');
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const logger = require('../../../lib/logger');
|
||||||
|
|
||||||
let request;
|
test.beforeEach(() => {
|
||||||
|
logger.setLevel('FATAL');
|
||||||
describe('Unit: The metrics api', () => {
|
});
|
||||||
beforeEach(done => {
|
|
||||||
const stores = store.createStores();
|
function getSetup () {
|
||||||
const app = require('../../../app')({
|
const stores = store.createStores();
|
||||||
baseUriPath: '',
|
const app = require('../../../app')({
|
||||||
stores: stores,
|
baseUriPath: '',
|
||||||
});
|
stores,
|
||||||
|
});
|
||||||
request = supertest(app);
|
|
||||||
done();
|
return {
|
||||||
});
|
request: supertest(app),
|
||||||
|
};
|
||||||
it('should register client', (done) => {
|
}
|
||||||
request
|
|
||||||
.post('/api/client/register')
|
test('should register client', () => {
|
||||||
.send({
|
const { request } = getSetup();
|
||||||
appName: 'demo',
|
return request
|
||||||
instanceId: 'test',
|
.post('/api/client/register')
|
||||||
strategies: ['default'],
|
.send({
|
||||||
started: Date.now(),
|
appName: 'demo',
|
||||||
interval: 10
|
instanceId: 'test',
|
||||||
})
|
strategies: ['default'],
|
||||||
.expect(202, done);
|
started: Date.now(),
|
||||||
});
|
interval: 10,
|
||||||
|
})
|
||||||
it('should require appName field', (done) => {
|
.expect(202);
|
||||||
request
|
});
|
||||||
.post('/api/client/register')
|
|
||||||
.expect(400, done)
|
test('should require appName field', () => {
|
||||||
});
|
const { request } = getSetup();
|
||||||
|
return request
|
||||||
it('should require strategies field', (done) => {
|
.post('/api/client/register')
|
||||||
request
|
.expect(400);
|
||||||
.post('/api/client/register')
|
});
|
||||||
.send({
|
|
||||||
appName: 'demo',
|
test('should require strategies field', () => {
|
||||||
instanceId: 'test',
|
const { request } = getSetup();
|
||||||
//strategies: ['default'],
|
return request
|
||||||
started: Date.now(),
|
.post('/api/client/register')
|
||||||
interval: 10
|
.send({
|
||||||
})
|
appName: 'demo',
|
||||||
.expect(400, done)
|
instanceId: 'test',
|
||||||
});
|
// strategies: ['default'],
|
||||||
|
started: Date.now(),
|
||||||
|
interval: 10,
|
||||||
it('should accept client metrics', (done) => {
|
})
|
||||||
request
|
.expect(400);
|
||||||
.post('/api/client/metrics')
|
});
|
||||||
.send({
|
|
||||||
appName: 'demo',
|
|
||||||
instanceId: '1',
|
test('should accept client metrics', () => {
|
||||||
bucket: {
|
const { request } = getSetup();
|
||||||
start: Date.now(),
|
return request
|
||||||
stop: Date.now(),
|
.post('/api/client/metrics')
|
||||||
toggles: {}
|
.send({
|
||||||
}
|
appName: 'demo',
|
||||||
})
|
instanceId: '1',
|
||||||
.expect(202, done)
|
bucket: {
|
||||||
});
|
start: Date.now(),
|
||||||
|
stop: Date.now(),
|
||||||
|
toggles: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
.expect(202);
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = () => ({
|
||||||
reset: () => {},
|
|
||||||
insert: () => Promise.resolve(),
|
insert: () => Promise.resolve(),
|
||||||
};
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = () => ({
|
||||||
reset: () => {},
|
|
||||||
insert: () => Promise.resolve(),
|
insert: () => Promise.resolve(),
|
||||||
};
|
});
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _features = [];
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = () => {
|
||||||
getFeatures: () => Promise.resolve(_features),
|
const _features = [];
|
||||||
addFeature: (feature) => _features.push(feature),
|
return {
|
||||||
reset: () => {
|
getFeatures: () => Promise.resolve(_features),
|
||||||
_features.lengyh = 0;
|
addFeature: (feature) => _features.push(feature),
|
||||||
},
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = () => ({
|
||||||
reset: () => {},
|
|
||||||
getMetricsLastHour: () => Promise.resolve([]),
|
getMetricsLastHour: () => Promise.resolve([]),
|
||||||
insert: () => Promise.resolve(),
|
insert: () => Promise.resolve(),
|
||||||
};
|
});
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const _strategies = [{ name: 'default', parameters: {} }];
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
getStrategies: () => Promise.resolve(_strategies),
|
module.exports = () => {
|
||||||
addStrategy: (strat) => _strategies.push(strat),
|
const _strategies = [{ name: 'default', parameters: {} }];
|
||||||
reset: () => {
|
|
||||||
_strategies.length = 0;
|
return {
|
||||||
},
|
getStrategies: () => Promise.resolve(_strategies),
|
||||||
|
addStrategy: (strat) => _strategies.push(strat),
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
const sinon = require('sinon');
|
'use strict';
|
||||||
|
|
||||||
const clientMetricsStore = require('./fake-metrics-store');
|
const clientMetricsStore = require('./fake-metrics-store');
|
||||||
const clientStrategyStore = require('./fake-client-strategy-store');
|
const clientStrategyStore = require('./fake-client-strategy-store');
|
||||||
@ -11,27 +11,18 @@ const strategyStore = require('./fake-strategies-store');
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
createStores: () => {
|
createStores: () => {
|
||||||
const db = {
|
const db = {
|
||||||
select: () => {
|
select: () => ({
|
||||||
return {
|
from: () => Promise.resolve(),
|
||||||
from: () => Promise.resolve()
|
}),
|
||||||
}
|
};
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clientMetricsStore.reset();
|
|
||||||
clientStrategyStore.reset();
|
|
||||||
clientInstanceStore.reset();
|
|
||||||
featureToggleStore.reset();
|
|
||||||
strategyStore.reset();
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
db,
|
db,
|
||||||
clientMetricsStore,
|
clientMetricsStore: clientMetricsStore(),
|
||||||
clientStrategyStore,
|
clientStrategyStore: clientStrategyStore(),
|
||||||
clientInstanceStore,
|
clientInstanceStore: clientInstanceStore(),
|
||||||
featureToggleStore,
|
featureToggleStore: featureToggleStore(),
|
||||||
strategyStore,
|
strategyStore: strategyStore(),
|
||||||
}
|
};
|
||||||
|
},
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
@ -1,35 +1,28 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const test = require('ava');
|
||||||
const store = require('./mocks/store');
|
const store = require('./mocks/store');
|
||||||
|
|
||||||
|
|
||||||
const supertest = require('supertest');
|
const supertest = require('supertest');
|
||||||
const assert = require('assert');
|
const logger = require('../../../lib/logger');
|
||||||
const sinon = require('sinon');
|
|
||||||
|
|
||||||
let request;
|
test.beforeEach(() => {
|
||||||
let strategyStore;
|
logger.setLevel('FATAL');
|
||||||
|
});
|
||||||
describe('Unit: The strategies api', () => {
|
|
||||||
beforeEach(done => {
|
test('should add version numbers for /stategies', t => {
|
||||||
const stores = store.createStores();
|
const stores = store.createStores();
|
||||||
const app = require('../../../app')({
|
const app = require('../../../app')({
|
||||||
baseUriPath: '',
|
baseUriPath: '',
|
||||||
stores: stores,
|
stores,
|
||||||
});
|
});
|
||||||
strategyStore = stores.strategyStore;
|
|
||||||
request = supertest(app);
|
const request = supertest(app);
|
||||||
done();
|
|
||||||
});
|
return request
|
||||||
|
.get('/api/strategies')
|
||||||
it('should add version numbers for /stategies', (done) => {
|
.expect('Content-Type', /json/)
|
||||||
request
|
.expect(200)
|
||||||
.get('/api/strategies')
|
.expect((res) => {
|
||||||
.expect('Content-Type', /json/)
|
t.true(res.body.version === 1);
|
||||||
.expect(200)
|
});
|
||||||
.end((err, res) => {
|
|
||||||
assert.equal(res.body.version, 1);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user