2014-02-19 23:14:31 +00:00
|
|
|
var loopback = require('../');
|
|
|
|
var lt = require('loopback-testing');
|
|
|
|
var path = require('path');
|
|
|
|
var SIMPLE_APP = path.join(__dirname, 'fixtures', 'simple-integration-app');
|
2015-04-20 16:23:44 +00:00
|
|
|
var app = require(path.join(SIMPLE_APP, 'server/server.js'));
|
2014-02-19 23:14:31 +00:00
|
|
|
var assert = require('assert');
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
describe('remoting - integration', function() {
|
2016-01-01 00:52:31 +00:00
|
|
|
before(function(done) {
|
|
|
|
if (app.booting) {
|
|
|
|
return app.once('booted', done);
|
|
|
|
}
|
|
|
|
done();
|
|
|
|
});
|
2014-02-19 23:14:31 +00:00
|
|
|
|
|
|
|
lt.beforeEach.withApp(app);
|
|
|
|
lt.beforeEach.givenModel('store');
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
afterEach(function(done) {
|
2014-02-19 23:14:31 +00:00
|
|
|
this.app.models.store.destroyAll(done);
|
|
|
|
});
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
describe('app.remotes.options', function() {
|
|
|
|
it('should load remoting options', function() {
|
2014-02-19 23:14:31 +00:00
|
|
|
var remotes = app.remotes();
|
2014-11-21 01:46:21 +00:00
|
|
|
assert.deepEqual(remotes.options, {'json': {'limit': '1kb', 'strict': false},
|
|
|
|
'urlencoded': {'limit': '8kb', 'extended': true}});
|
2014-02-19 23:14:31 +00:00
|
|
|
});
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
it('rest handler', function() {
|
2014-02-19 23:14:31 +00:00
|
|
|
var handler = app.handler('rest');
|
|
|
|
assert(handler);
|
|
|
|
});
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
it('should accept request that has entity below 1kb', function(done) {
|
2014-02-19 23:14:31 +00:00
|
|
|
// Build an object that is smaller than 1kb
|
2014-11-21 01:46:21 +00:00
|
|
|
var name = '';
|
2014-02-19 23:14:31 +00:00
|
|
|
for (var i = 0; i < 256; i++) {
|
2014-11-21 01:46:21 +00:00
|
|
|
name += '11';
|
2014-02-19 23:14:31 +00:00
|
|
|
}
|
|
|
|
this.http = this.post('/api/stores');
|
|
|
|
this.http.send({
|
2014-11-21 01:46:21 +00:00
|
|
|
'name': name
|
2014-02-19 23:14:31 +00:00
|
|
|
});
|
2014-11-21 02:35:36 +00:00
|
|
|
this.http.end(function(err) {
|
2014-02-19 23:14:31 +00:00
|
|
|
if (err) return done(err);
|
|
|
|
this.req = this.http.req;
|
|
|
|
this.res = this.http.res;
|
|
|
|
assert.equal(this.res.statusCode, 200);
|
|
|
|
done();
|
|
|
|
}.bind(this));
|
|
|
|
});
|
|
|
|
|
2014-11-21 02:35:36 +00:00
|
|
|
it('should reject request that has entity beyond 1kb', function(done) {
|
2014-02-19 23:14:31 +00:00
|
|
|
// Build an object that is larger than 1kb
|
2014-11-21 01:46:21 +00:00
|
|
|
var name = '';
|
2014-02-19 23:14:31 +00:00
|
|
|
for (var i = 0; i < 2048; i++) {
|
2014-11-21 01:46:21 +00:00
|
|
|
name += '11111111111';
|
2014-02-19 23:14:31 +00:00
|
|
|
}
|
|
|
|
this.http = this.post('/api/stores');
|
|
|
|
this.http.send({
|
2014-11-21 01:46:21 +00:00
|
|
|
'name': name
|
2014-02-19 23:14:31 +00:00
|
|
|
});
|
2014-11-21 02:35:36 +00:00
|
|
|
this.http.end(function(err) {
|
2014-02-19 23:14:31 +00:00
|
|
|
if (err) return done(err);
|
|
|
|
this.req = this.http.req;
|
|
|
|
this.res = this.http.res;
|
|
|
|
// Request is rejected with 413
|
|
|
|
assert.equal(this.res.statusCode, 413);
|
|
|
|
done();
|
|
|
|
}.bind(this));
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2014-11-17 17:44:20 +00:00
|
|
|
describe('Model shared classes', function() {
|
|
|
|
function formatReturns(m) {
|
|
|
|
var returns = m.returns;
|
|
|
|
if (!returns || returns.length === 0) {
|
|
|
|
return '';
|
|
|
|
}
|
|
|
|
var type = returns[0].type;
|
|
|
|
return type ? ':' + type : '';
|
|
|
|
}
|
|
|
|
|
|
|
|
function formatMethod(m) {
|
|
|
|
return [
|
|
|
|
m.name,
|
|
|
|
'(',
|
|
|
|
m.accepts.map(function(a) {
|
2014-11-21 01:46:21 +00:00
|
|
|
return a.arg + ':' + a.type;
|
2014-11-17 17:44:20 +00:00
|
|
|
}).join(','),
|
|
|
|
')',
|
|
|
|
formatReturns(m),
|
|
|
|
' ',
|
|
|
|
m.getHttpMethod(),
|
|
|
|
' ',
|
|
|
|
m.getFullPath()
|
|
|
|
].join('');
|
|
|
|
}
|
|
|
|
|
|
|
|
function findClass(name) {
|
|
|
|
return app.handler('rest').adapter
|
2014-07-03 06:19:41 +00:00
|
|
|
.getClasses()
|
2014-11-17 17:44:20 +00:00
|
|
|
.filter(function(c) {
|
|
|
|
return c.name === name;
|
|
|
|
})[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
it('has expected remote methods', function() {
|
|
|
|
var storeClass = findClass('store');
|
2014-07-03 06:19:41 +00:00
|
|
|
var methods = storeClass.methods
|
2014-11-17 17:44:20 +00:00
|
|
|
.filter(function(m) {
|
|
|
|
return m.name.indexOf('__') === -1;
|
|
|
|
})
|
2014-07-03 06:19:41 +00:00
|
|
|
.map(function(m) {
|
2014-11-17 17:44:20 +00:00
|
|
|
return formatMethod(m);
|
2014-07-03 06:19:41 +00:00
|
|
|
});
|
|
|
|
|
2014-11-17 17:44:20 +00:00
|
|
|
var expectedMethods = [
|
|
|
|
'create(data:object):store POST /stores',
|
|
|
|
'upsert(data:object):store PUT /stores',
|
|
|
|
'exists(id:any):boolean GET /stores/:id/exists',
|
2015-04-16 22:02:41 +00:00
|
|
|
'findById(id:any,filter:object):store GET /stores/:id',
|
2014-11-17 17:44:20 +00:00
|
|
|
'find(filter:object):store GET /stores',
|
|
|
|
'findOne(filter:object):store GET /stores/findOne',
|
2015-09-19 02:13:30 +00:00
|
|
|
'updateAll(where:object,data:object):object POST /stores/update',
|
|
|
|
'deleteById(id:any):object DELETE /stores/:id',
|
2014-11-17 17:44:20 +00:00
|
|
|
'count(where:object):number GET /stores/count',
|
2015-09-19 02:13:30 +00:00
|
|
|
'prototype.updateAttributes(data:object):store PUT /stores/:id',
|
|
|
|
'createChangeStream(options:object):ReadableStream POST /stores/change-stream'
|
2014-11-17 17:44:20 +00:00
|
|
|
];
|
|
|
|
|
2014-07-03 06:19:41 +00:00
|
|
|
// The list of methods is from docs:
|
2015-09-19 02:13:30 +00:00
|
|
|
// https://docs.strongloop.com/display/public/LB/Exposing+models+over+REST
|
2014-11-17 17:44:20 +00:00
|
|
|
expect(methods).to.include.members(expectedMethods);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('has expected remote methods for scopes', function() {
|
|
|
|
var storeClass = findClass('store');
|
|
|
|
var methods = storeClass.methods
|
|
|
|
.filter(function(m) {
|
|
|
|
return m.name.indexOf('__') === 0;
|
|
|
|
})
|
|
|
|
.map(function(m) {
|
|
|
|
return formatMethod(m);
|
|
|
|
});
|
|
|
|
|
|
|
|
var expectedMethods = [
|
|
|
|
'__get__superStores(filter:object):store GET /stores/superStores',
|
|
|
|
'__create__superStores(data:store):store POST /stores/superStores',
|
|
|
|
'__delete__superStores() DELETE /stores/superStores',
|
|
|
|
'__count__superStores(where:object):number GET /stores/superStores/count'
|
|
|
|
];
|
|
|
|
|
|
|
|
expect(methods).to.include.members(expectedMethods);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should have correct signatures for belongsTo methods',
|
|
|
|
function() {
|
|
|
|
|
|
|
|
var widgetClass = findClass('widget');
|
|
|
|
var methods = widgetClass.methods
|
|
|
|
.filter(function(m) {
|
|
|
|
return m.name.indexOf('prototype.__') === 0;
|
|
|
|
})
|
|
|
|
.map(function(m) {
|
|
|
|
return formatMethod(m);
|
|
|
|
});
|
|
|
|
|
|
|
|
var expectedMethods = [
|
|
|
|
'prototype.__get__store(refresh:boolean):store ' +
|
|
|
|
'GET /widgets/:id/store'
|
|
|
|
];
|
|
|
|
expect(methods).to.include.members(expectedMethods);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should have correct signatures for hasMany methods',
|
|
|
|
function() {
|
|
|
|
|
|
|
|
var physicianClass = findClass('store');
|
|
|
|
var methods = physicianClass.methods
|
|
|
|
.filter(function(m) {
|
|
|
|
return m.name.indexOf('prototype.__') === 0;
|
|
|
|
})
|
|
|
|
.map(function(m) {
|
|
|
|
return formatMethod(m);
|
|
|
|
});
|
|
|
|
|
|
|
|
var expectedMethods = [
|
|
|
|
'prototype.__findById__widgets(fk:any):widget ' +
|
|
|
|
'GET /stores/:id/widgets/:fk',
|
|
|
|
'prototype.__destroyById__widgets(fk:any) ' +
|
|
|
|
'DELETE /stores/:id/widgets/:fk',
|
|
|
|
'prototype.__updateById__widgets(fk:any,data:widget):widget ' +
|
|
|
|
'PUT /stores/:id/widgets/:fk',
|
|
|
|
'prototype.__get__widgets(filter:object):widget ' +
|
|
|
|
'GET /stores/:id/widgets',
|
|
|
|
'prototype.__create__widgets(data:widget):widget ' +
|
|
|
|
'POST /stores/:id/widgets',
|
|
|
|
'prototype.__delete__widgets() ' +
|
|
|
|
'DELETE /stores/:id/widgets',
|
|
|
|
'prototype.__count__widgets(where:object):number ' +
|
|
|
|
'GET /stores/:id/widgets/count'
|
|
|
|
];
|
|
|
|
expect(methods).to.include.members(expectedMethods);
|
|
|
|
});
|
|
|
|
|
|
|
|
it('should have correct signatures for hasMany-through methods',
|
2015-02-20 14:31:15 +00:00
|
|
|
function() { // jscs:disable validateIndentation
|
2014-11-17 17:44:20 +00:00
|
|
|
|
|
|
|
var physicianClass = findClass('physician');
|
|
|
|
var methods = physicianClass.methods
|
|
|
|
.filter(function(m) {
|
|
|
|
return m.name.indexOf('prototype.__') === 0;
|
|
|
|
})
|
|
|
|
.map(function(m) {
|
|
|
|
return formatMethod(m);
|
|
|
|
});
|
|
|
|
|
|
|
|
var expectedMethods = [
|
|
|
|
'prototype.__findById__patients(fk:any):patient ' +
|
|
|
|
'GET /physicians/:id/patients/:fk',
|
|
|
|
'prototype.__destroyById__patients(fk:any) ' +
|
|
|
|
'DELETE /physicians/:id/patients/:fk',
|
|
|
|
'prototype.__updateById__patients(fk:any,data:patient):patient ' +
|
|
|
|
'PUT /physicians/:id/patients/:fk',
|
|
|
|
'prototype.__link__patients(fk:any,data:appointment):appointment ' +
|
|
|
|
'PUT /physicians/:id/patients/rel/:fk',
|
|
|
|
'prototype.__unlink__patients(fk:any) ' +
|
|
|
|
'DELETE /physicians/:id/patients/rel/:fk',
|
|
|
|
'prototype.__exists__patients(fk:any):boolean ' +
|
|
|
|
'HEAD /physicians/:id/patients/rel/:fk',
|
|
|
|
'prototype.__get__patients(filter:object):patient ' +
|
|
|
|
'GET /physicians/:id/patients',
|
|
|
|
'prototype.__create__patients(data:patient):patient ' +
|
|
|
|
'POST /physicians/:id/patients',
|
|
|
|
'prototype.__delete__patients() ' +
|
|
|
|
'DELETE /physicians/:id/patients',
|
|
|
|
'prototype.__count__patients(where:object):number ' +
|
|
|
|
'GET /physicians/:id/patients/count'
|
|
|
|
];
|
|
|
|
expect(methods).to.include.members(expectedMethods);
|
2014-07-03 06:19:41 +00:00
|
|
|
});
|
|
|
|
});
|
2014-11-17 17:44:20 +00:00
|
|
|
|
2014-03-21 19:18:00 +00:00
|
|
|
});
|