Merge pull request #2282 from strongloop/feature/remove-auto-attach-2.x
Clean up unit-tests - use local registry [2.x]
This commit is contained in:
commit
c2ad201bf6
|
@ -147,12 +147,10 @@ module.exports = function(Role) {
|
|||
});
|
||||
|
||||
function isUserClass(modelClass) {
|
||||
if (modelClass) {
|
||||
return modelClass === loopback.User ||
|
||||
modelClass.prototype instanceof loopback.User;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (!modelClass) return false;
|
||||
var User = modelClass.modelBuilder.models.User;
|
||||
if (!User) return false;
|
||||
return modelClass == User || modelClass.prototype instanceof User;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
@ -103,5 +103,10 @@
|
|||
"depd": "loopback-datasource-juggler/lib/browser.depd.js",
|
||||
"bcrypt": false
|
||||
},
|
||||
"config": {
|
||||
"ci": {
|
||||
"debug": "*,-mocha:*,-eslint:*"
|
||||
}
|
||||
},
|
||||
"license": "MIT"
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
var path = require('path');
|
||||
|
||||
describe('loopback.rest', function() {
|
||||
var MyModel;
|
||||
var app, MyModel;
|
||||
|
||||
beforeEach(function() {
|
||||
var ds = app.dataSource('db', { connector: loopback.Memory });
|
||||
MyModel = ds.createModel('MyModel', {name: String});
|
||||
loopback.autoAttach();
|
||||
// override the global app object provided by test/support.js
|
||||
// and create a local one that does not share state with other tests
|
||||
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) {
|
||||
|
@ -101,7 +105,7 @@ describe('loopback.rest', function() {
|
|||
});
|
||||
|
||||
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
|
||||
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) {
|
||||
var ds = app.dataSource('db', { connector: loopback.Memory });
|
||||
var CustomModel = ds.createModel('CustomModel',
|
||||
var CustomModel = app.registry.createModel('CustomModel',
|
||||
{ name: String },
|
||||
{ http: { 'path': 'domain1/CustomModelPath' }
|
||||
});
|
||||
|
||||
app.model(CustomModel);
|
||||
app.model(CustomModel, { dataSource: 'db' });
|
||||
app.use(loopback.rest());
|
||||
|
||||
request(app).get('/domain1/CustomModelPath').expect(200).end(done);
|
||||
});
|
||||
|
||||
it('should report 200 for url-encoded HTTP path', function(done) {
|
||||
var ds = app.dataSource('db', { connector: loopback.Memory });
|
||||
var CustomModel = ds.createModel('CustomModel',
|
||||
var CustomModel = app.registry.createModel('CustomModel',
|
||||
{ name: String },
|
||||
{ http: { path: 'domain%20one/CustomModelPath' }
|
||||
});
|
||||
|
||||
app.model(CustomModel);
|
||||
app.model(CustomModel, { dataSource: 'db' });
|
||||
app.use(loopback.rest());
|
||||
|
||||
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) {
|
||||
givenUserModelWithAuth();
|
||||
app.enableAuth();
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
app.use(loopback.rest());
|
||||
|
||||
givenLoggedInUser(function(err, token) {
|
||||
if (err) return done(err);
|
||||
expect(token).instanceOf(app.models.accessToken);
|
||||
expect(token).instanceOf(app.models.AccessToken);
|
||||
request(app).get('/users/' + token.userId)
|
||||
.set('Authorization', token.id)
|
||||
.expect(200)
|
||||
|
@ -268,25 +270,25 @@ describe('loopback.rest', function() {
|
|||
|
||||
it('should enable context using loopback.context', function(done) {
|
||||
app.use(loopback.context({ enableHttpContext: true }));
|
||||
app.enableAuth();
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
app.use(loopback.rest());
|
||||
|
||||
invokeGetToken(done);
|
||||
});
|
||||
|
||||
it('should enable context with loopback.rest', function(done) {
|
||||
app.enableAuth();
|
||||
app.set('remoting', { context: { enableHttpContext: true } });
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
app.set('remoting', { context: { enableHttpContext: true }});
|
||||
app.use(loopback.rest());
|
||||
|
||||
invokeGetToken(done);
|
||||
});
|
||||
|
||||
it('should support explicit context', function(done) {
|
||||
app.enableAuth();
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
app.use(loopback.context());
|
||||
app.use(loopback.token(
|
||||
{ model: loopback.getModelByType(loopback.AccessToken) }));
|
||||
{ model: app.registry.getModelByType('AccessToken') }));
|
||||
app.use(function(req, res, next) {
|
||||
loopback.getCurrentContext().set('accessToken', req.accessToken);
|
||||
next();
|
||||
|
@ -321,32 +323,26 @@ describe('loopback.rest', function() {
|
|||
});
|
||||
|
||||
function givenUserModelWithAuth() {
|
||||
// NOTE(bajtos) It is important to create a custom AccessToken model here,
|
||||
// in order to overwrite the entry created by previous tests in
|
||||
// the global model registry
|
||||
app.model('accessToken', {
|
||||
options: {
|
||||
base: 'AccessToken'
|
||||
},
|
||||
dataSource: 'db'
|
||||
});
|
||||
return app.model('user', {
|
||||
options: {
|
||||
base: 'User',
|
||||
relations: {
|
||||
accessTokens: {
|
||||
model: 'accessToken',
|
||||
type: 'hasMany',
|
||||
foreignKey: 'userId'
|
||||
}
|
||||
}
|
||||
},
|
||||
dataSource: 'db'
|
||||
});
|
||||
var AccessToken = app.registry.getModel('AccessToken');
|
||||
app.model(AccessToken, { dataSource: 'db' });
|
||||
var User = app.registry.getModel('User');
|
||||
app.model(User, { dataSource: 'db' });
|
||||
|
||||
// NOTE(bajtos) This is puzzling to me. The built-in User & AccessToken
|
||||
// models should come with both relations already set up, i.e. the
|
||||
// following two lines should not be neccessary.
|
||||
// And it does behave that way when only tests in this file are run.
|
||||
// However, when I run the full test suite (all files), the relations
|
||||
// get broken.
|
||||
AccessToken.belongsTo(User, { as: 'user', foreignKey: 'userId' });
|
||||
User.hasMany(AccessToken, { as: 'accessTokens', foreignKey: 'userId' });
|
||||
|
||||
return User;
|
||||
}
|
||||
|
||||
function givenLoggedInUser(cb, done) {
|
||||
var credentials = { email: 'user@example.com', password: 'pwd' };
|
||||
var User = app.models.user;
|
||||
var User = app.models.User;
|
||||
User.create(credentials,
|
||||
function(err, user) {
|
||||
if (err) return done(err);
|
||||
|
|
|
@ -407,4 +407,27 @@ describe('role model', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('isOwner', function() {
|
||||
it('supports app-local model registry', function(done) {
|
||||
var app = loopback({ localRegistry: true, loadBuiltinModels: true });
|
||||
app.dataSource('db', { connector: 'memory' });
|
||||
// attach all auth-related models to 'db' datasource
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
|
||||
var Role = app.models.Role;
|
||||
var User = app.models.User;
|
||||
|
||||
var u = app.registry.findModel('User');
|
||||
var credentials = { email: 'test@example.com', password: 'pass' };
|
||||
User.create(credentials, function(err, user) {
|
||||
if (err) return done(err);
|
||||
|
||||
Role.isOwner(User, user.id, user.id, function(err, result) {
|
||||
if (err) return done(err);
|
||||
expect(result, 'isOwner result').to.equal(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
require('./support');
|
||||
var loopback = require('../');
|
||||
var User;
|
||||
var AccessToken;
|
||||
var MailConnector = require('../lib/connectors/mail');
|
||||
|
||||
var userMemory = loopback.createDataSource({
|
||||
connector: 'memory'
|
||||
});
|
||||
var User, AccessToken;
|
||||
|
||||
describe('User', function() {
|
||||
var validCredentialsEmail = 'foo@bar.com';
|
||||
|
@ -19,45 +13,59 @@ describe('User', function() {
|
|||
var invalidCredentials = {email: 'foo1@bar.com', password: 'invalid'};
|
||||
var incompleteCredentials = {password: 'bar1'};
|
||||
|
||||
var defaultApp;
|
||||
// Create a local app variable to prevent clashes with the global
|
||||
// variable shared by all tests. While this should not be necessary if
|
||||
// the tests were written correctly, it turns out that's not the case :(
|
||||
var app;
|
||||
|
||||
beforeEach(function() {
|
||||
// FIXME: [rfeng] Remove loopback.User.app so that remote hooks don't go
|
||||
// to the wrong app instance
|
||||
defaultApp = loopback.User.app;
|
||||
loopback.User.app = null;
|
||||
User = loopback.User.extend('TestUser', {}, {http: {path: 'test-users'}});
|
||||
AccessToken = loopback.AccessToken.extend('TestAccessToken');
|
||||
User.email = loopback.Email.extend('email');
|
||||
loopback.autoAttach();
|
||||
beforeEach(function setupAppAndModels(done) {
|
||||
// override the global app object provided by test/support.js
|
||||
// and create a local one that does not share state with other tests
|
||||
app = loopback({ localRegistry: true, loadBuiltinModels: true });
|
||||
app.dataSource('db', { connector: 'memory' });
|
||||
|
||||
// setup Email model, it's needed by User tests
|
||||
app.dataSource('email', {
|
||||
connector: loopback.Mail,
|
||||
transports: [{ type: 'STUB' }],
|
||||
});
|
||||
var Email = app.registry.getModel('Email');
|
||||
app.model(Email, { dataSource: 'email' });
|
||||
|
||||
// attach User and related models
|
||||
User = app.registry.createModel('TestUser', {}, {
|
||||
base: 'User',
|
||||
http: { path: 'test-users' },
|
||||
});
|
||||
app.model(User, { dataSource: 'db' });
|
||||
|
||||
AccessToken = app.registry.getModel('AccessToken');
|
||||
app.model(AccessToken, { dataSource: 'db' });
|
||||
|
||||
User.email = Email;
|
||||
|
||||
// Update the AccessToken relation to use the subclass of User
|
||||
AccessToken.belongsTo(User, {as: 'user', foreignKey: 'userId'});
|
||||
User.hasMany(AccessToken, {as: 'accessTokens', foreignKey: 'userId'});
|
||||
|
||||
// Speed up the password hashing algorithm
|
||||
// for tests using the built-in User model
|
||||
User.settings.saltWorkFactor = 4;
|
||||
|
||||
// allow many User.afterRemote's to be called
|
||||
User.setMaxListeners(0);
|
||||
|
||||
});
|
||||
|
||||
beforeEach(function(done) {
|
||||
app.enableAuth();
|
||||
app.use(loopback.token({model: AccessToken}));
|
||||
app.enableAuth({ dataSource: 'db' });
|
||||
app.use(loopback.token({ model: AccessToken }));
|
||||
app.use(loopback.rest());
|
||||
app.model(User);
|
||||
|
||||
User.create(validCredentials, function(err, user) {
|
||||
if (err) return done(err);
|
||||
User.create(validCredentialsEmailVerified, done);
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
loopback.User.app = defaultApp;
|
||||
User.destroyAll(function(err) {
|
||||
User.accessToken.destroyAll(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('User.create', function() {
|
||||
it('Create a new user', function(done) {
|
||||
User.create({email: 'f@b.com', password: 'bar'}, function(err, user) {
|
||||
|
@ -694,12 +702,19 @@ describe('User', function() {
|
|||
var User;
|
||||
var AccessToken;
|
||||
|
||||
before(function() {
|
||||
User = loopback.User.extend('RealmUser', {},
|
||||
{realmRequired: true, realmDelimiter: ':'});
|
||||
AccessToken = loopback.AccessToken.extend('RealmAccessToken');
|
||||
beforeEach(function() {
|
||||
User = app.registry.createModel('RealmUser', {}, {
|
||||
base: 'TestUser',
|
||||
realmRequired: true,
|
||||
realmDelimiter: ':',
|
||||
});
|
||||
|
||||
loopback.autoAttach();
|
||||
AccessToken = app.registry.createModel('RealmAccessToken', {}, {
|
||||
base: 'AccessToken',
|
||||
});
|
||||
|
||||
app.model(AccessToken, { dataSource: 'db' });
|
||||
app.model(User, { dataSource: 'db' });
|
||||
|
||||
// Update the AccessToken relation to use the subclass of User
|
||||
AccessToken.belongsTo(User, {as: 'user', foreignKey: 'userId'});
|
||||
|
@ -770,15 +785,6 @@ describe('User', function() {
|
|||
});
|
||||
});
|
||||
|
||||
afterEach(function(done) {
|
||||
User.deleteAll({realm: 'realm1'}, function(err) {
|
||||
if (err) {
|
||||
return done(err);
|
||||
}
|
||||
User.deleteAll({realm: 'realm2'}, done);
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects a user by without realm', function(done) {
|
||||
User.login(credentialWithoutRealm, function(err, accessToken) {
|
||||
assert(err);
|
||||
|
@ -828,11 +834,11 @@ describe('User', function() {
|
|||
});
|
||||
|
||||
describe('User.login with realmRequired but no realmDelimiter', function() {
|
||||
before(function() {
|
||||
beforeEach(function() {
|
||||
User.settings.realmDelimiter = undefined;
|
||||
});
|
||||
|
||||
after(function() {
|
||||
afterEach(function() {
|
||||
User.settings.realmDelimiter = ':';
|
||||
});
|
||||
|
||||
|
@ -1534,7 +1540,7 @@ describe('User', function() {
|
|||
describe('ctor', function() {
|
||||
it('exports default Email model', function() {
|
||||
expect(User.email, 'User.email').to.be.a('function');
|
||||
expect(User.email.modelName, 'modelName').to.eql('email');
|
||||
expect(User.email.modelName, 'modelName').to.eql('Email');
|
||||
});
|
||||
|
||||
it('exports default AccessToken model', function() {
|
||||
|
|
Loading…
Reference in New Issue