mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Begin work on running tests against the database:
* Add Travis postgresql setup. * Replace "db mocks" with a before hook that creates the same data through the HTTP API. * Reset DB and re-create all fixtures for each test. We'll need something better here. * CAVEAT: no concept of a dev vs test database. Running tests will clear data from the currently configured database.
This commit is contained in:
		
							parent
							
								
									6bfde35de0
								
							
						
					
					
						commit
						642c06f6ba
					
				@ -1,8 +1,11 @@
 | 
			
		||||
language: node_js
 | 
			
		||||
node_js:
 | 
			
		||||
- "0.10"
 | 
			
		||||
env: DATABASE_URL=postgres://postgres@localhost:5432/unleash_test
 | 
			
		||||
before_script:
 | 
			
		||||
- echo '--timeout 10000' > test/mocha.opts
 | 
			
		||||
- psql -c 'create database unleash_test;' -U postgres
 | 
			
		||||
- ./node_modules/.bin/db-migrate up
 | 
			
		||||
script:
 | 
			
		||||
- npm install
 | 
			
		||||
- npm test
 | 
			
		||||
@ -11,3 +14,5 @@ notifications:
 | 
			
		||||
  hipchat:
 | 
			
		||||
    rooms:
 | 
			
		||||
      secure: GiIDk52xccnUKnevjLE+w6eUXg0jfV7oOmagw5VnOV5jXGUxdzMk/Q9um+oSClEPE51IvF76zoFEKPIX/CNdjgalEr+CZADy1gene/YRGrNgrXmYYmiU1/dNzelpla1WpKPrY2pkbOgKxrCR9ScID+pMs6vzvJnPwK9vu66W61U=
 | 
			
		||||
addons:
 | 
			
		||||
  postgresql: "9.3"
 | 
			
		||||
