Skip to content

Commit

Permalink
Controller tests
Browse files Browse the repository at this point in the history
  • Loading branch information
juanhapes committed Jul 2, 2019
1 parent 50a72c4 commit 59c0270
Show file tree
Hide file tree
Showing 4 changed files with 238 additions and 41 deletions.
3 changes: 2 additions & 1 deletion lib/controller/controller-error.js
Expand Up @@ -5,7 +5,8 @@ class ControllerError extends Error {
static get codes() {

return {
INVALID_CONTROLLER: 1
INVALID_CONTROLLER: 1,
WRONG_CALLBACK: 2
};
}

Expand Down
13 changes: 8 additions & 5 deletions lib/controller/index.js
Expand Up @@ -135,12 +135,12 @@ class Controller {
*/
async getPaged(data = {}, callback) {

if(!callback || typeof callback !== 'function')
throw new ControllerError('Callback should be a function', ControllerError.codes.WRONG_CALLBACK);

// se copia para que no se alteren las paginas y limites originales
const params = { ...data };

if(!callback || typeof callback !== 'function')
throw new Error('Callback should be a function');

if(!params.page)
params.page = 1;

Expand All @@ -154,9 +154,12 @@ class Controller {

await callback.call(null, items, params.page, params.limit);

params.page++;
const newParams = { ...params };

newParams.page++;

this.getPaged(params, callback);
if(items.length === newParams.limit)
this.getPaged(newParams, callback);
}

async getTotals() {
Expand Down
8 changes: 4 additions & 4 deletions lib/utils/index.js
Expand Up @@ -14,11 +14,11 @@ class Utils {
moduleContent = require(modulePath);
/* eslint-enable */

} catch(e) {
} catch(err) {

if(e instanceof ReferenceError || e instanceof TypeError || e instanceof SyntaxError || e instanceof RangeError
|| e.code !== 'MODULE_NOT_FOUND' || !(~e.message.indexOf(modulePath)))
logger.error('Module', e);
if(err instanceof ReferenceError || err instanceof TypeError || err instanceof SyntaxError || err instanceof RangeError
|| err.code !== 'MODULE_NOT_FOUND' || !(~err.message.indexOf(modulePath)))
logger.error('Module', err);

moduleContent = false;
}
Expand Down
255 changes: 224 additions & 31 deletions tests/controller-get-test.js
Expand Up @@ -4,6 +4,9 @@ const assert = require('assert');
const sandbox = require('sinon').createSandbox();

const { Controller, Model } = require('..'); // al index
const ControllerError = require('../lib/controller/controller-error');

const Utils = require('../lib/utils');

/* eslint-disable prefer-arrow-callback */

Expand All @@ -12,75 +15,265 @@ describe('Controller', function() {
const FooController = class Foo extends Controller {};
const fooController = new FooController();

fooController.formatGet = () => {};
fooController.afterGet = () => {};

const FooModel = class Foo extends Model {};
const fooModel = new FooModel();

let stubModelGet;

let getPagedCallback;

let stubFormatGet;

let stubAfterGet;

let spyChangeKeys;

beforeEach(() => {
stubModelGet = sandbox.stub(FooModel.prototype, 'get');

sandbox.stub(fooController, 'getModel')
.returns(fooModel);

stubFormatGet = sandbox.stub(fooController, 'formatGet')
.callsFake(({ ...item }) => item);

stubAfterGet = sandbox.stub(fooController, 'afterGet')
.callsFake(([...newItems]) => newItems);

getPagedCallback = sandbox.stub();

spyChangeKeys = sandbox.spy(Utils, 'changeKeys');
});

afterEach(() => {
sandbox.restore();
});

it('should return null when model returns undefined', async function() {
context('when call \'get\' method', function() {

it('should return null if model returns undefined', async function() {

stubModelGet.returns();
stubModelGet.returns();

const result = await fooController.get({
fooParam: 1
const result = await fooController.get({
fooParam: 1
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { fooParam: 1 });

assert.deepEqual(result, null);
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { fooParam: 1 });
it('shouldn\'t prepare results if model return an empty array', async function() {

assert.deepEqual(result, null);
});
stubModelGet.returns([]);

it('should prepare results when model get passing the params', async function() {
const result = await fooController.get();

stubModelGet.returns([{ fooItem: 2 }]);
sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, {});

const result = await fooController.get({
fooParam: 1
assert.deepEqual(result, []);
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { fooParam: 1 });
it('should prepare results if model get passing the params', async function() {

assert.deepEqual(result, [{ fooItem: 2 }]);
});
stubModelGet.returns([{ fooItem: 2 }]);

const result = await fooController.get({
fooParam: 1
});

it('should call controller formatGet with each item', async function() {
sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { fooParam: 1 });

fooController.formatGet = () => {};
const stubFormatGet = sandbox.stub(fooController, 'formatGet')
.callsFake(({ ...item }) => {
assert.deepEqual(result, [{ fooItem: 2 }]);
});

it('should admit object result from model', async function() {

stubModelGet.returns({ foo: 456 });

const result = await fooController.get({
fooParam: 1
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { fooParam: 1 });

assert.deepEqual(result, { foo: 456 });
});

context('when param \'changeKeys\' received', function() {

it('should change keys if key found in items', async function() {

stubModelGet.returns([{ id: 1, foo: 'bar' }, { id: 2, bar: 'foo' }]);

const result = await fooController.get({
changeKeys: 'id'
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { changeKeys: 'id' });

sandbox.assert.calledOnce(spyChangeKeys);
sandbox.assert.calledWithExactly(spyChangeKeys, [{ id: 1, foo: 'bar' }, { id: 2, bar: 'foo' }], 'id');

assert.deepEqual(result, {
1: { id: 1, foo: 'bar' },
2: { id: 2, bar: 'foo' }
});
});

it('should ignore items that hasn\'t the key', async function() {

stubModelGet.returns([{ foo: 'bar' }, { bar: 'foo' }]);

const result = await fooController.get({
changeKeys: 'id'
});

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { changeKeys: 'id' });

sandbox.assert.calledOnce(spyChangeKeys);
sandbox.assert.calledWithExactly(spyChangeKeys, [{ foo: 'bar' }, { bar: 'foo' }], 'id');

assert.deepEqual(result, {});
});
});

it('should call controller \'formatGet\' with each item if \'formatGet\' method exists', async function() {

stubFormatGet.callsFake(({ ...item }) => {
item.added = 123;
return item;
});

stubModelGet.returns([{ fooItem: 2 }, { anotherFooItem: 3 }]);
stubModelGet.returns([{ fooItem: 2 }, { anotherFooItem: 3 }]);

const result = await fooController.get();

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, {});

sandbox.assert.calledTwice(stubFormatGet);
sandbox.assert.calledWithExactly(stubFormatGet.getCall(0), { fooItem: 2 });
sandbox.assert.calledWithExactly(stubFormatGet.getCall(1), { anotherFooItem: 3 });

assert.deepEqual(result, [
{ fooItem: 2, added: 123 },
{ anotherFooItem: 3, added: 123 }
]);
});

context('when \'afterGet\' method exists', function() {

it('should call controller \'afterGet\' with all items', async function() {

stubModelGet.returns([{ foo: 1 }, { bar: 2 }]);

const result = await fooController.get();

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, {});

sandbox.assert.calledOnce(stubAfterGet);
sandbox.assert.calledWithExactly(stubAfterGet, [{ foo: 1 }, { bar: 2 }], {}, {}, []);

assert.deepEqual(result, [{ foo: 1 }, { bar: 2 }]);
});

it('should call controller \'afterGet\' with all items, params, indexes and ids', async function() {

stubModelGet.returns([{ id: 33, foo: 45 }, { id: 78, bar: 987 }]);

const result = await fooController.get({ extraParam: true });

const result = await fooController.get();
sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, { extraParam: true });

sandbox.assert.calledOnce(stubModelGet);
sandbox.assert.calledWithExactly(stubModelGet, {});
sandbox.assert.calledOnce(stubAfterGet);
sandbox.assert.calledWithExactly(stubAfterGet, [{ id: 33, foo: 45 }, { id: 78, bar: 987 }], { extraParam: true }, { 33: 0, 78: 1 }, [33, 78]);

sandbox.assert.calledTwice(stubFormatGet);
sandbox.assert.calledWithExactly(stubFormatGet.getCall(0), { fooItem: 2 });
sandbox.assert.calledWithExactly(stubFormatGet.getCall(1), { anotherFooItem: 3 });
assert.deepEqual(result, [{ id: 33, foo: 45 }, { id: 78, bar: 987 }]);
});
});

assert.deepEqual(result, [
{ fooItem: 2, added: 123 },
{ anotherFooItem: 3, added: 123 }
]);
});

context('when call \'getPaged\' method', function() {

it('should reject if received an invalid callback', async function() {

const wrongCallbackError = {
name: 'ControllerError',
code: ControllerError.codes.WRONG_CALLBACK
};

const badCallbacks = [
1, 'foo', true, { foo: 'bar' }, ['foo', 'bar'], null, undefined
];

const promises = badCallbacks.map(badCallback => {
return assert.rejects(() => fooController.getPaged({}, badCallback), wrongCallbackError);
});

promises.push(assert.rejects(() => fooController.getPaged(), wrongCallbackError));

await Promise.all(promises);
});

it('shouldn\'t call the callback if get response empty results', async function() {

const stubGet = sandbox.stub(fooController, 'get')
.returns([]);

await fooController.getPaged({}, getPagedCallback);

sandbox.assert.calledOnce(stubGet);
sandbox.assert.calledWithExactly(stubGet, {
page: 1,
limit: Controller.defaultPageLimit
});

sandbox.assert.notCalled(getPagedCallback);
});

it('should call the callback one time if get response an array of items, passing custom limit', async function() {

const stubGet = sandbox.stub(fooController, 'get')
.onCall(0)
.returns([{ foo: 1 }, { bar: 2 }])
.onCall(1)
.returns([{ foo: 5 }])
.returns([]); // for the following calls

await fooController.getPaged({ limit: 2 }, getPagedCallback);

sandbox.assert.calledTwice(stubGet);

sandbox.assert.calledWithExactly(stubGet.getCall(0), {
page: 1,
limit: 2
});

sandbox.assert.calledWithExactly(stubGet.getCall(1), {
page: 2,
limit: 2
});

sandbox.assert.calledTwice(getPagedCallback);

sandbox.assert.calledWithExactly(getPagedCallback.getCall(0), [{ foo: 1 }, { bar: 2 }], 1, 2);

sandbox.assert.calledWithExactly(getPagedCallback.getCall(1), [{ foo: 5 }], 2, 2);
});
});

});

0 comments on commit 59c0270

Please sign in to comment.