test/rest.middleware: use local registry

Rework tests in `test/rest.middleware.test.js` to not depend
on `app.autoAttach()` and global shared registry of Models. Instead,
each tests creates a fresh app instance with a new in-memory datasource
and a new set of Models.
This commit is contained in:
Miroslav Bajtoš 2016-05-02 14:53:21 +02:00
parent cae9786f0e
commit 53cd449c9c
1 changed files with 37 additions and 41 deletions

View File

@ -1,11 +1,15 @@
var path = require('path'); var path = require('path');
describe('loopback.rest', function() { describe('loopback.rest', function() {
var MyModel; var app, MyModel;
beforeEach(function() { beforeEach(function() {
var ds = app.dataSource('db', { connector: loopback.Memory }); // override the global app object provided by test/support.js
MyModel = ds.createModel('MyModel', {name: String}); // and create a local one that does not share state with other tests
loopback.autoAttach(); app = loopback({ localRegistry: true, loadBuiltinModels: true });
var db = app.dataSource('db', { connector: 'memory' });
MyModel = app.registry.createModel('MyModel');
MyModel.attachTo(db);
}); });
it('works out-of-the-box', function(done) { it('works out-of-the-box', function(done) {
@ -101,7 +105,7 @@ describe('loopback.rest', function() {
}); });
it('should honour `remoting.rest.supportedTypes`', function(done) { it('should honour `remoting.rest.supportedTypes`', function(done) {
var app = loopback(); var app = loopback({ localRegistry: true });
// NOTE it is crucial to set `remoting` before creating any models // NOTE it is crucial to set `remoting` before creating any models
var supportedTypes = ['json', 'application/javascript', 'text/javascript']; var supportedTypes = ['json', 'application/javascript', 'text/javascript'];
@ -117,26 +121,24 @@ describe('loopback.rest', function() {
}); });
it('allows models to provide a custom HTTP path', function(done) { it('allows models to provide a custom HTTP path', function(done) {
var ds = app.dataSource('db', { connector: loopback.Memory }); var CustomModel = app.registry.createModel('CustomModel',
var CustomModel = ds.createModel('CustomModel',
{ name: String }, { name: String },
{ http: { 'path': 'domain1/CustomModelPath' } { http: { 'path': 'domain1/CustomModelPath' }
}); });
app.model(CustomModel); app.model(CustomModel, { dataSource: 'db' });
app.use(loopback.rest()); app.use(loopback.rest());
request(app).get('/domain1/CustomModelPath').expect(200).end(done); request(app).get('/domain1/CustomModelPath').expect(200).end(done);
}); });
it('should report 200 for url-encoded HTTP path', function(done) { it('should report 200 for url-encoded HTTP path', function(done) {
var ds = app.dataSource('db', { connector: loopback.Memory }); var CustomModel = app.registry.createModel('CustomModel',
var CustomModel = ds.createModel('CustomModel',
{ name: String }, { name: String },
{ http: { path: 'domain%20one/CustomModelPath' } { http: { path: 'domain%20one/CustomModelPath' }
}); });
app.model(CustomModel); app.model(CustomModel, { dataSource: 'db' });
app.use(loopback.rest()); app.use(loopback.rest());
request(app).get('/domain%20one/CustomModelPath').expect(200).end(done); request(app).get('/domain%20one/CustomModelPath').expect(200).end(done);
@ -144,12 +146,12 @@ describe('loopback.rest', function() {
it('includes loopback.token when necessary', function(done) { it('includes loopback.token when necessary', function(done) {
givenUserModelWithAuth(); givenUserModelWithAuth();
app.enableAuth(); app.enableAuth({ dataSource: 'db' });
app.use(loopback.rest()); app.use(loopback.rest());
givenLoggedInUser(function(err, token) { givenLoggedInUser(function(err, token) {
if (err) return done(err); if (err) return done(err);
expect(token).instanceOf(app.models.accessToken); expect(token).instanceOf(app.models.AccessToken);
request(app).get('/users/' + token.userId) request(app).get('/users/' + token.userId)
.set('Authorization', token.id) .set('Authorization', token.id)
.expect(200) .expect(200)
@ -268,14 +270,14 @@ describe('loopback.rest', function() {
it('should enable context using loopback.context', function(done) { it('should enable context using loopback.context', function(done) {
app.use(loopback.context({ enableHttpContext: true })); app.use(loopback.context({ enableHttpContext: true }));
app.enableAuth(); app.enableAuth({ dataSource: 'db' });
app.use(loopback.rest()); app.use(loopback.rest());
invokeGetToken(done); invokeGetToken(done);
}); });
it('should enable context with loopback.rest', function(done) { it('should enable context with loopback.rest', function(done) {
app.enableAuth(); app.enableAuth({ dataSource: 'db' });
app.set('remoting', { context: { enableHttpContext: true }}); app.set('remoting', { context: { enableHttpContext: true }});
app.use(loopback.rest()); app.use(loopback.rest());
@ -283,10 +285,10 @@ describe('loopback.rest', function() {
}); });
it('should support explicit context', function(done) { it('should support explicit context', function(done) {
app.enableAuth(); app.enableAuth({ dataSource: 'db' });
app.use(loopback.context()); app.use(loopback.context());
app.use(loopback.token( app.use(loopback.token(
{ model: loopback.getModelByType(loopback.AccessToken) })); { model: app.registry.getModelByType('AccessToken') }));
app.use(function(req, res, next) { app.use(function(req, res, next) {
loopback.getCurrentContext().set('accessToken', req.accessToken); loopback.getCurrentContext().set('accessToken', req.accessToken);
next(); next();
@ -321,32 +323,26 @@ describe('loopback.rest', function() {
}); });
function givenUserModelWithAuth() { function givenUserModelWithAuth() {
// NOTE(bajtos) It is important to create a custom AccessToken model here, var AccessToken = app.registry.getModel('AccessToken');
// in order to overwrite the entry created by previous tests in app.model(AccessToken, { dataSource: 'db' });
// the global model registry var User = app.registry.getModel('User');
app.model('accessToken', { app.model(User, { dataSource: 'db' });
options: {
base: 'AccessToken' // NOTE(bajtos) This is puzzling to me. The built-in User & AccessToken
}, // models should come with both relations already set up, i.e. the
dataSource: 'db' // following two lines should not be neccessary.
}); // And it does behave that way when only tests in this file are run.
return app.model('user', { // However, when I run the full test suite (all files), the relations
options: { // get broken.
base: 'User', AccessToken.belongsTo(User, { as: 'user', foreignKey: 'userId' });
relations: { User.hasMany(AccessToken, { as: 'accessTokens', foreignKey: 'userId' });
accessTokens: {
model: 'accessToken', return User;
type: 'hasMany',
foreignKey: 'userId'
}
}
},
dataSource: 'db'
});
} }
function givenLoggedInUser(cb, done) { function givenLoggedInUser(cb, done) {
var credentials = { email: 'user@example.com', password: 'pwd' }; var credentials = { email: 'user@example.com', password: 'pwd' };
var User = app.models.user; var User = app.models.User;
User.create(credentials, User.create(credentials,
function(err, user) { function(err, user) {
if (err) return done(err); if (err) return done(err);