@ -18,7 +18,7 @@ module.exports = function (app) {
 | 
			
		||||
    app.get('/strategies/:name', function (req, res) {
 | 
			
		||||
        strategyDb.getStrategy(req.params.name)
 | 
			
		||||
            .then(function (strategy) { res.json(strategy);  })
 | 
			
		||||
            .catch(function () { res.json(404, {error: 'Could not find strategy'}); });
 | 
			
		||||
            .catch(function () { res.status(404).json({error: 'Could not find strategy'}); });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    app.delete('/strategies/:name', function (req, res) {
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,6 @@
 | 
			
		||||
        "jshint": "2.5.2",
 | 
			
		||||
        "mocha": "1.20.1",
 | 
			
		||||
        "mocha-lcov-reporter": "0.0.1",
 | 
			
		||||
        "mockery": "1.4.0",
 | 
			
		||||
        "pre-commit": "0.0.9",
 | 
			
		||||
        "react-tools": "^0.12.0",
 | 
			
		||||
        "supertest": "0.13.0",
 | 
			
		||||
 | 
			
		||||
@ -1,11 +1,6 @@
 | 
			
		||||
var specHelper = require('./specHelper');
 | 
			
		||||
var request = require('./specHelper').request;
 | 
			
		||||
 | 
			
		||||
describe('The event api', function () {
 | 
			
		||||
    var request;
 | 
			
		||||
 | 
			
		||||
    before(function () { request = specHelper.setupMockServer(); });
 | 
			
		||||
    after(specHelper.tearDownMockServer);
 | 
			
		||||
 | 
			
		||||
    it('returns events', function (done) {
 | 
			
		||||
        request
 | 
			
		||||
            .get('/events')
 | 
			
		||||
 | 
			
		||||
@ -1,111 +0,0 @@
 | 
			
		||||
var Promise = require("bluebird");
 | 
			
		||||
 | 
			
		||||
var events = [
 | 
			
		||||
    {
 | 
			
		||||
        "id": 1,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "id": 2,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
            "foo": "bar"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "id": 3,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
            "foo": "rab",
 | 
			
		||||
            "name": "myname"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
var filterableEvents = [
 | 
			
		||||
    {
 | 
			
		||||
        "id": 1,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
            "name": "foo"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "id": 2,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
            "name": "bar"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "id": 3,
 | 
			
		||||
        "created_at": 1414159948677,
 | 
			
		||||
        "type": "feature-create",
 | 
			
		||||
        "created_by": "me",
 | 
			
		||||
        "data": {
 | 
			
		||||
            "name": "myname"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function filterEventsByName(name) {
 | 
			
		||||
    return filterableEvents.filter(function (n){return n.data.name===name;});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getEvent(name) {
 | 
			
		||||
    var eventFound;
 | 
			
		||||
    events.forEach(function (event) {
 | 
			
		||||
        if (event.name === name) {
 | 
			
		||||
            eventFound = event;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return eventFound;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function storeEvent() {
 | 
			
		||||
    return new Promise(function (resolve) {
 | 
			
		||||
        resolve();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    store: storeEvent,
 | 
			
		||||
 | 
			
		||||
    getEvents: function() {
 | 
			
		||||
        return new Promise(function (resolve) {
 | 
			
		||||
            resolve(events);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getEventsFilterByName: function(name) {
 | 
			
		||||
        return new Promise(function (resolve) {
 | 
			
		||||
            resolve(filterEventsByName(name));
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    getEvent: function(name) {
 | 
			
		||||
        var event = getEvent(name);
 | 
			
		||||
        if(event) {
 | 
			
		||||
            return Promise.resolve(event);
 | 
			
		||||
        } else {
 | 
			
		||||
            return Promise.reject("Event not found");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
@ -1,28 +1,8 @@
 | 
			
		||||
var assert = require('assert'),
 | 
			
		||||
    mockery = require('mockery'),
 | 
			
		||||
    eventType = require('../lib/eventType'),
 | 
			
		||||
    eventStore;
 | 
			
		||||
 | 
			
		||||
var assert     = require('assert'),
 | 
			
		||||
    eventType  = require('../lib/eventType'),
 | 
			
		||||
    eventStore = require('../lib/eventStore');
 | 
			
		||||
 | 
			
		||||
describe('EventStore', function () {
 | 
			
		||||
    before(function () {
 | 
			
		||||
        mockery.enable({
 | 
			
		||||
            warnOnReplace: false,
 | 
			
		||||
            warnOnUnregistered: false,
 | 
			
		||||
            useCleanCache: true
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        mockery.registerSubstitute('./eventDb', '../test/eventDbMock');
 | 
			
		||||
        mockery.registerSubstitute('./strategyDb', '../test/strategyDbMock');
 | 
			
		||||
 | 
			
		||||
        eventStore = require('../lib/eventStore');
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(function () {
 | 
			
		||||
        mockery.disable();
 | 
			
		||||
        mockery.deregisterAll();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('#create()', function () {
 | 
			
		||||
        it('should emit event', function (done) {
 | 
			
		||||
            eventStore.once(eventType.featureCreated, function (x) {
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,26 @@
 | 
			
		||||
var assert     = require('assert');
 | 
			
		||||
var specHelper = require('./specHelper');
 | 
			
		||||
var request    = specHelper.request;
 | 
			
		||||
var stringify  = function (o) { return JSON.stringify(o, null, ' '); };
 | 
			
		||||
 | 
			
		||||
describe('The features api', function () {
 | 
			
		||||
    var request;
 | 
			
		||||
    beforeEach(function (done) {
 | 
			
		||||
        var d = function (err) { console.log('done', err); done.bind(null, err)(); };
 | 
			
		||||
 | 
			
		||||
    before(function () { request = specHelper.setupMockServer();  });
 | 
			
		||||
    after(specHelper.tearDownMockServer);
 | 
			
		||||
        specHelper.db.resetAndSetup()
 | 
			
		||||
            .then(d.bind(null, null))
 | 
			
		||||
            .catch(d);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('returns three mocked feature toggles', function (done) {
 | 
			
		||||
    it('returns three feature toggles', function (done) {
 | 
			
		||||
        request
 | 
			
		||||
            .get('/features')
 | 
			
		||||
            .expect('Content-Type', /json/)
 | 
			
		||||
            .expect(200, done);
 | 
			
		||||
            .expect(200)
 | 
			
		||||
            .end(function (err, res) {
 | 
			
		||||
                assert(res.body.features.length === 3, "expected 3 features, got " + stringify(res.body));
 | 
			
		||||
                done();
 | 
			
		||||
            });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('gets a feature by name', function (done) {
 | 
			
		||||
@ -23,7 +33,7 @@ describe('The features api', function () {
 | 
			
		||||
    it('creates new feature toggle', function (done) {
 | 
			
		||||
        request
 | 
			
		||||
            .post('/features')
 | 
			
		||||
            .send({name: 'com.test.feature', 'enabled': false})
 | 
			
		||||
            .send({name: 'com.test.feature', enabled: false})
 | 
			
		||||
            .set('Content-Type', 'application/json')
 | 
			
		||||
            .expect(201, done);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@ -1,56 +0,0 @@
 | 
			
		||||
var Promise = require("bluebird");
 | 
			
		||||
var NotFoundError = require('../lib/error/NotFoundError');
 | 
			
		||||
 | 
			
		||||
var features = [
 | 
			
		||||
    {
 | 
			
		||||
        "name": "featureX",
 | 
			
		||||
        "description": "the #1 feature",
 | 
			
		||||
        "enabled": true,
 | 
			
		||||
        "strategy": "default"
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "featureY",
 | 
			
		||||
        "description": "soon to be the #1 feature",
 | 
			
		||||
        "enabled": false,
 | 
			
		||||
        "strategy": "baz",
 | 
			
		||||
        "parameters": {
 | 
			
		||||
            "foo": "bar"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "name": "featureZ",
 | 
			
		||||
        "description": "terrible feature",
 | 
			
		||||
        "enabled": true,
 | 
			
		||||
        "strategy": "baz",
 | 
			
		||||
        "parameters": {
 | 
			
		||||
            "foo": "rab"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function getFeature(name) {
 | 
			
		||||
    var featureFound;
 | 
			
		||||
    features.forEach(function (feature) {
 | 
			
		||||
        if (feature.name === name) {
 | 
			
		||||
            featureFound = feature;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    return featureFound;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getFeatures: function() {
 | 
			
		||||
        return new Promise(function (resolve) {
 | 
			
		||||
            resolve(features);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    getFeature: function(name) {
 | 
			
		||||
        var feature = getFeature(name);
 | 
			
		||||
        if(feature) {
 | 
			
		||||
            return Promise.resolve(feature);
 | 
			
		||||
        } else {
 | 
			
		||||
            return Promise.reject(new NotFoundError("feature not found"));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@ -1,10 +1,7 @@
 | 
			
		||||
var specHelper = require('./specHelper');
 | 
			
		||||
var request = specHelper.request;
 | 
			
		||||
 | 
			
		||||
describe('The routes', function () {
 | 
			
		||||
    var request;
 | 
			
		||||
 | 
			
		||||
    before(function () { request = specHelper.setupMockServer(); });
 | 
			
		||||
    after(specHelper.tearDownMockServer);
 | 
			
		||||
 | 
			
		||||
    describe('healthcheck', function () {
 | 
			
		||||
        it('returns health good', function (done) {
 | 
			
		||||
 | 
			
		||||
@ -1,37 +1,91 @@
 | 
			
		||||
var request = require('supertest');
 | 
			
		||||
var mockery = require('mockery');
 | 
			
		||||
 | 
			
		||||
process.env.NODE_ENV = 'test';
 | 
			
		||||
 | 
			
		||||
var server;
 | 
			
		||||
var Promise = require('bluebird');
 | 
			
		||||
var request = require('supertest');
 | 
			
		||||
var app     = require('../app');
 | 
			
		||||
var knex    = require('../lib/dbPool');
 | 
			
		||||
 | 
			
		||||
function setupMockServer() {
 | 
			
		||||
    mockery.enable({
 | 
			
		||||
        warnOnReplace: false,
 | 
			
		||||
        warnOnUnregistered: false,
 | 
			
		||||
        useCleanCache: true
 | 
			
		||||
Promise.promisifyAll(request);
 | 
			
		||||
request = request(app);
 | 
			
		||||
 | 
			
		||||
function createStrategies() {
 | 
			
		||||
    return Promise.map([
 | 
			
		||||
        {
 | 
			
		||||
            name: "default",
 | 
			
		||||
            description: "Default on or off Strategy."
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            name: "usersWithEmail",
 | 
			
		||||
            description: "Active for users defined  in the comma-separated emails-parameter.",
 | 
			
		||||
            parametersTemplate: {
 | 
			
		||||
                emails: "String"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ], function (strategy) {
 | 
			
		||||
        return request
 | 
			
		||||
            .post('/strategies').send(strategy)
 | 
			
		||||
            .set('Content-Type', 'application/json')
 | 
			
		||||
            .expect(201)
 | 
			
		||||
            .endAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    mockery.registerSubstitute('./eventDb', '../test/eventDbMock');
 | 
			
		||||
    mockery.registerSubstitute('./featureDb', '../test/featureDbMock');
 | 
			
		||||
    mockery.registerSubstitute('./strategyDb', '../test/strategyDbMock');
 | 
			
		||||
 | 
			
		||||
    var app = require('../app');
 | 
			
		||||
 | 
			
		||||
    return request(app);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function tearDownMockServer() {
 | 
			
		||||
    mockery.disable();
 | 
			
		||||
    mockery.deregisterAll();
 | 
			
		||||
function createFeatures() {
 | 
			
		||||
    return Promise.map([
 | 
			
		||||
        {
 | 
			
		||||
            "name": "featureX",
 | 
			
		||||
            "description": "the #1 feature",
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "strategy": "default"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "featureY",
 | 
			
		||||
            "description": "soon to be the #1 feature",
 | 
			
		||||
            "enabled": false,
 | 
			
		||||
            "strategy": "baz",
 | 
			
		||||
            "parameters": {
 | 
			
		||||
                "foo": "bar"
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "name": "featureZ",
 | 
			
		||||
            "description": "terrible feature",
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "strategy": "baz",
 | 
			
		||||
            "parameters": {
 | 
			
		||||
                "foo": "rab"
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    ], function (feature) {
 | 
			
		||||
        return request
 | 
			
		||||
            .post('/features').send(feature)
 | 
			
		||||
            .set('Content-Type', 'application/json')
 | 
			
		||||
            .expect(201)
 | 
			
		||||
            .endAsync();
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    if (server) {
 | 
			
		||||
        server.server.close();
 | 
			
		||||
        server = null;
 | 
			
		||||
    }
 | 
			
		||||
function destroyStrategies() {
 | 
			
		||||
    return knex('strategies').del();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function destroyFeatures() {
 | 
			
		||||
    return knex('features').del();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function resetDatabase() {
 | 
			
		||||
    return Promise.all([destroyStrategies(), destroyFeatures()]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setupDatabase() {
 | 
			
		||||
    return Promise.all([createStrategies(), createFeatures()]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    setupMockServer: setupMockServer,
 | 
			
		||||
    tearDownMockServer: tearDownMockServer
 | 
			
		||||
    request: request,
 | 
			
		||||
    db: {
 | 
			
		||||
        reset: resetDatabase,
 | 
			
		||||
        setup: setupDatabase,
 | 
			
		||||
        resetAndSetup: function () { return resetDatabase().then(setupDatabase); }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@ -1,10 +1,12 @@
 | 
			
		||||
var specHelper = require('./specHelper');
 | 
			
		||||
var request    = specHelper.request;
 | 
			
		||||
 | 
			
		||||
describe('The strategy api', function () {
 | 
			
		||||
    var request;
 | 
			
		||||
 | 
			
		||||
    before(function () { request = specHelper.setupMockServer(); });
 | 
			
		||||
    after(specHelper.tearDownMockServer);
 | 
			
		||||
    beforeEach(function (done) {
 | 
			
		||||
        specHelper.db.resetAndSetup()
 | 
			
		||||
            .then(done.bind(null, null))
 | 
			
		||||
            .catch(done);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('gets all strategies', function (done) {
 | 
			
		||||
        request
 | 
			
		||||
 | 
			
		||||
@ -1,41 +0,0 @@
 | 
			
		||||
var Promise = require("bluebird");
 | 
			
		||||
 | 
			
		||||
var strategies = [
 | 
			
		||||
    {
 | 
			
		||||
        name: "default",
 | 
			
		||||
        description: "Default on or off Strategy."
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        name: "usersWithEmail",
 | 
			
		||||
        description: "Active for users defined  in the comma-separated emails-parameter.",
 | 
			
		||||
        parametersTemplate: {
 | 
			
		||||
            emails: "String"
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        name: "deletable",
 | 
			
		||||
        description: "deletable"
 | 
			
		||||
    }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
function byName(name) {
 | 
			
		||||
    return strategies.filter(function(s) {
 | 
			
		||||
        return s.name === name;
 | 
			
		||||
    })[0];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    getStrategies: function() {
 | 
			
		||||
        return new Promise(function (resolve) {
 | 
			
		||||
            resolve(strategies);
 | 
			
		||||
        });
 | 
			
		||||
    },
 | 
			
		||||
    getStrategy: function(name) {
 | 
			
		||||
        var strategy = byName(name);
 | 
			
		||||
        if(strategy) {
 | 
			
		||||
            return Promise.resolve(strategy);
 | 
			
		||||
        } else {
 | 
			
		||||
            return Promise.reject("strategy not found");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user