diff --git a/modules/route/back/methods/roadmap/specs/clone.spec.js b/modules/route/back/methods/roadmap/specs/clone.spec.js
new file mode 100644
index 000000000..41e696157
--- /dev/null
+++ b/modules/route/back/methods/roadmap/specs/clone.spec.js
@@ -0,0 +1,109 @@
+const app = require('vn-loopback/server/server');
+const models = require('vn-loopback/server/server').models;
+
+describe('AgencyTerm filter()', () => {
+ const authUserId = 9;
+ const today = Date.vnNew();
+ today.setHours(2, 0, 0, 0);
+
+ it('should return all results matching the filter', async() => {
+ const tx = await models.AgencyTerm.beginTransaction({});
+
+ try {
+ const options = {transaction: tx};
+ const filter = {};
+ const ctx = {req: {accessToken: {userId: authUserId}}};
+
+ const agencyTerms = await models.AgencyTerm.filter(ctx, filter, options);
+ const firstAgencyTerm = agencyTerms[0];
+
+ expect(firstAgencyTerm.routeFk).toEqual(1);
+ expect(agencyTerms.length).toEqual(5);
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ });
+
+ it('should return results matching "search" searching by integer', async() => {
+ let ctx = {
+ args: {
+ search: 1,
+ }
+ };
+
+ let result = await app.models.AgencyTerm.filter(ctx);
+
+ expect(result.length).toEqual(1);
+ expect(result[0].routeFk).toEqual(1);
+ });
+
+ it('should return results matching "search" searching by string', async() => {
+ let ctx = {
+ args: {
+ search: 'Plants SL',
+ }
+ };
+
+ let result = await app.models.AgencyTerm.filter(ctx);
+
+ expect(result.length).toEqual(2);
+ });
+
+ it('should return results matching "from" and "to"', async() => {
+ const tx = await models.Buy.beginTransaction({});
+ const options = {transaction: tx};
+
+ try {
+ const from = Date.vnNew();
+ from.setHours(0, 0, 0, 0);
+
+ const to = Date.vnNew();
+ to.setHours(23, 59, 59, 999);
+
+ const ctx = {
+ args: {
+ from: from,
+ to: to
+ }
+ };
+
+ const results = await models.AgencyTerm.filter(ctx, options);
+
+ expect(results.length).toBe(5);
+
+ await tx.rollback();
+ } catch (e) {
+ await tx.rollback();
+ throw e;
+ }
+ });
+
+ it('should return results matching "agencyModeFk"', async() => {
+ let ctx = {
+ args: {
+ agencyModeFk: 1,
+ }
+ };
+
+ let result = await app.models.AgencyTerm.filter(ctx);
+
+ expect(result.length).toEqual(1);
+ expect(result[0].routeFk).toEqual(1);
+ });
+
+ it('should return results matching "agencyFk"', async() => {
+ let ctx = {
+ args: {
+ agencyFk: 2,
+ }
+ };
+
+ let result = await app.models.AgencyTerm.filter(ctx);
+
+ expect(result.length).toEqual(1);
+ expect(result[0].routeFk).toEqual(2);
+ });
+});
diff --git a/modules/route/front/roadmap/card/index.spec.js b/modules/route/front/roadmap/card/index.spec.js
new file mode 100644
index 000000000..ab2314bb9
--- /dev/null
+++ b/modules/route/front/roadmap/card/index.spec.js
@@ -0,0 +1,27 @@
+import './index';
+
+describe('component vnItemTypeCard', () => {
+ let controller;
+ let $httpBackend;
+
+ beforeEach(ngModule('item'));
+
+ beforeEach(inject(($componentController, _$httpBackend_) => {
+ $httpBackend = _$httpBackend_;
+ controller = $componentController('vnItemTypeCard', {$element: null});
+ }));
+
+ describe('reload()', () => {
+ it('should reload the controller data', () => {
+ controller.$params.id = 1;
+
+ const itemType = {id: 1};
+
+ $httpBackend.expectGET('ItemTypes/1').respond(itemType);
+ controller.reload();
+ $httpBackend.flush();
+
+ expect(controller.itemType).toEqual(itemType);
+ });
+ });
+});
diff --git a/modules/route/front/roadmap/create/index.spec.js b/modules/route/front/roadmap/create/index.spec.js
new file mode 100644
index 000000000..d6d9883a7
--- /dev/null
+++ b/modules/route/front/roadmap/create/index.spec.js
@@ -0,0 +1,107 @@
+import './index';
+import watcher from 'core/mocks/watcher.js';
+
+describe('AgencyTerm', () => {
+ describe('Component vnAgencyTermCreateInvoiceIn', () => {
+ let controller;
+ let $scope;
+ let $httpBackend;
+ let $httpParamSerializer;
+
+ beforeEach(ngModule('route'));
+
+ beforeEach(inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
+ $scope = $rootScope.$new();
+ $httpBackend = _$httpBackend_;
+ $httpParamSerializer = _$httpParamSerializer_;
+ const $element = angular.element('');
+ controller = $componentController('vnAgencyTermCreateInvoiceIn', {$element});
+ controller._route = {
+ id: 1
+ };
+ }));
+
+ describe('$onChanges()', () => {
+ it('should update the params data when $params.q is defined', () => {
+ controller.$params = {q: '{"supplierName": "Plants SL","rows": null}'};
+
+ const params = {q: '{"supplierName": "Plants SL", "rows": null}'};
+ const json = JSON.parse(params.q);
+
+ controller.$onChanges();
+
+ expect(controller.params).toEqual(json);
+ });
+ });
+
+ describe('route() setter', () => {
+ it('should set the ticket data and then call setDefaultParams() and getAllowedContentTypes()', () => {
+ jest.spyOn(controller, 'setDefaultParams');
+ jest.spyOn(controller, 'getAllowedContentTypes');
+ controller.route = {
+ id: 1
+ };
+
+ expect(controller.route).toBeDefined();
+ expect(controller.setDefaultParams).toHaveBeenCalledWith();
+ expect(controller.getAllowedContentTypes).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('getAllowedContentTypes()', () => {
+ it('should make an HTTP GET request to get the allowed content types', () => {
+ const expectedResponse = ['image/png', 'image/jpg'];
+ $httpBackend.expect('GET', `DmsContainers/allowedContentTypes`).respond(expectedResponse);
+ controller.getAllowedContentTypes();
+ $httpBackend.flush();
+
+ expect(controller.allowedContentTypes).toBeDefined();
+ expect(controller.allowedContentTypes).toEqual('image/png, image/jpg');
+ });
+ });
+
+ describe('setDefaultParams()', () => {
+ it('should perform a GET query and define the dms property on controller', () => {
+ const params = {filter: {
+ where: {code: 'invoiceIn'}
+ }};
+ const serializedParams = $httpParamSerializer(params);
+ $httpBackend.expect('GET', `DmsTypes/findOne?${serializedParams}`).respond({id: 1, code: 'invoiceIn'});
+ controller.params = {supplierName: 'Plants SL'};
+ controller.setDefaultParams();
+ $httpBackend.flush();
+
+ expect(controller.dms).toBeDefined();
+ expect(controller.dms.dmsTypeId).toEqual(1);
+ });
+ });
+
+ describe('onSubmit()', () => {
+ it('should make an HTTP POST request to save the form data', () => {
+ controller.$.watcher = watcher;
+
+ jest.spyOn(controller.$.watcher, 'updateOriginalData');
+ const files = [{id: 1, name: 'MyFile'}];
+ controller.dms = {files};
+ const serializedParams = $httpParamSerializer(controller.dms);
+ const query = `dms/uploadFile?${serializedParams}`;
+ controller.params = {rows: null};
+
+ $httpBackend.expect('POST', query).respond({});
+ $httpBackend.expect('POST', 'AgencyTerms/createInvoiceIn').respond({});
+ controller.onSubmit();
+ $httpBackend.flush();
+ });
+ });
+
+ describe('onFileChange()', () => {
+ it('should set dms hasFileAttached property to true if has any files', () => {
+ const files = [{id: 1, name: 'MyFile'}];
+ controller.onFileChange(files);
+ $scope.$apply();
+
+ expect(controller.dms.hasFileAttached).toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/modules/route/front/roadmap/index/index.spec.js b/modules/route/front/roadmap/index/index.spec.js
new file mode 100644
index 000000000..55c40daa5
--- /dev/null
+++ b/modules/route/front/roadmap/index/index.spec.js
@@ -0,0 +1,94 @@
+import './index.js';
+import crudModel from 'core/mocks/crud-model';
+
+describe('AgencyTerm', () => {
+ describe('Component vnAgencyTermIndex', () => {
+ let controller;
+ let $window;
+
+ beforeEach(ngModule('route'));
+
+ beforeEach(inject(($componentController, _$window_) => {
+ $window = _$window_;
+ const $element = angular.element('');
+ controller = $componentController('vnAgencyTermIndex', {$element});
+ controller.$.model = crudModel;
+ controller.$.model.data = [
+ {supplierFk: 1, totalPrice: null},
+ {supplierFk: 1},
+ {supplierFk: 2}
+ ];
+ }));
+
+ describe('checked() getter', () => {
+ it('should return the checked lines', () => {
+ const data = controller.$.model.data;
+ data[0].checked = true;
+
+ const checkedRows = controller.checked;
+
+ const firstCheckedRow = checkedRows[0];
+
+ expect(firstCheckedRow.supplierFk).toEqual(1);
+ });
+ });
+
+ describe('totalCheked() getter', () => {
+ it('should return the total checked lines', () => {
+ const data = controller.$.model.data;
+ data[0].checked = true;
+
+ const checkedRows = controller.totalChecked;
+
+ expect(checkedRows).toEqual(1);
+ });
+ });
+
+ describe('preview()', () => {
+ it('should show the summary dialog', () => {
+ controller.$.summary = {show: () => {}};
+ jest.spyOn(controller.$.summary, 'show');
+
+ let event = new MouseEvent('click', {
+ view: $window,
+ bubbles: true,
+ cancelable: true
+ });
+ const route = {id: 1};
+
+ controller.preview(event, route);
+
+ expect(controller.$.summary.show).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('createInvoiceIn()', () => {
+ it('should throw an error if more than one autonomous are checked', () => {
+ jest.spyOn(controller.vnApp, 'showError');
+ const data = controller.$.model.data;
+ data[0].checked = true;
+ data[2].checked = true;
+
+ controller.createInvoiceIn();
+
+ expect(controller.vnApp.showError).toHaveBeenCalled();
+ });
+
+ it('should call the function go() on $state to go to the file management', () => {
+ jest.spyOn(controller.$state, 'go');
+ const data = controller.$.model.data;
+ data[0].checked = true;
+
+ controller.createInvoiceIn();
+
+ delete data[0].checked;
+ const params = JSON.stringify({
+ supplierName: data[0].supplierName,
+ rows: [data[0]]
+ });
+
+ expect(controller.$state.go).toHaveBeenCalledWith('route.agencyTerm.createInvoiceIn', {q: params});
+ });
+ });
+ });
+});
diff --git a/modules/route/front/roadmap/main/index.spec.js b/modules/route/front/roadmap/main/index.spec.js
new file mode 100644
index 000000000..dcb14ec0e
--- /dev/null
+++ b/modules/route/front/roadmap/main/index.spec.js
@@ -0,0 +1,31 @@
+import './index';
+
+describe('Item', () => {
+ describe('Component vnItemType', () => {
+ let controller;
+
+ beforeEach(ngModule('item'));
+
+ beforeEach(inject($componentController => {
+ const $element = angular.element('');
+ controller = $componentController('vnItemType', {$element});
+ }));
+
+ describe('exprBuilder()', () => {
+ it('should return a filter based on a search by id', () => {
+ const filter = controller.exprBuilder('search', '123');
+
+ expect(filter).toEqual({id: '123'});
+ });
+
+ it('should return a filter based on a search by name or code', () => {
+ const filter = controller.exprBuilder('search', 'Alstroemeria');
+
+ expect(filter).toEqual({or: [
+ {name: {like: '%Alstroemeria%'}},
+ {code: {like: '%Alstroemeria%'}},
+ ]});
+ });
+ });
+ });
+});