loopback/test/app.test.js

533 lines
16 KiB
JavaScript
Raw Normal View History

var path = require('path');
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-app');
2014-05-03 04:19:14 +00:00
var loopback = require('../');
2014-06-05 07:45:09 +00:00
var PersistedModel = loopback.PersistedModel;
var describe = require('./util/describe');
var it = require('./util/it');
2013-06-07 19:57:51 +00:00
describe('app', function() {
2013-06-06 00:11:21 +00:00
2013-06-07 19:57:51 +00:00
describe('app.model(Model)', function() {
var app, db;
beforeEach(function() {
app = loopback();
db = loopback.createDataSource({connector: loopback.Memory});
});
2013-07-16 20:46:33 +00:00
it("Expose a `Model` to remote clients", function() {
2014-06-05 07:45:09 +00:00
var Color = PersistedModel.extend('color', {name: String});
2013-06-07 19:57:51 +00:00
app.model(Color);
2014-05-03 04:19:14 +00:00
Color.attachTo(db);
expect(app.models()).to.eql([Color]);
});
it('uses singlar name as app.remoteObjects() key', function() {
2014-06-05 07:45:09 +00:00
var Color = PersistedModel.extend('color', {name: String});
app.model(Color);
2014-05-03 04:19:14 +00:00
Color.attachTo(db);
expect(app.remoteObjects()).to.eql({ color: Color });
});
it('uses singular name as shared class name', function() {
2014-06-05 07:45:09 +00:00
var Color = PersistedModel.extend('color', {name: String});
app.model(Color);
2014-05-03 04:19:14 +00:00
Color.attachTo(db);
var classes = app.remotes().classes().map(function(c) {return c.name});
expect(classes).to.contain('color');
});
it('registers existing models to app.models', function() {
var Color = db.createModel('color', {name: String});
app.model(Color);
expect(Color.app).to.be.equal(app);
expect(Color.shared).to.equal(true);
expect(app.models.color).to.equal(Color);
expect(app.models.Color).to.equal(Color);
});
it.onServer('updates REST API when a new model is added', function(done) {
2014-02-19 19:40:05 +00:00
app.use(loopback.rest());
request(app).get('/colors').expect(404, function(err, res) {
if (err) return done(err);
2014-06-05 07:45:09 +00:00
var Color = PersistedModel.extend('color', {name: String});
2014-02-19 19:40:05 +00:00
app.model(Color);
2014-05-03 04:19:14 +00:00
Color.attachTo(db);
2014-02-19 19:40:05 +00:00
request(app).get('/colors').expect(200, done);
});
});
describe('in compat mode', function() {
before(function() {
loopback.compat.usePluralNamesForRemoting = true;
});
after(function() {
loopback.compat.usePluralNamesForRemoting = false;
});
it('uses plural name as shared class name', function() {
var Color = db.createModel('color', {name: String});
app.model(Color);
var classes = app.remotes().classes().map(function(c) {return c.name});
expect(classes).to.contain('colors');
});
it('uses plural name as app.remoteObjects() key', function() {
var Color = db.createModel('color', {name: String});
app.model(Color);
expect(app.remoteObjects()).to.eql({ colors: Color });
});
2013-06-07 19:57:51 +00:00
});
2013-06-06 00:11:21 +00:00
});
2013-06-07 19:57:51 +00:00
describe('app.model(name, config)', function () {
var app;
beforeEach(function() {
app = loopback();
2013-10-29 21:12:23 +00:00
app.boot({
app: {port: 3000, host: '127.0.0.1'},
// prevent loading of models.json, it is not available in the browser
models: {},
2013-10-29 21:12:23 +00:00
dataSources: {
db: {
connector: 'memory'
}
}
});
});
2013-10-29 21:12:23 +00:00
it('Sugar for defining a fully built model', function () {
2013-10-29 21:12:23 +00:00
app.model('foo', {
dataSource: 'db'
});
var Foo = app.models.foo;
var f = new Foo();
2013-10-29 21:12:23 +00:00
assert(f instanceof loopback.Model);
});
it('interprets extra first-level keys as options', function() {
app.model('foo', {
dataSource: 'db',
base: 'User'
});
expect(app.models.foo.definition.settings.base).to.equal('User');
});
it('prefers config.options.key over config.key', function() {
app.model('foo', {
dataSource: 'db',
base: 'User',
options: {
base: 'Application'
}
});
expect(app.models.foo.definition.settings.base).to.equal('Application');
});
it('honors config.public options', function() {
app.model('foo', {
dataSource: 'db',
public: false
});
expect(app.models.foo.app).to.equal(app);
expect(app.models.foo.shared).to.equal(false);
});
it('defaults config.public to be true', function() {
app.model('foo', {
dataSource: 'db'
});
expect(app.models.foo.app).to.equal(app);
expect(app.models.foo.shared).to.equal(true);
});
});
2013-10-29 21:12:23 +00:00
describe('app.model(ModelCtor, config)', function() {
it('attaches the model to a datasource', function() {
app.dataSource('db', { connector: 'memory' });
var TestModel = loopback.Model.extend('TestModel');
// TestModel was most likely already defined in a different test,
// thus TestModel.dataSource may be already set
delete TestModel.dataSource;
app.model(TestModel, { dataSource: 'db' });
expect(app.models.TestModel.dataSource).to.equal(app.dataSources.db);
});
});
describe('app.models', function() {
it('is unique per app instance', function() {
app.dataSource('db', { connector: 'memory' });
var Color = app.model('Color', { dataSource: 'db' });
expect(app.models.Color).to.equal(Color);
var anotherApp = loopback();
expect(anotherApp.models.Color).to.equal(undefined);
});
});
describe('app.dataSources', function() {
it('is unique per app instance', function() {
app.dataSource('ds', { connector: 'memory' });
expect(app.datasources.ds).to.not.equal(undefined);
var anotherApp = loopback();
expect(anotherApp.datasources.ds).to.equal(undefined);
});
});
describe('app.dataSource', function() {
it('looks up the connector in `app.connectors`', function() {
app.connector('custom', loopback.Memory);
app.dataSource('custom', { connector: 'custom' });
expect(app.dataSources.custom.name).to.equal(loopback.Memory.name);
});
});
describe.onServer('app.boot([options])', function () {
2013-10-29 21:12:23 +00:00
beforeEach(function () {
app.boot({
app: {
port: 3000,
host: '127.0.0.1',
restApiRoot: '/rest-api',
foo: {bar: 'bat'},
baz: true
2013-10-29 21:12:23 +00:00
},
models: {
'foo-bar-bat-baz': {
options: {
plural: 'foo-bar-bat-bazzies'
},
dataSource: 'the-db'
}
},
dataSources: {
'the-db': {
connector: 'memory'
}
2013-10-29 21:12:23 +00:00
}
});
});
it('should have port setting', function () {
2013-10-29 21:12:23 +00:00
assert.equal(this.app.get('port'), 3000);
});
it('should have host setting', function() {
2013-10-29 21:12:23 +00:00
assert.equal(this.app.get('host'), '127.0.0.1');
});
it('should have restApiRoot setting', function() {
assert.equal(this.app.get('restApiRoot'), '/rest-api');
});
it('should have other settings', function () {
expect(this.app.get('foo')).to.eql({
bar: 'bat'
});
expect(this.app.get('baz')).to.eql(true);
});
describe('boot and models directories', function() {
beforeEach(function() {
var app = this.app = loopback();
app.boot(SIMPLE_APP);
});
it('should run all modules in the boot directory', function () {
assert(process.loadedFooJS);
delete process.loadedFooJS;
});
it('should run all modules in the models directory', function () {
assert(process.loadedBarJS);
delete process.loadedBarJS;
});
});
describe('PaaS and npm env variables', function() {
beforeEach(function() {
this.boot = function () {
var app = loopback();
app.boot({
app: {
port: undefined,
host: undefined
}
});
return app;
}
});
it('should be honored', function() {
var assertHonored = function (portKey, hostKey) {
process.env[hostKey] = randomPort();
process.env[portKey] = randomHost();
var app = this.boot();
assert.equal(app.get('port'), process.env[portKey]);
assert.equal(app.get('host'), process.env[hostKey]);
delete process.env[portKey];
delete process.env[hostKey];
}.bind(this);
assertHonored('OPENSHIFT_SLS_PORT', 'OPENSHIFT_NODEJS_IP');
assertHonored('npm_config_port', 'npm_config_host');
assertHonored('npm_package_config_port', 'npm_package_config_host');
assertHonored('OPENSHIFT_SLS_PORT', 'OPENSHIFT_SLS_IP');
assertHonored('PORT', 'HOST');
});
it('should be honored in order', function() {
process.env.npm_config_host = randomHost();
process.env.OPENSHIFT_SLS_IP = randomHost();
process.env.OPENSHIFT_NODEJS_IP = randomHost();
process.env.HOST = randomHost();
process.env.npm_package_config_host = randomHost();
var app = this.boot();
assert.equal(app.get('host'), process.env.npm_config_host);
2014-02-18 19:20:23 +00:00
delete process.env.npm_config_host;
delete process.env.OPENSHIFT_SLS_IP;
delete process.env.OPENSHIFT_NODEJS_IP;
delete process.env.HOST;
delete process.env.npm_package_config_host;
process.env.npm_config_port = randomPort();
process.env.OPENSHIFT_SLS_PORT = randomPort();
process.env.OPENSHIFT_NODEJS_PORT = randomPort();
process.env.PORT = randomPort();
process.env.npm_package_config_port = randomPort();
var app = this.boot();
assert.equal(app.get('host'), process.env.npm_config_host);
assert.equal(app.get('port'), process.env.npm_config_port);
2014-02-18 19:20:23 +00:00
delete process.env.npm_config_port;
delete process.env.OPENSHIFT_SLS_PORT;
delete process.env.OPENSHIFT_NODEJS_PORT;
delete process.env.PORT;
delete process.env.npm_package_config_port;
});
function randomHost() {
return Math.random().toString().split('.')[1];
}
function randomPort() {
return Math.floor(Math.random() * 10000);
}
2014-02-18 19:20:23 +00:00
it('should honor 0 for free port', function () {
var app = loopback();
app.boot({app: {port: 0}});
assert.equal(app.get('port'), 0);
});
it('should default to port 3000', function () {
var app = loopback();
app.boot({app: {port: undefined}});
assert.equal(app.get('port'), 3000);
});
});
2013-10-29 21:12:23 +00:00
it('Instantiate models', function () {
assert(app.models);
assert(app.models.FooBarBatBaz);
assert(app.models.fooBarBatBaz);
assertValidDataSource(app.models.FooBarBatBaz.dataSource);
assert.isFunc(app.models.FooBarBatBaz, 'find');
assert.isFunc(app.models.FooBarBatBaz, 'create');
});
it('Attach models to data sources', function () {
assert.equal(app.models.FooBarBatBaz.dataSource, app.dataSources.theDb);
});
it('Instantiate data sources', function () {
assert(app.dataSources);
assert(app.dataSources.theDb);
assertValidDataSource(app.dataSources.theDb);
assert(app.dataSources.TheDb);
});
});
describe.onServer('app.boot(appRootDir)', function () {
2013-10-29 21:12:23 +00:00
it('Load config files', function () {
var app = loopback();
app.boot(SIMPLE_APP);
2013-10-29 21:12:23 +00:00
assert(app.models.foo);
assert(app.models.Foo);
assert(app.models.Foo.dataSource);
assert.isFunc(app.models.Foo, 'find');
assert.isFunc(app.models.Foo, 'create');
});
});
2013-11-19 20:35:29 +00:00
describe.onServer('listen()', function() {
it('starts http server', function(done) {
var app = loopback();
app.set('port', 0);
app.get('/', function(req, res) { res.send(200, 'OK'); });
var server = app.listen();
expect(server).to.be.an.instanceOf(require('http').Server);
request(server)
.get('/')
.expect(200, done);
});
it('updates port on "listening" event', function(done) {
var app = loopback();
app.set('port', 0);
app.listen(function() {
expect(app.get('port'), 'port').to.not.equal(0);
done();
});
});
it('forwards to http.Server.listen on more than one arg', function(done) {
var app = loopback();
app.set('port', 1);
app.listen(0, '127.0.0.1', function() {
expect(app.get('port'), 'port').to.not.equal(0).and.not.equal(1);
expect(this.address().address).to.equal('127.0.0.1');
done();
});
});
it('forwards to http.Server.listen when the single arg is not a function',
function(done) {
var app = loopback();
app.set('port', 1);
app.listen(0).on('listening', function() {
expect(app.get('port'), 'port') .to.not.equal(0).and.not.equal(1);
done();
});
}
);
it('uses app config when no parameter is supplied', function(done) {
var app = loopback();
// Http listens on all interfaces by default
// Custom host serves as an indicator whether
// the value was used by app.listen
app.set('host', '127.0.0.1');
app.listen()
.on('listening', function() {
expect(this.address().address).to.equal('127.0.0.1');
done();
});
});
});
describe.onServer('enableAuth', function() {
it('should set app.isAuthEnabled to true', function() {
expect(app.isAuthEnabled).to.not.equal(true);
app.enableAuth();
expect(app.isAuthEnabled).to.equal(true);
});
});
describe.onServer('app.get("/", loopback.status())', function () {
2013-11-19 20:35:29 +00:00
it('should return the status of the application', function (done) {
var app = loopback();
app.get('/', loopback.status());
request(app)
.get('/')
.expect(200)
.end(function(err, res) {
if(err) return done(err);
assert.equal(typeof res.body, 'object');
assert(res.body.started);
// The number can be 0
assert(res.body.uptime !== undefined);
2013-11-19 20:35:29 +00:00
var elapsed = Date.now() - Number(new Date(res.body.started));
// elapsed should be a positive number...
assert(elapsed > 0);
// less than 100 milliseconds
assert(elapsed < 100);
done();
});
});
});
describe('app.connectors', function() {
it('is unique per app instance', function() {
app.connectors.foo = 'bar';
var anotherApp = loopback();
expect(anotherApp.connectors.foo).to.equal(undefined);
});
it('includes Remote connector', function() {
expect(app.connectors.remote).to.equal(loopback.Remote);
});
it('includes Memory connector', function() {
expect(app.connectors.memory).to.equal(loopback.Memory);
});
});
describe('app.connector', function() {
// any connector will do
it('adds the connector to the registry', function() {
app.connector('foo-bar', loopback.Memory);
expect(app.connectors['foo-bar']).to.equal(loopback.Memory);
});
it('adds a classified alias', function() {
app.connector('foo-bar', loopback.Memory);
expect(app.connectors.FooBar).to.equal(loopback.Memory);
});
it('adds a camelized alias', function() {
app.connector('FOO-BAR', loopback.Memory);
expect(app.connectors.FOOBAR).to.equal(loopback.Memory);
});
});
describe('app.settings', function() {
it('can be altered via `app.set(key, value)`', function() {
app.set('write-key', 'write-value');
expect(app.settings).to.have.property('write-key', 'write-value');
});
it('can be read via `app.get(key)`', function() {
app.settings['read-key'] = 'read-value';
expect(app.get('read-key')).to.equal('read-value');
});
it('is unique per app instance', function() {
var app1 = loopback();
var app2 = loopback();
expect(app1.settings).to.not.equal(app2.settings);
app1.set('key', 'value');
expect(app2.get('key'), 'app2 value').to.equal(undefined);
});
});
2014-06-14 07:40:57 +00:00
it('exposes loopback as a property', function() {
var app = loopback();
expect(app.loopback).to.equal(loopback);
});
2013-10-29 21:12:23 +00:00
});