Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2034-postcode_autocomplete
gitea/salix/pipeline/head There was a failure building this commit Details

This commit is contained in:
Joan Sanchez 2020-03-02 08:07:14 +01:00
commit 5ccc79df8c
233 changed files with 1767 additions and 689 deletions

View File

@ -32,3 +32,5 @@ rules:
indent: [error, 4]
arrow-parens: [error, as-needed]
jasmine/no-focused-tests: 0
no-multiple-empty-lines: ["error", { "max": 1, "maxEOF": 1 }]
space-in-parens: ["error", "never"]

View File

@ -24,8 +24,14 @@ module.exports = Self => {
});
Self.sendCheckingPresence = async(ctx, workerId, message) => {
if (!workerId) return false;
const models = Self.app.models;
const account = await models.Account.findById(workerId);
const userId = ctx.req.accessToken.userId;
if (!account)
throw new Error(`Could not send message "${message}" to worker id ${workerId} from user ${userId}`);
const query = `SELECT worker_isWorking(?) isWorking`;
const [result] = await Self.rawSql(query, [workerId]);
@ -37,7 +43,7 @@ module.exports = Self => {
}
});
const department = workerDepartment && workerDepartment.department();
const channelName = department.chatName;
const channelName = department && department.chatName;
if (channelName)
return Self.send(ctx, `#${channelName}`, `@${account.name} => ${message}`);

View File

@ -0,0 +1,6 @@
ALTER TABLE `vn`.`sample`
ADD COLUMN `hasPreview` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' AFTER `hasCompany`,
CHANGE COLUMN `isVisible` `isVisible` TINYINT(1) UNSIGNED NOT NULL DEFAULT '1' ,
CHANGE COLUMN `hasCompany` `hasCompany` TINYINT(1) UNSIGNED NOT NULL DEFAULT '0' ;
UPDATE `vn`.`sample` SET `hasPreview` = '0' WHERE (`id` = '14');

View File

@ -0,0 +1,2 @@
ALTER TABLE `vn`.`zoneEvent`
ADD COLUMN m3Max DECIMAL(10,2) UNSIGNED NULL DEFAULT NULL AFTER bonus;

View File

@ -1103,11 +1103,11 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`)
(104, 500),
(105, 5000);
INSERT INTO `vn`.`supplier`(`id`, `name`,`account`,`countryFk`,`nif`,`isFarmer`,`retAccount`,`commission`, `created`, `postcodeFk`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`)
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`retAccount`,`commission`, `created`, `postcodeFk`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`)
VALUES
(1, 'Plants SL', 4000000001, 1, 'A11111111', 0, NULL, 0, CURDATE(), 1111, 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1),
(2, 'Flower King', 4000000002, 1, 'B22222222', 0, NULL, 0, CURDATE(), 2222, 1, 'supplier address 2', 'LONDON', 2, 45671, 1, 2),
(442, 'Verdnatura Levante SL', 4000000442, 1, 'C33333333', 0, NULL, 0, CURDATE(), 3333, 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2);
(1, 'Plants SL', 'Plants nick', 4000000001, 1, 'A11111111', 0, NULL, 0, CURDATE(), 1111, 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1),
(2, 'Flower King', 'The king', 4000000002, 1, 'B22222222', 0, NULL, 0, CURDATE(), 2222, 1, 'supplier address 2', 'LONDON', 2, 45671, 1, 2),
(442, 'Verdnatura Levante SL', 'Verdnatura', 4000000442, 1, 'C33333333', 0, NULL, 0, CURDATE(), 3333, 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2);
INSERT INTO `cache`.`cache_calc`(`id`, `cache_id`, `cacheName`, `params`, `last_refresh`, `expires`, `created`, `connection_id`)
VALUES

View File

@ -40,16 +40,12 @@ let actions = {
},
login: async function(userName) {
try {
await this.expectURL('#!/login');
} catch (e) {
await this.goto(`${defaultURL}/#!/login`);
let dialog = await this.evaluate(() => {
return document.querySelector('button[response="accept"]');
});
if (dialog)
await this.waitToClick('button[response="accept"]');
}
await this.doLogin(userName);
await this.waitForFunction(() => {
@ -175,7 +171,7 @@ let actions = {
},
waitToClick: async function(selector) {
await this.waitForSelector(selector, {});
await this.waitForSelector(selector);
await this.click(selector);
},
@ -327,11 +323,18 @@ let actions = {
},
hideSnackbar: async function() {
await this.waitToClick('#shapes .shown button');
await this.waitFor(750); // holds up for the snackbar to be visible for a small period of time.
await this.evaluate(() => {
let hideButton = document.querySelector('#shapes .shown button');
if (hideButton)
return document.querySelector('#shapes .shown button').click();
});
},
waitForLastShape: async function(selector) {
await this.wait(selector);
waitForLastSnackbar: async function() {
const selector = 'vn-snackbar .shown .text';
await this.waitForSelector(selector);
let snackBarText = await this.evaluate(selector => {
const shape = document.querySelector(selector);
@ -341,12 +344,6 @@ let actions = {
return snackBarText;
},
waitForLastSnackbar: async function() {
await this.waitFor(1000); // this needs a refactor to be somehow dynamic ie: page.waitForResponse(urlOrPredicate[, options]) or something to fire waitForLastShape once the request is completed
await this.waitForSpinnerLoad();
return await this.waitForLastShape('vn-snackbar .shown .text');
},
accessToSearchResult: async function(searchValue) {
await this.clearInput('vn-searchbar');
await this.write('vn-searchbar', searchValue);
@ -412,7 +409,7 @@ let actions = {
.includes(searchValue.toLowerCase());
}, {}, builtSelector, searchValue);
await this.waitForMutation(`.vn-drop-down`, 'childList');
await this.waitForMutation('.vn-drop-down', 'childList');
await this.waitForContentLoaded();
},

View File

@ -28,7 +28,7 @@ export async function getBrowser() {
});
});
page = extendPage(page);
page.setDefaultTimeout(5000);
page.setDefaultTimeout(10000);
await page.goto(defaultURL, {waitUntil: 'networkidle0'});
return {page, close: browser.close.bind(browser)};
}

View File

@ -511,14 +511,16 @@ export default {
},
ticketRequests: {
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
request: 'vn-ticket-request-index vn-table vn-tr',
descriptionInput: 'vn-ticket-request-create [ng-model="$ctrl.ticketRequest.description"]',
atender: 'vn-ticket-request-create vn-autocomplete[ng-model="$ctrl.ticketRequest.attenderFk"]',
quantity: 'vn-ticket-request-create vn-input-number[ng-model="$ctrl.ticketRequest.quantity"]',
price: 'vn-ticket-request-create vn-input-number[ng-model="$ctrl.ticketRequest.price"]',
firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)',
firstRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(6) vn-input-number',
secondRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(2) > vn-td:nth-child(6) vn-input-number',
thirdDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(3) > vn-td:nth-child(2) vn-textfield',
thirdRemoveRequestButton: 'vn-ticket-request-index vn-tr:nth-child(3) vn-icon[icon="delete"]',
thirdRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(3) > vn-td:nth-child(6) vn-input-number',
saveButton: 'vn-ticket-request-create button[type=submit]',
firstDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(2) vn-textfield',
},
ticketLog: {
@ -788,7 +790,7 @@ export default {
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
upload: 'vn-travel-thermograph-create button[type=submit]'
},
agencyBasicData: {
zoneBasicData: {
name: 'vn-zone-basic-data vn-textfield[ng-model="$ctrl.zone.name"]',
agency: 'vn-zone-basic-data vn-autocomplete[ng-model="$ctrl.zone.agencyModeFk"]',
maxVolume: 'vn-zone-basic-data vn-input-number[ng-model="$ctrl.zone.m3Max"]',
@ -799,5 +801,10 @@ export default {
inflation: 'vn-zone-basic-data vn-input-number[ng-model="$ctrl.zone.inflation"]',
volumetric: 'vn-zone-basic-data vn-check[ng-model="$ctrl.zone.isVolumetric"]',
saveButton: 'vn-zone-basic-data vn-submit > button',
},
entrySummary: {
header: 'vn-entry-summary > vn-card > h5',
reference: 'vn-entry-summary vn-label-value[label="Reference"]',
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
}
};

View File

@ -101,7 +101,6 @@ describe('Client create path', async() => {
});
it('should click on the Clients button of the top bar menu', async() => {
await page.waitFor(500);
await page.waitToClick(selectors.globalItems.applicationsMenuButton);
await page.wait(selectors.globalItems.applicationsMenuVisible);
await page.waitToClick(selectors.globalItems.clientsButton);

View File

@ -160,6 +160,7 @@ describe('Client Edit fiscalData path', () => {
});
it('should propagate the Equalization tax changes', async() => {
await page.waitFor(1000);
await page.waitToClick(selectors.clientFiscalData.acceptPropagationButton);
const result = await page.waitForLastSnackbar();

View File

@ -47,7 +47,7 @@ describe('Client Add address path', () => {
expect(result).toEqual('Incoterms is required for a non UEE member');
});
it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => {
it(`should receive an error after clicking save button as customsAgent is empty`, async() => {
await page.autocompleteSearch(selectors.clientAddresses.incoterms, 'Free Alongside Ship');
await page.waitToClick(selectors.clientAddresses.saveButton);
const result = await page.waitForLastSnackbar();
@ -63,13 +63,20 @@ describe('Client Add address path', () => {
expect(result).toEqual('Data saved!');
});
it(`should click on the first address button to confirm the new address exists and it's the default one`, async() => {
it(`should navigate back to the addresses index`, async() => {
let url = await page.expectURL('/address/index');
expect(url).toBe(true);
});
it(`should confirm the new address exists and it's the default one`, async() => {
await page.waitFor(2000); // needs more than a single second to load the section
const result = await page.waitToGetProperty(selectors.clientAddresses.defaultAddress, 'innerText');
expect(result).toContain('320 Park Avenue New York');
});
it(`should click on the make default icon of the second address`, async() => {
it('should click on the make default icon of the second address', async() => {
await page.waitToClick(selectors.clientAddresses.secondMakeDefaultStar);
const result = await page.waitForLastSnackbar();
@ -101,6 +108,7 @@ describe('Client Add address path', () => {
});
it(`should go back to the addreses section by clicking the cancel button`, async() => {
await page.waitForSelector('#shapes .shown', {hidden: true});
await page.waitToClick(selectors.clientAddresses.cancelEditAddressButton);
await page.waitToClick('.vn-confirm.shown button[response="accept"]');
let url = await page.expectURL('address/index');

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors';
import getBrowser from '../../helpers/puppeteer';
describe('Client lock verified data path', () => {
xdescribe('Client lock verified data path', () => {
let browser;
let page;
beforeAll(async() => {
@ -113,7 +113,7 @@ describe('Client lock verified data path', () => {
});
});
describe('as salesAssistant', () => {
xdescribe('as salesAssistant', () => {
it('should log in as salesAssistant then get to the client fiscal data', async() => {
await page.forceReloadSection('client.card.fiscalData');
await page.loginAndModule('salesAssistant', 'client');

View File

@ -85,7 +85,7 @@ describe('User config', () => {
await page.autocompleteSearch(selectors.globalItems.userLocalCompany, 'VNL');
let result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
expect(result).toContain('Data saved!');
});
});
@ -125,7 +125,7 @@ describe('User config', () => {
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
let result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
expect(result).toContain('Data saved!');
});
});
});

View File

@ -32,6 +32,6 @@ describe('Client contacts', () => {
await page.waitToClick(selectors.clientContacts.saveButton);
let result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
expect(result).toContain('Data saved!');
});
});

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Worker time control path', () => {
xdescribe('Worker time control path', () => {
let browser;
let page;
beforeAll(async() => {

View File

@ -37,22 +37,21 @@ describe('Item Edit basic data path', () => {
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
}, 20000);
});
it(`should create a new intrastat`, async() => {
await page.waitToClick(selectors.itemBasicData.newIntrastatButton);
await page.write(selectors.itemBasicData.newIntrastatId, '588420239');
await page.write(selectors.itemBasicData.newIntrastatDescription, 'Tropical Flowers');
await page.waitToClick(selectors.itemBasicData.acceptIntrastatButton);
await page.waitToClick(selectors.itemBasicData.acceptIntrastatButton); // this popover obscures the rest of the form for aprox 2 seconds
await page.waitFor(2000);
await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers');
let newcode = await page.waitToGetProperty(selectors.itemBasicData.intrastat, 'value');
expect(newcode).toEqual('588420239 Tropical Flowers');
});
it(`should save with the new intrastat`, async() => {
await page.waitFor(250);
await page.waitForTextInField(selectors.itemBasicData.intrastat, 'Tropical Flowers');
it('should save with the new intrastat', async() => {
await page.waitToClick(selectors.itemBasicData.submitBasicDataButton);
const result = await page.waitForLastSnackbar();

View File

@ -33,7 +33,6 @@ describe('Item regularize path', () => {
});
it('should search for an specific item', async() => {
await page.clearInput(selectors.itemsIndex.topbarSearch);
await page.write(selectors.itemsIndex.topbarSearch, 'Ranged weapon pistol 9mm');
await page.waitToClick(selectors.itemsIndex.searchButton);
await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 1);
@ -42,7 +41,7 @@ describe('Item regularize path', () => {
expect(resultCount).toEqual(1);
});
it(`should click on the search result to access to the item tax`, async() => {
it(`should click on the search result to access to the summary`, async() => {
await page.waitForTextInElement(selectors.itemsIndex.searchResult, 'Ranged weapon pistol 9mm');
await page.waitToClick(selectors.itemsIndex.searchResult);
let url = await page.expectURL('/summary');
@ -80,6 +79,7 @@ describe('Item regularize path', () => {
});
it('should clear the user local settings now', async() => {
await page.waitForContentLoaded();
await page.waitToClick(selectors.globalItems.userMenuButton);
await page.clearInput(selectors.globalItems.userConfigFirstAutocomplete);
const result = await page.waitForLastSnackbar();

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Item index path', () => {
xdescribe('Item index path', () => {
let browser;
let page;
beforeAll(async() => {
@ -54,7 +54,8 @@ describe('Item index path', () => {
await page.waitForSelector(selectors.itemsIndex.firstItemId, {hidden: true});
});
it('should mark all unchecked boxes to leave the index as it was', async() => {
xit('should mark all unchecked boxes to leave the index as it was', async() => {
await page.waitForContentLoaded();
await page.waitToClick(selectors.itemsIndex.fieldsToShowButton);
await page.waitToClick(selectors.itemsIndex.idCheckbox);
await page.waitToClick(selectors.itemsIndex.stemsCheckbox);

View File

@ -97,6 +97,7 @@ describe('Ticket List sale path', () => {
});
it('should select the 2nd and 3th item and delete both', async() => {
await page.waitFor(2000);
await page.waitToClick(selectors.ticketSales.secondSaleCheckbox);
await page.waitToClick(selectors.ticketSales.thirdSaleCheckbox);
await page.waitToClick(selectors.ticketSales.deleteSaleButton);

View File

@ -9,7 +9,7 @@ describe('Ticket purchase request path', () => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('salesPerson', 'ticket');
await page.accessToSearchResult('16');
await page.accessToSearchResult('1');
await page.accessToSection('ticket.card.request.index');
});
@ -17,10 +17,10 @@ describe('Ticket purchase request path', () => {
await browser.close();
});
it(`should add a new request`, async() => {
it('should add a new request', async() => {
await page.waitToClick(selectors.ticketRequests.addRequestButton);
await page.write(selectors.ticketRequests.descriptionInput, 'New stuff');
await page.write(selectors.ticketRequests.quantity, '99');
await page.write(selectors.ticketRequests.quantity, '9');
await page.autocompleteSearch(selectors.ticketRequests.atender, 'buyerNick');
await page.write(selectors.ticketRequests.price, '999');
await page.waitToClick(selectors.ticketRequests.saveButton);
@ -29,29 +29,52 @@ describe('Ticket purchase request path', () => {
expect(result).toEqual('Data saved!');
});
it(`should have been redirected to the request index`, async() => {
it('should have been redirected to the request index', async() => {
let url = await page.expectURL('/request');
expect(url).toBe(true);
});
it(`should confirm the new request was added`, async() => {
await page.reloadSection('ticket.card.request.index');
const result = await page.waitToGetProperty(selectors.ticketRequests.firstDescription, 'value');
expect(result).toEqual('New stuff');
});
it(`should delete the added request`, async() => {
await page.waitToClick(selectors.ticketRequests.firstRemoveRequestButton);
it(`should edit the third request quantity as it's state is still new`, async() => {
await page.waitFor(2000); // looks like it needs more than a single second some times to load
await page.write(selectors.ticketRequests.thirdRequestQuantity, '9');
await page.keyboard.press('Enter');
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it(`should confirm the request was deleted`, async() => {
it('should confirm the new request was added', async() => {
await page.reloadSection('ticket.card.request.index');
const result = await page.waitToGetProperty(selectors.ticketRequests.thirdRequestQuantity, 'value');
expect(result).toEqual('99');
});
it(`should confirm first request can't be edited as its state is different to new`, async() => {
await page.waitForClassPresent(selectors.ticketRequests.firstRequestQuantity, 'disabled');
const result = await page.isDisabled(selectors.ticketRequests.firstRequestQuantity);
expect(result).toBe(true);
});
it(`should confirm second request can't be edited as its state is different to new`, async() => {
await page.waitForClassPresent(selectors.ticketRequests.secondRequestQuantity, 'disabled');
const result = await page.isDisabled(selectors.ticketRequests.secondRequestQuantity);
expect(result).toBe(true);
});
it('should delete the added request', async() => {
await page.waitToClick(selectors.ticketRequests.thirdRemoveRequestButton);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should confirm the request was deleted', async() => {
await page.reloadSection('ticket.card.request.index');
await page.wait(selectors.ticketRequests.addRequestButton);
await page.waitForSelector(selectors.ticketRequests.request, {hidden: true});
await page.waitForSelector(selectors.ticketRequests.thirdDescription, {hidden: true});
});
});

View File

@ -129,6 +129,7 @@ describe('Ticket descriptor path', () => {
});
it('should delete the stowaway', async() => {
await page.waitForContentLoaded();
await page.waitToClick(selectors.ticketDescriptor.moreMenu);
await page.waitToClick(selectors.ticketDescriptor.moreMenuDeleteStowawayButton);
await page.waitToClick(selectors.ticketDescriptor.acceptDeleteStowawayButton);

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Claim action path', () => {
xdescribe('Claim action path', () => {
let browser;
let page;
@ -24,7 +24,8 @@ describe('Claim action path', () => {
expect(result).toEqual('Data saved!');
});
it('should import the second importable ticket', async() => {
xit('should import the second importable ticket', async() => {
await page.waitFor(2000); // the animation adding the header element for the claimed total obscures somehow other elements for 2 seconds
await page.waitToClick(selectors.claimAction.importTicketButton);
await page.waitToClick(selectors.claimAction.secondImportableTicket);
const result = await page.waitForLastSnackbar();
@ -33,6 +34,7 @@ describe('Claim action path', () => {
});
it('should edit the second line destination field', async() => {
await page.waitForContentLoaded();
await page.autocompleteSearch(selectors.claimAction.secondLineDestination, 'Bueno');
const result = await page.waitForLastSnackbar();
@ -43,7 +45,7 @@ describe('Claim action path', () => {
await page.waitToClick(selectors.claimAction.firstDeleteLine);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
expect(result).toContain('Data saved!');
});
it('should refresh the view to check the remaining line is the expected one', async() => {
@ -61,6 +63,7 @@ describe('Claim action path', () => {
});
it('should check the "is paid with mana" checkbox', async() => {
page.waitFor(2500); // can't use waitForNavigation here and needs more time than a single second to get the section ready...
await page.waitToClick(selectors.claimAction.isPaidWithManaCheckbox);
const result = await page.waitForLastSnackbar();

View File

@ -1,7 +1,7 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('InvoiceOut descriptor path', () => {
xdescribe('InvoiceOut descriptor path', () => {
let browser;
let page;
@ -26,7 +26,7 @@ describe('InvoiceOut descriptor path', () => {
expect(result).toEqual(1);
});
it('should navigate to the invoiceOut index', async() => {
xit('should navigate to the invoiceOut index', async() => {
await page.waitToClick(selectors.globalItems.applicationsMenuButton);
await page.wait(selectors.globalItems.applicationsMenuVisible);
await page.waitToClick(selectors.globalItems.invoiceOutButton);

View File

@ -1,103 +0,0 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Agency basic data path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('deliveryBoss', 'zone'); // turns up the agency module name and route aint the same lol
await page.accessToSearchResult('10');
await page.accessToSection('zone.card.basicData');
});
afterAll(async() => {
await browser.close();
});
it('should reach the basic data section', async() => {
let url = await page.expectURL('#!/zone/10/basic-data');
expect(url).toBe(true);
});
it('should edit de form and then save', async() => {
await page.clearInput(selectors.agencyBasicData.name);
await page.write(selectors.agencyBasicData.name, 'Brimstone teleportation');
await page.autocompleteSearch(selectors.agencyBasicData.agency, 'Quantum break device');
await page.write(selectors.agencyBasicData.maxVolume, '10');
await page.clearInput(selectors.agencyBasicData.travelingDays);
await page.write(selectors.agencyBasicData.travelingDays, '1');
await page.clearInput(selectors.agencyBasicData.closing);
await page.type(selectors.agencyBasicData.closing, '2100');
await page.clearInput(selectors.agencyBasicData.price);
await page.write(selectors.agencyBasicData.price, '999');
await page.clearInput(selectors.agencyBasicData.bonus);
await page.write(selectors.agencyBasicData.bonus, '100');
await page.clearInput(selectors.agencyBasicData.inflation);
await page.write(selectors.agencyBasicData.inflation, '200');
await page.waitToClick(selectors.agencyBasicData.volumetric);
await page.waitToClick(selectors.agencyBasicData.saveButton);
});
it('should reload the section', async() => {
await page.reloadSection('zone.card.basicData');
let url = await page.expectURL('#!/zone/10/basic-data');
expect(url).toBe(true);
});
it('should confirm the name was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.name, 'value');
expect(result).toEqual('Brimstone teleportation');
});
it('should confirm the agency was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.agency, 'value');
expect(result).toEqual('Quantum break device');
});
it('should confirm the max volume was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.maxVolume, 'value');
expect(result).toEqual('10');
});
it('should confirm the traveling days were updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.travelingDays, 'value');
expect(result).toEqual('1');
});
it('should confirm the closing hour was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.closing, 'value');
expect(result).toEqual('21:00');
});
it('should confirm the price was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.price, 'value');
expect(result).toEqual('999');
});
it('should confirm the bonus was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.bonus, 'value');
expect(result).toEqual('100');
});
it('should confirm the inflation was updated', async() => {
const result = await page.waitToGetProperty(selectors.agencyBasicData.inflation, 'value');
expect(result).toEqual('200');
});
it('should confirm the volumetric checkbox was checked', async() => {
await page.waitForClassPresent(selectors.agencyBasicData.volumetric, 'checked');
});
});

View File

@ -0,0 +1,103 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
xdescribe('Zone basic data path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('deliveryBoss', 'zone'); // turns up the zone module name and route aint the same lol
await page.accessToSearchResult('10');
await page.accessToSection('zone.card.basicData');
});
afterAll(async() => {
await browser.close();
});
it('should reach the basic data section', async() => {
let url = await page.expectURL('#!/zone/10/basic-data');
expect(url).toBe(true);
});
it('should edit de form and then save', async() => {
await page.clearInput(selectors.zoneBasicData.name);
await page.write(selectors.zoneBasicData.name, 'Brimstone teleportation');
await page.autocompleteSearch(selectors.zoneBasicData.agency, 'Quantum break device');
await page.write(selectors.zoneBasicData.maxVolume, '10');
await page.clearInput(selectors.zoneBasicData.travelingDays);
await page.write(selectors.zoneBasicData.travelingDays, '1');
await page.clearInput(selectors.zoneBasicData.closing);
await page.type(selectors.zoneBasicData.closing, '2100');
await page.clearInput(selectors.zoneBasicData.price);
await page.write(selectors.zoneBasicData.price, '999');
await page.clearInput(selectors.zoneBasicData.bonus);
await page.write(selectors.zoneBasicData.bonus, '100');
await page.clearInput(selectors.zoneBasicData.inflation);
await page.write(selectors.zoneBasicData.inflation, '200');
await page.waitToClick(selectors.zoneBasicData.volumetric);
await page.waitToClick(selectors.zoneBasicData.saveButton);
});
xit('should reload the section', async() => {
await page.reloadSection('zone.card.basicData');
let url = await page.expectURL('#!/zone/10/basic-data');
expect(url).toBe(true);
});
it('should confirm the name was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.name, 'value');
expect(result).toEqual('Brimstone teleportation');
});
it('should confirm the agency was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.agency, 'value');
expect(result).toEqual('Quantum break device');
});
it('should confirm the max volume was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.maxVolume, 'value');
expect(result).toEqual('10');
});
it('should confirm the traveling days were updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.travelingDays, 'value');
expect(result).toEqual('1');
});
xit('should confirm the closing hour was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.closing, 'value');
expect(result).toEqual('21:00');
});
it('should confirm the price was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.price, 'value');
expect(result).toEqual('999');
});
it('should confirm the bonus was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.bonus, 'value');
expect(result).toEqual('100');
});
it('should confirm the inflation was updated', async() => {
const result = await page.waitToGetProperty(selectors.zoneBasicData.inflation, 'value');
expect(result).toEqual('200');
});
it('should confirm the volumetric checkbox was checked', async() => {
await page.waitForClassPresent(selectors.zoneBasicData.volumetric, 'checked');
});
});

View File

@ -0,0 +1,43 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.waitToClick('vn-entry-index vn-tbody > a:nth-child(2)');
});
afterAll(async() => {
await browser.close();
});
it('should reach the second entry summary section', async() => {
let url = await page.expectURL('#!/entry/2/summary');
expect(url).toBe(true);
});
it(`should display details from the entry on the header`, async() => {
await page.waitForTextInElement(selectors.entrySummary.header, 'The king');
const result = await page.waitToGetProperty(selectors.entrySummary.header, 'innerText');
expect(result).toContain('The king');
});
it('should display some entry details like the reference', async() => {
const result = await page.waitToGetProperty(selectors.entrySummary.reference, 'innerText');
expect(result).toContain('Movement 2');
});
it('should display other entry details like the confirmed', async() => {
const result = await page.checkboxState(selectors.entrySummary.confirmed, 'innerText');
expect(result).toContain('unchecked');
});
});

View File

@ -16,7 +16,7 @@ describe('Component vnButtonMenu', () => {
describe('onButtonClick(event)', () => {
it(`should emit the open event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
let event = new MouseEvent('click', {
view: controller.element.window,
@ -31,7 +31,7 @@ describe('Component vnButtonMenu', () => {
describe('onDropDownSelect(value)', () => {
it(`should set field to the given value and emit the change event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.onDropDownSelect({name: 'Item name'});
expect(controller.field).toBe('Item name');

View File

@ -23,7 +23,7 @@
<section
ng-repeat="day in ::$ctrl.weekDays"
translate-attr="::{title: day.name}"
ng-click="$ctrl.selectWeekDay(day.index)">
ng-click="$ctrl.selectWeekDay($event, day.index)">
<span>{{::day.localeChar}}</span>
</section>
</div>
@ -38,7 +38,7 @@
on-last="$ctrl.repeatLast()">
<div
class="day-number"
ng-click="$ctrl.select(day)">
ng-click="$ctrl.select($event, day)">
{{::day | date: 'd'}}
</div>
</section>

View File

@ -127,10 +127,11 @@ export default class Calendar extends FormInput {
/*
* Day selection event
*/
select(day) {
select($event, day) {
if (!this.editable) return;
this.change(day);
this.emit('selection', {
$event: $event,
$days: [day],
$type: 'day'
});
@ -140,7 +141,7 @@ export default class Calendar extends FormInput {
/*
* WeekDay selection event
*/
selectWeekDay(weekday) {
selectWeekDay($event, weekday) {
if (!this.editable) return;
let days = [];
for (let day of this.days) {
@ -149,6 +150,7 @@ export default class Calendar extends FormInput {
}
this.field = days[0];
this.emit('selection', {
$event: $event,
$days: days,
$type: 'weekday',
$weekday: weekday

View File

@ -20,7 +20,7 @@ describe('Component vnCalendar', () => {
describe('moveNext()', () => {
it(`should shift to the next month, then emit a 'move' event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
let nextMonth = new Date(date.getTime());
nextMonth.setMonth(nextMonth.getMonth() + 1);
@ -33,7 +33,7 @@ describe('Component vnCalendar', () => {
describe('movePrevious()', () => {
it(`should shift to the previous month, then emit a 'move' event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
let previousMonth = new Date(date.getTime());
previousMonth.setMonth(previousMonth.getMonth() - 1);
@ -46,13 +46,19 @@ describe('Component vnCalendar', () => {
describe('select()', () => {
it(`should return the selected element, then emit a 'selection' event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
const day = new Date();
day.setHours(0, 0, 0, 0);
controller.select(day);
const clickEvent = new Event('click');
const target = document.createElement('div');
target.dispatchEvent(clickEvent);
controller.select(clickEvent, day);
let res = {
$event: clickEvent,
$days: [day],
$type: 'day'
};

View File

@ -17,7 +17,7 @@ describe('Component vnChip', () => {
describe('onRemove()', () => {
it(`should emit remove event`, () => {
controller.emit = () => {};
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.onRemove();
expect(controller.emit).toHaveBeenCalledWith('remove');

View File

@ -12,6 +12,15 @@ vn-chip {
max-width: 100%;
box-sizing: border-box;
&.small {
height: 1.5em;
& > div {
padding: 0.6em;
font-size: 0.8rem;
}
}
&.colored {
background-color: $color-main;
color: $color-font-bg;

View File

@ -100,7 +100,7 @@ export default class CrudModel extends ModelProxy {
}
removeFilter() {
return applyFilter(null, null);
return this.applyFilter(null, null);
}
/**
@ -240,14 +240,12 @@ export default class CrudModel extends ModelProxy {
onRemoteDone(json, filter, append) {
let data = json.data;
if (append)
this.orgData = this.orgData.concat(data);
else {
this.orgData = data;
this.currentFilter = filter;
}
this.data = this.proxiedData.slice();
this.moreRows = filter.limit && data.length == filter.limit;
this.onRequestEnd();

View File

@ -26,7 +26,7 @@ describe('Component vnCrudModel', () => {
describe('save()', () => {
it(`should make an HTTP post query and then update the original rows with the returned values`, () => {
spyOn(controller, 'applyChanges');
jest.spyOn(controller, 'applyChanges');
controller.insert({value: 'My new item 1'});
controller.insert({value: 'My new item 2'});
@ -47,4 +47,186 @@ describe('Component vnCrudModel', () => {
expect(controller.applyChanges).toHaveBeenCalledWith();
});
});
describe('setter url()', () => {
it('should set the url', () => {
spyOn(controller, 'autoRefresh');
spyOn(controller, 'clear');
controller.url = '/TestUrl';
expect(controller.url).toEqual('/TestUrl');
});
});
describe('isLoading()', () => {
it('should return false if canceler is null', () => {
controller.canceler = null;
expect(controller.isLoading).toBe(false);
});
it('should return true if canceler is not null', () => {
controller.canceler = 'validValue';
expect(controller.isLoading).toBe(true);
});
});
describe('buildFilter()', () => {
it('should build a filter and return it', () => {
controller.order = 'id ASC';
controller.fields = ['id'];
controller.limit = 1;
controller.filter = 'filterTest';
const result = controller.buildFilter();
expect(Object.keys(result).length).toEqual(13);
});
});
describe('sendRequest()', () => {
it('should call refresh() and check that the sendRequest is called', () => {
spyOn(controller, 'sendRequest').and.callThrough();
spyOn(controller, 'onRemoteDone');
spyOn(controller, 'onRemoteError');
const filter = {id: 1};
const serializedParams = encodeURIComponent(JSON.stringify(filter));
$httpBackend.whenRoute('GET', `model?filter=${serializedParams}`).respond();
controller.sendRequest(filter, true);
$httpBackend.flush();
expect(controller.isPaging).toBe(false);
});
});
describe('addFilter()', () => {
it('should call addFilter and check that the new filter has been added', () => {
spyOn(controller, 'refresh');
const filter = {where: {id: 1}};
controller.userFilter = {where: {name: 'test'}};
const filterMerged = {'where': {'and': [{'name': 'test'}, {'id': 1}]}};
controller.addFilter(filter);
expect(controller.userFilter).toEqual(filterMerged);
expect(controller.refresh).toHaveBeenCalledWith();
});
});
describe('applyFilter()', () => {
it('should call applyFilter and check that the refresh() is called', () => {
spyOn(controller, 'refresh');
const filter = {where: {id: 1}};
const params = {where: {id: 2}};
controller.applyFilter(filter, params);
expect(controller.userFilter).toEqual(filter);
expect(controller.userParams).toEqual(params);
expect(controller.refresh).toHaveBeenCalledWith();
});
});
describe('removeFilter()', () => {
it('should check the userFilter and userParams are removed', () => {
controller.removeFilter();
expect(controller.userFilter).toBe(null);
expect(controller.userParams).toBe(null);
});
});
describe('loadMore()', () => {
it('should call sendRequest with the new filter', () => {
spyOn(controller, 'sendRequest');
controller.moreRows = true;
controller.loadMore();
expect(controller.sendRequest).toHaveBeenCalledWith({'skip': 2}, true);
});
});
describe('clear()', () => {
it('should check that orgData and moreRows are set to null', () => {
controller.moreRows = true;
controller.clear();
expect(controller.moreRows).toBe(null);
expect(controller.orgData).toBe(null);
});
});
describe('refresh()', () => {
it('shold resolve a fake promise if this._url is undefined', () => {
spyOn(controller.$q, 'resolve');
controller._url = undefined;
controller.refresh();
expect(controller.$q.resolve).toHaveBeenCalledWith();
});
});
describe('onRemoteDone()', () => {
it('should check onRequestEnd is called, moreRows is true and currentFilter is undefined when append is true', () => {
spyOn(controller, 'onRequestEnd');
const append = true;
const json = {data: [
{
id: 1,
name: 'test'
}]};
const filter = {limit: 1};
controller.onRemoteDone(json, filter, append);
expect(controller.moreRows).toBe(true);
expect(controller.currentFilter).toBeUndefined();
expect(controller.onRequestEnd).toHaveBeenCalledWith();
});
it('should check onRequestEnd is called, moreRows is true and currentFilter is defined when append is false', () => {
spyOn(controller, 'onRequestEnd');
const append = false;
const json = {data: [
{
id: 1,
name: 'test'
}]};
const filter = {limit: 1};
controller.onRemoteDone(json, filter, append);
expect(controller.moreRows).toBe(true);
expect(controller.currentFilter).toBe(filter);
expect(controller.onRequestEnd).toHaveBeenCalledWith();
});
});
describe('onRemoteError()', () => {
it('should check the error', () => {
spyOn(controller, 'onRequestEnd');
let error;
try {
const newError = new Error('TestError');
controller.onRemoteError(newError);
} catch (e) {
error = e.message;
}
expect(controller.onRequestEnd).toHaveBeenCalledWith();
expect(error).toEqual('TestError');
});
});
});

View File

@ -30,7 +30,7 @@ describe('Component vnDialog', () => {
it(`should not hide the dialog when false is returned from response handler`, () => {
controller.show(() => false);
spyOn(controller, 'hide');
jest.spyOn(controller, 'hide');
controller.respond('answer');
expect(controller.hide).not.toHaveBeenCalled();
@ -51,7 +51,7 @@ describe('Component vnDialog', () => {
describe('respond()', () => {
it(`should do nothing if dialog is already hidden`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
jest.spyOn(controller, 'onResponse');
controller.respond();
expect(controller.onResponse).not.toHaveBeenCalledWith();
@ -59,7 +59,7 @@ describe('Component vnDialog', () => {
it(`should call onResponse() if it's defined`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
jest.spyOn(controller, 'onResponse');
controller.show();
controller.respond();
@ -69,7 +69,7 @@ describe('Component vnDialog', () => {
it(`should call onResponse() with the response`, () => {
controller.onResponse = () => {};
spyOn(controller, 'onResponse');
jest.spyOn(controller, 'onResponse');
controller.show();
controller.respond('response');
@ -79,7 +79,7 @@ describe('Component vnDialog', () => {
it(`should call onAccept() when accept response is given`, () => {
controller.onAccept = () => {};
spyOn(controller, 'onAccept');
jest.spyOn(controller, 'onAccept');
controller.show();
controller.respond('accept');

View File

@ -20,7 +20,7 @@ describe('Component vnMultiCheck', () => {
describe('checked() setter', () => {
it(`should set controller _checked property with the argument received then call toggle()`, () => {
spyOn(controller, 'toggle');
jest.spyOn(controller, 'toggle');
controller.checked = crudModel;
expect(controller._checked).toEqual(crudModel);

View File

@ -37,6 +37,22 @@ export default class Popover extends Popup {
super.hide();
}
get parent() {
return this.__parent;
}
// Bug #2147 Popover loses parent location
set parent(value) {
this.__parent = value;
if (!value) return;
const parentRect = value.getBoundingClientRect();
this.parentRect = {};
for (let prop in parentRect)
this.parentRect[prop] = parentRect[prop];
}
/**
* Repositions the popover to a correct location relative to the parent.
*/
@ -55,7 +71,7 @@ export default class Popover extends Popup {
arrowStyle.top = '';
arrowStyle.bottom = '';
let parentRect = this.parent.getBoundingClientRect();
let parentRect = this.parentRect;
let popoverRect = this.windowEl.getBoundingClientRect();
let arrowRect = arrow.getBoundingClientRect();
let clamp = (value, min, max) => Math.min(Math.max(value, min), max);

View File

@ -22,7 +22,7 @@ describe('Component vnPopover', () => {
describe('show()', () => {
it(`should enable the shown property and emit the open event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.show();
expect(controller.shown).toBeTruthy();
@ -31,7 +31,7 @@ describe('Component vnPopover', () => {
it(`should do nothing if it's already shown`, () => {
controller.shown = true;
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.show();
expect(controller.emit).not.toHaveBeenCalledWith('open');
@ -65,7 +65,7 @@ describe('Component vnPopover', () => {
describe('hide()', () => {
it(`should disable the shown property and emit the close event`, inject($timeout => {
controller.show();
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.hide();
$timeout.flush();
@ -75,7 +75,7 @@ describe('Component vnPopover', () => {
it(`should do nothing if it's already hidden`, () => {
controller.shown = false;
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.hide();
expect(controller.emit).not.toHaveBeenCalledWith('close');

View File

@ -139,7 +139,7 @@ describe('Component vnSearchbar', () => {
describe('doSearch()', () => {
it(`should go to the search state and pass the filter as query param`, () => {
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller.searchState = 'search.state';
controller.doSearch(filter);

View File

@ -63,15 +63,58 @@ export default class Controller extends Component {
show(data) {
this.actionHandler = data.actionHandler;
let shape = this.createShape(data);
let shape;
setTimeout(() =>
this.hide(shape), data.timeout || 3000);
const lastShape = this.lastShape;
const lastShapeData = lastShape && lastShape.data;
const isEqual = lastShape && (lastShapeData.shapeType == data.shapeType && lastShapeData.message == data.message);
if (lastShape && isEqual) {
shape = lastShape.element;
const shapeText = shape.querySelector('.text');
let chip = shapeText.querySelector('vn-chip');
if (chip) {
const text = chip.querySelector('span');
const number = parseInt(text.innerHTML);
text.innerHTML = number + 1;
} else {
chip = document.createElement('vn-chip');
chip.setAttribute('class', 'warning small');
let parent = document.createElement('div');
let span = document.createElement('span');
let text = document.createTextNode(1);
span.append(text);
parent.append(span);
chip.append(parent);
shapeText.appendChild(chip);
}
lastShape.element.classList.add('shown');
if (this.hideTimeout)
clearTimeout(this.hideTimeout);
} else {
shape = this.createShape(data);
setTimeout(() =>
shape.classList.add('shown'), 30);
}
this.hideTimeout = setTimeout(() => {
this.hide(shape);
this.lastShape = null;
}, data.timeout || 3000);
this.lastShape = {
data: data,
element: shape
};
}
/**
* Shows an error.
*

View File

@ -19,10 +19,16 @@ vn-snackbar .shape {
border-radius: .2em;
margin-bottom: 15px;
color: white;
padding: 1em;
padding: 0.8em;
&.text {
text-align: center
& > .text {
text-align: center;
vn-chip {
position: absolute;
left: -1em;
top: -1em;
}
}
&.shown {

View File

@ -17,14 +17,14 @@ describe('Component vnSpinner', () => {
describe('enable()', () => {
it(`should call start() when enable is set to true`, () => {
spyOn(controller, 'start');
jest.spyOn(controller, 'start');
controller.enable = true;
expect(controller.start).toHaveBeenCalledWith();
});
it(`should call stop() when enable is set to false`, () => {
spyOn(controller, 'stop');
jest.spyOn(controller, 'stop');
controller.enable = false;
expect(controller.stop).toHaveBeenCalledWith();

View File

@ -8,7 +8,7 @@ describe('Component vnStepControl', () => {
beforeEach(angular.mock.inject(($componentController, _$state_) => {
$state = _$state_;
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller = $componentController('vnStepControl', {$state: $state});
}));

View File

@ -20,7 +20,7 @@ describe('Component vnTh', () => {
describe('onInit()', () => {
it(`should define controllers order as per defaultOrder then call setOrder()`, () => {
controller.defaultOrder = 'DESC';
spyOn(controller.table, 'setOrder');
jest.spyOn(controller.table, 'setOrder');
controller.$onInit();
expect(controller.order).toEqual('DESC');
@ -44,7 +44,7 @@ describe('Component vnTh', () => {
});
it(`should call the setOrder() function after changing a value`, () => {
spyOn(controller.table, 'setOrder');
jest.spyOn(controller.table, 'setOrder');
controller.order = 'Change me!';
expect(controller.table.setOrder).toHaveBeenCalledWith('MyField', 'Change me!');
@ -54,7 +54,7 @@ describe('Component vnTh', () => {
describe('onToggleOrder()', () => {
it(`should not call updateArrow() method if field property isn't defined`, () => {
controller.column.setAttribute('field', '');
spyOn(controller, 'updateArrow');
jest.spyOn(controller, 'updateArrow');
controller.onToggleOrder();
@ -64,8 +64,8 @@ describe('Component vnTh', () => {
it(`should call toggleOrder() method if field property and
table field property equals and then call updateArrow()`, () => {
controller.table.field = 'MyField';
spyOn(controller, 'toggleOrder');
spyOn(controller, 'updateArrow');
jest.spyOn(controller, 'toggleOrder');
jest.spyOn(controller, 'updateArrow');
controller.onToggleOrder();
@ -76,8 +76,8 @@ describe('Component vnTh', () => {
it(`should call setOrder() method if field property and
table field property doesn't equals and then call updateArrow()`, () => {
controller.table.field = 'MyField2';
spyOn(controller.table, 'setOrder');
spyOn(controller, 'updateArrow');
jest.spyOn(controller.table, 'setOrder');
jest.spyOn(controller, 'updateArrow');
controller.onToggleOrder();

View File

@ -37,7 +37,7 @@ describe('Component vnTreeview', () => {
xdescribe('undrop()', () => {
it(`should reset all drop events and properties`, () => {
controller.dropping = angular.element(`<vn-treeview-child class="dropping"></vn-treeview-child>`);
spyOn(controller.dropping.classList, 'remove');
jest.spyOn(controller.dropping.classList, 'remove');
controller.undrop();
@ -69,9 +69,7 @@ describe('Component vnTreeview', () => {
describe('fetch()', () => {
it(`should call the fetchFunc() method`, () => {
spyOn(controller, 'fetchFunc').and.returnValue(
new Promise(resolve => resolve([{name: 'My item'}]))
);
jest.spyOn(controller, 'fetchFunc');
controller.fetch().then(() => {
expect(controller.data).toBeDefined();
});
@ -82,7 +80,7 @@ describe('Component vnTreeview', () => {
describe('setParent()', () => {
it(`should set the parent property recursively to each element of an item list`, () => {
spyOn(controller, 'setParent').and.callThrough();
jest.spyOn(controller, 'setParent');
const items = [{name: 'Item1'}, {name: 'Item2', childs: [
{name: 'Item3'}
]}];
@ -97,8 +95,8 @@ describe('Component vnTreeview', () => {
describe('onToggle()', () => {
it(`should call the fold() or unfold() methods`, () => {
spyOn(controller, 'fold');
spyOn(controller, 'unfold');
jest.spyOn(controller, 'fold');
jest.spyOn(controller, 'unfold');
let event = new MouseEvent('click', {
bubbles: true,
@ -130,11 +128,9 @@ describe('Component vnTreeview', () => {
describe('unfold()', () => {
it(`should unfold a parent item`, () => {
const expectedResponse = [{name: 'Item 1'}, {name: 'Item 2'}];
spyOn(controller, 'fetchFunc').and.returnValue(
new Promise(resolve => resolve(expectedResponse))
);
spyOn(controller, 'setParent');
spyOn(controller, 'sortFunc');
jest.spyOn(controller, 'fetchFunc');
jest.spyOn(controller, 'setParent');
jest.spyOn(controller, 'sortFunc');
const parent = {name: 'My item', sons: 1};
const child = {name: 'Item 1'};
child.parent = parent;
@ -157,7 +153,7 @@ describe('Component vnTreeview', () => {
view: window
});
spyOn(controller, 'removeFunc');
jest.spyOn(controller, 'removeFunc');
const item = {name: 'My item'};
controller.onRemove(event, item);
@ -187,7 +183,7 @@ describe('Component vnTreeview', () => {
view: window
});
spyOn(controller, 'createFunc');
jest.spyOn(controller, 'createFunc');
const parent = {name: 'My item'};
controller.onCreate(event, parent);
@ -197,8 +193,8 @@ describe('Component vnTreeview', () => {
describe('create()', () => {
it(`should unfold an inactive parent and then create a child`, () => {
spyOn(controller, 'unfold');
spyOn(controller, 'sortFunc');
jest.spyOn(controller, 'unfold');
jest.spyOn(controller, 'sortFunc');
const parent = {name: 'My item', sons: 2, childs: [
{name: 'Item 1'},
{name: 'Item 2'}
@ -216,8 +212,8 @@ describe('Component vnTreeview', () => {
});
it(`should create a child on an active parent`, () => {
spyOn(controller, 'unfold');
spyOn(controller, 'sortFunc');
jest.spyOn(controller, 'unfold');
jest.spyOn(controller, 'sortFunc');
const parent = {name: 'My item', sons: 2, childs: [
{name: 'Item 1'},
{name: 'Item 2'}
@ -236,9 +232,7 @@ describe('Component vnTreeview', () => {
describe('move()', () => {
it(`should move an item to anocher parent and then unfold the parent`, () => {
spyOn(controller, 'unfold').and.returnValue(
new Promise(resolve => resolve())
);
jest.spyOn(controller, 'unfold');
const newParent = {name: 'My item 2', sons: 0};
const parent = {name: 'My item', sons: 3, childs: [
{name: 'Item 1'},
@ -255,8 +249,8 @@ describe('Component vnTreeview', () => {
});
it(`should move an item to anocher parent`, () => {
spyOn(controller, 'unfold');
spyOn(controller, 'create');
jest.spyOn(controller, 'unfold');
jest.spyOn(controller, 'create');
const newParent = {name: 'My item 2', sons: 0, active: true};
const parent = {name: 'My item', sons: 3, childs: [
{name: 'Item 1'},

View File

@ -25,10 +25,10 @@ describe('Component vnWatcher', () => {
}));
describe('$onInit()', () => {
it(`should call fetchData() if controllers get and url properties are defined`, () => {
it('should call fetchData() if controllers get and url properties are defined', () => {
controller.get = () => {};
controller.url = 'test.com';
spyOn(controller, 'fetchData');
jest.spyOn(controller, 'fetchData').mockReturnThis();
controller.$onInit();
expect(controller.fetchData).toHaveBeenCalledWith();
@ -45,7 +45,7 @@ describe('Component vnWatcher', () => {
describe('fetchData()', () => {
it(`should perform a query then store the received data into controller.data and call updateOriginalData()`, () => {
spyOn(controller, 'updateOriginalData');
jest.spyOn(controller, 'updateOriginalData');
let json = {data: 'some data'};
controller.data = [1];
controller.idField = 0;
@ -61,9 +61,9 @@ describe('Component vnWatcher', () => {
});
describe('submitBack()', () => {
it(`should call controller.window.history.back() function after calling controllers submit() function`, done => {
spyOn(controller, 'submit').and.returnValue(Promise.resolve());
spyOn(controller.window.history, 'back');
it('should call controller.window.history.back() function after calling controllers submit() function', done => {
jest.spyOn(controller, 'submit').mockReturnValue(Promise.resolve());
jest.spyOn(controller.window.history, 'back');
controller.submitBack()
.then(() => {
expect(controller.submit).toHaveBeenCalledWith();
@ -74,9 +74,9 @@ describe('Component vnWatcher', () => {
});
describe('submitGo()', () => {
it(`should call controller.$state.go() function after calling controllers submit() function`, done => {
spyOn(controller, 'submit').and.returnValue(Promise.resolve());
spyOn(controller.$state, 'go');
it('should call controller.$state.go() function after calling controllers submit() function', done => {
jest.spyOn(controller, 'submit').mockReturnValue(Promise.resolve());
jest.spyOn(controller.$state, 'go');
let state = 'the.State';
controller.submitGo(state)
.then(() => {
@ -112,7 +112,7 @@ describe('Component vnWatcher', () => {
$setSubmitted: () => {},
$setPristine: () => {}
};
spyOn(controller.form, '$setSubmitted');
jest.spyOn(controller.form, '$setSubmitted');
controller.realSubmit();
expect(controller.form.$setSubmitted).toHaveBeenCalledWith();
@ -141,7 +141,7 @@ describe('Component vnWatcher', () => {
controller.idField = 'id';
controller.url = 'test.com';
let json = {data: 'some data'};
spyOn(controller, 'writeData').and.callThrough();
jest.spyOn(controller, 'writeData');
$httpBackend.whenPATCH(`${controller.url}/1`, changedData).respond(json);
$httpBackend.expectPATCH(`${controller.url}/1`);
controller.realSubmit()
@ -161,7 +161,7 @@ describe('Component vnWatcher', () => {
controller.orgData = {id: 1};
controller.url = 'test.com';
let json = {data: 'some data'};
spyOn(controller, 'writeData').and.callThrough();
jest.spyOn(controller, 'writeData');
$httpBackend.whenPOST(`${controller.url}`, controller.data).respond(json);
$httpBackend.expectPOST(`${controller.url}`, controller.data);
controller.realSubmit()
@ -175,7 +175,7 @@ describe('Component vnWatcher', () => {
describe('writeData()', () => {
it(`should call Object.asssign() function over controllers.data with json.data, then call updateOriginalData function and finally call resolve() function`, () => {
spyOn(controller, 'updateOriginalData');
jest.spyOn(controller, 'updateOriginalData');
controller.data = {};
let json = {data: 'some data'};
let resolve = jasmine.createSpy('resolve');

View File

@ -24,7 +24,7 @@ describe('Directive dialog', () => {
it('should call show() function if dialog is a instance of vnDialog', () => {
let html = `<div vn-dialog="myDialog"></div>`;
spyOn(controller, 'show');
jest.spyOn(controller, 'show');
compile(html);
element[0].click();

View File

@ -0,0 +1,25 @@
const popover = {
show: () => {
return {
then: callback => {
callback();
}
};
},
hide: () => {
return {
then: callback => {
callback();
}
};
},
relocate: () => {
return {
then: callback => {
callback();
}
};
}
};
module.exports = popover;

View File

@ -23,6 +23,12 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-net:before {
content: "\e95b";
}
.icon-anonymous:before {
content: "\e95c";
}
.icon-buyrequest:before {
content: "\e914";
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

@ -12,7 +12,7 @@ export default function moduleImport(moduleName) {
case 'ticket' : return import('ticket/front');
case 'order' : return import('order/front');
case 'claim' : return import('claim/front');
case 'agency' : return import('agency/front');
case 'zone' : return import('zone/front');
case 'travel' : return import('travel/front');
case 'worker' : return import('worker/front');
case 'invoiceOut' : return import('invoiceOut/front');

View File

@ -26,7 +26,7 @@ describe('Component vnLeftMenu', () => {
describe('depth() setter', () => {
it(`should set depth property and call activateItem()`, () => {
spyOn(controller, 'activateItem');
jest.spyOn(controller, 'activateItem');
controller.depth = 3;
expect(controller.depth).toEqual(3);

View File

@ -32,7 +32,7 @@ Remove: Quitar
# Modules
Agencies: Agencias
Zones: Zonas
Claims: Reclamaciones
Clients: Clientes
Items: Artículos

View File

@ -2,7 +2,7 @@ import 'angular';
import 'angular-mocks';
import core from './front/core/module.js';
import './front/salix/components/app/app.js';
import './modules/agency/front/module.js';
import './modules/zone/front/module.js';
import './modules/claim/front/module.js';
import './modules/client/front/module.js';
import './modules/invoiceOut/front/module.js';

View File

@ -1,16 +0,0 @@
vn-zone-delivery-days {
vn-zone-calendar {
display: flex;
justify-content: center;
flex-wrap: wrap;
& > vn-calendar {
min-width: 16.5em;
}
}
form {
display: flex;
flex-direction: column;
}
}

View File

@ -1,3 +0,0 @@
import {ng} from 'core/vendor';
export default ng.module('agency', ['vnCore']);

View File

@ -36,8 +36,8 @@ describe('claim', () => {
describe('openAddSalesDialog()', () => {
it('should call getClaimableFromTicket and $.addSales.show', () => {
controller.$ = {addSales: {show: () => {}}};
spyOn(controller, 'getClaimedSales');
spyOn(controller.$.addSales, 'show');
jest.spyOn(controller, 'getClaimedSales');
jest.spyOn(controller.$.addSales, 'show');
controller.openAddSalesDialog();
expect(controller.getClaimedSales).toHaveBeenCalledWith();
@ -58,9 +58,9 @@ describe('claim', () => {
describe('addClaimedSale(saleFk)', () => {
it('should make a post and call refresh, hide and showSuccess', () => {
spyOn(controller.$.model, 'refresh');
spyOn(controller.$.addSales, 'hide');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'refresh');
jest.spyOn(controller.$.addSales, 'hide');
jest.spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expectPOST(`ClaimEnds/`).respond({});
controller.addClaimedSale(1);
$httpBackend.flush();
@ -73,8 +73,8 @@ describe('claim', () => {
describe('deleteClaimedSale(id)', () => {
it('should make a delete and call refresh and showSuccess', () => {
spyOn(controller.$.model, 'refresh');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'refresh');
jest.spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expectDELETE(`ClaimEnds/1`).respond({});
controller.deleteClaimedSale(1);
$httpBackend.flush();
@ -99,8 +99,8 @@ describe('claim', () => {
describe('importToNewRefundTicket()', () => {
it('should perform a post query and add lines from a new ticket', () => {
spyOn(controller.$.model, 'refresh');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'refresh');
jest.spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expect('POST', `ClaimBeginnings/1/importToNewRefundTicket`).respond({});
controller.importToNewRefundTicket();
$httpBackend.flush();
@ -112,8 +112,8 @@ describe('claim', () => {
describe('showLastTickets()', () => {
it('should get a list of tickets and call lastTicketsPopover show() method', () => {
spyOn(controller.$.lastTicketsModel, 'refresh');
spyOn(controller.$.lastTicketsPopover, 'show');
jest.spyOn(controller.$.lastTicketsModel, 'refresh');
jest.spyOn(controller.$.lastTicketsPopover, 'show');
controller.showLastTickets({});
expect(controller.$.lastTicketsModel.refresh).toHaveBeenCalledWith();
@ -123,9 +123,9 @@ describe('claim', () => {
describe('importTicketLines()', () => {
it('should perform a post query and add lines from an existent ticket', () => {
spyOn(controller.$.model, 'refresh');
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.lastTicketsPopover, 'hide');
jest.spyOn(controller.$.model, 'refresh');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.lastTicketsPopover, 'hide');
let data = {claimFk: 1, ticketFk: 1};
$httpBackend.expect('POST', `ClaimEnds/importTicketSales`, data).respond({});
controller.importTicketLines(1);
@ -139,8 +139,8 @@ describe('claim', () => {
describe('regularize()', () => {
it('should perform a post query and reload the claim card', () => {
spyOn(controller.card, 'reload');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.card, 'reload');
jest.spyOn(controller.vnApp, 'showSuccess');
let data = {claimFk: $state.params.id};
$httpBackend.expect('POST', `Claims/regularizeClaim`, data).respond({});
@ -156,9 +156,9 @@ describe('claim', () => {
const greugeTypeId = 7;
const freightPickUpPrice = 11;
it('should do nothing', () => {
spyOn(controller.$http, 'post');
spyOn(controller.card, 'reload');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$http, 'post');
jest.spyOn(controller.card, 'reload');
jest.spyOn(controller.vnApp, 'showSuccess');
controller.onUpdateGreugeResponse('cancel');
@ -168,8 +168,8 @@ describe('claim', () => {
});
it('should make a query and get the greugeTypeId and greuge config', () => {
spyOn(controller.card, 'reload');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.card, 'reload');
jest.spyOn(controller.vnApp, 'showSuccess');
const greugeTypeParams = $httpParamSerializer({filter: {where: {code: 'freightPickUp'}}});
$httpBackend.expect('GET', `GreugeTypes/findOne?${greugeTypeParams}`).respond({id: greugeTypeId});
@ -183,13 +183,13 @@ describe('claim', () => {
// #1957 - Investigate how to test nested httpBackend requests
xit('should perform a insert into greuges', () => {
spyOn(controller.card, 'reload');
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.card, 'reload');
jest.spyOn(controller.vnApp, 'showSuccess');
spyOn(controller, 'getGreugeTypeId').and.returnValue(new Promise(resolve => {
jest.spyOn(controller, 'getGreugeTypeId').and.returnValue(new Promise(resolve => {
return resolve({id: greugeTypeId});
}));
spyOn(controller, 'getGreugeConfig').and.returnValue(new Promise(resolve => {
jest.spyOn(controller, 'getGreugeConfig').and.returnValue(new Promise(resolve => {
return resolve({freightPickUpPrice});
}));

View File

@ -17,7 +17,7 @@ describe('Claim', () => {
describe('onSubmit()', () => {
it(`should redirect to 'claim.card.detail' state`, () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('claim.card.detail');

View File

@ -22,7 +22,7 @@ describe('Item Component vnClaimDescriptor', () => {
};
const serializedParams = $httpParamSerializer(params);
let expectedPath = `api/report/claim-pickup-order?${serializedParams}`;
spyOn(window, 'open');
jest.spyOn(window, 'open').mockReturnThis();
controller.showPickupOrder();
expect(window.open).toHaveBeenCalledWith(expectedPath);
@ -43,7 +43,7 @@ describe('Item Component vnClaimDescriptor', () => {
describe('sendPickupOrder(response)', () => {
it('should make a query and call vnApp.showMessage() if the response is accept', () => {
spyOn(controller.vnApp, 'showMessage');
jest.spyOn(controller.vnApp, 'showMessage');
const params = {
recipient: 'client@email',
@ -78,8 +78,8 @@ describe('Item Component vnClaimDescriptor', () => {
let response = 'accept';
controller.claim = {id: 2};
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$state, 'go');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$state, 'go');
$httpBackend.when('DELETE', `Claims/2`).respond(200);
$httpBackend.expect('DELETE', `Claims/2`);
controller.deleteClaim(response);

View File

@ -37,8 +37,8 @@ describe('claim', () => {
describe('openAddSalesDialog()', () => {
it('should call getClaimableFromTicket and $.addSales.show', () => {
spyOn(controller, 'getClaimableFromTicket');
spyOn(controller.$.addSales, 'show');
jest.spyOn(controller, 'getClaimableFromTicket');
jest.spyOn(controller.$.addSales, 'show');
controller.openAddSalesDialog();
expect(controller.getClaimableFromTicket).toHaveBeenCalledWith();
@ -58,8 +58,8 @@ describe('claim', () => {
describe('addClaimedSale(index)', () => {
it('should make a post and call refresh, hide and showSuccess', () => {
spyOn(controller.$.addSales, 'hide');
spyOn(controller.$state, 'go');
jest.spyOn(controller.$.addSales, 'hide');
jest.spyOn(controller.$state, 'go');
$httpBackend.expectPOST(`ClaimBeginnings/`).respond({});
controller.addClaimedSale(1);
$httpBackend.flush();
@ -71,7 +71,7 @@ describe('claim', () => {
describe('deleteClaimedSale(index)', () => {
it('should make a delete and call refresh and showSuccess', () => {
spyOn(controller.$.model, 'remove');
jest.spyOn(controller.$.model, 'remove');
$httpBackend.expectDELETE(`ClaimBeginnings/1`).respond({});
controller.deleteClaimedSale(0);
$httpBackend.flush();
@ -82,7 +82,7 @@ describe('claim', () => {
describe('setClaimedQuantity(id, claimedQuantity)', () => {
it('should make a patch and call refresh and showSuccess', () => {
spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.vnApp, 'showSuccess');
$httpBackend.expectPATCH(`ClaimBeginnings/`).respond({});
controller.setClaimedQuantity(1, 1);
$httpBackend.flush();
@ -112,10 +112,10 @@ describe('claim', () => {
controller.newDiscount = 10;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller, 'calculateTotals');
spyOn(controller, 'clearDiscount');
spyOn(controller.$.editPopover, 'hide');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller, 'calculateTotals');
jest.spyOn(controller, 'clearDiscount');
jest.spyOn(controller.$.editPopover, 'hide');
$httpBackend.when('POST', 'Tickets/1/updateDiscount').respond({});
controller.updateDiscount();
@ -135,8 +135,8 @@ describe('claim', () => {
stopImmediatePropagation: () => {},
target: 'the target element'
};
spyOn(event, 'stopImmediatePropagation');
spyOn(controller.$.descriptor, 'show');
jest.spyOn(event, 'stopImmediatePropagation');
jest.spyOn(controller.$.descriptor, 'show');
controller.showItemDescriptor(event, itemId);

View File

@ -20,7 +20,7 @@ describe('Claim', () => {
describe('onSubmit()', () => {
it(`should redirect to 'claim.card.action' state`, () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('claim.card.action');

View File

@ -28,8 +28,8 @@ describe('Claim', () => {
it('should make an HTTP Post query', () => {
const dmsId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'remove');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'remove');
controller.photos = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;
@ -62,8 +62,8 @@ describe('Claim', () => {
it('should make an HTTP Post query, then refresh the model data', () => {
const claimId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'refresh');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'refresh');
controller.photos = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;
controller.dms = {files: []};

View File

@ -28,7 +28,7 @@ describe('Claim', () => {
describe('$onChanges()', () => {
it('should call getSummary when item.id is defined', () => {
spyOn(controller, 'getSummary');
jest.spyOn(controller, 'getSummary');
controller.$onChanges();
expect(controller.getSummary).toHaveBeenCalledWith();

View File

@ -22,7 +22,10 @@
"type": "Boolean"
},
"hasCompany": {
"type": "Number"
"type": "Boolean"
},
"hasPreview": {
"type": "Boolean"
}
},
"scopes": {

View File

@ -35,7 +35,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it('should perform a PATCH and not set value to defaultAddressFk property', () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.address.isDefaultAddress = false;
controller.onSubmit();
@ -44,7 +44,7 @@ describe('Client', () => {
});
it('should perform a PATCH and set a value to defaultAddressFk property', () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.address.isDefaultAddress = true;
controller.onSubmit();

View File

@ -36,8 +36,8 @@ describe('Client', () => {
describe('removeObservation()', () => {
it('should call $.watcher.setDirty() and $.model.remove(index)', () => {
spyOn(controller.$.watcher, 'setDirty');
spyOn(controller.$.model, 'remove');
jest.spyOn(controller.$.watcher, 'setDirty');
jest.spyOn(controller.$.model, 'remove');
controller.removeObservation(1);
expect(controller.$.model.remove).toHaveBeenCalledWith(1);
@ -47,7 +47,7 @@ describe('Client', () => {
describe('cancel()', () => {
it('should call goToIndex()', () => {
spyOn(controller, 'goToIndex');
jest.spyOn(controller, 'goToIndex');
controller.cancel();
expect(controller.goToIndex).toHaveBeenCalledWith();
@ -56,7 +56,7 @@ describe('Client', () => {
describe('goToIndex()', () => {
it('should call $state.go("client.card.address.index")', () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.goToIndex();
expect(controller.$state.go).toHaveBeenCalledWith('client.card.address.index');

View File

@ -22,7 +22,7 @@ describe('Client', () => {
describe('setDefault()', () => {
it('should perform a PATCH and set a value to defaultAddressFk property', () => {
spyOn(controller, 'sortAddresses');
jest.spyOn(controller, 'sortAddresses');
let address = {id: 1};
let data = {defaultAddressFk: address.id};
let expectedResult = {defaultAddressFk: address.id};

View File

@ -31,9 +31,9 @@ describe('Client', () => {
it('should apply the filters on he models and get the client balance', () => {
controller._companyId = 442;
controller.$stateParams.id = 101;
spyOn(controller, 'getBalances');
spyOn(controller.$.model, 'applyFilter').and.returnValue(Promise.resolve());
spyOn(controller.$.riskModel, 'applyFilter').and.returnValue(Promise.resolve());
jest.spyOn(controller, 'getBalances').mockReturnThis();
jest.spyOn(controller.$.model, 'applyFilter').mockReturnValue(Promise.resolve());
jest.spyOn(controller.$.riskModel, 'applyFilter').mockReturnValue(Promise.resolve());
controller.getData().then(() => {
expect(controller.$.model.applyFilter).toHaveBeenCalledWith(null, {'clientId': 101, 'companyId': 442});
@ -44,14 +44,8 @@ describe('Client', () => {
});
describe('company setter/getter', () => {
it('should return the company', () => {
controller.companyId = null;
expect(controller._companyId).toEqual(jasmine.any(Object));
});
it('should return the company and then call getData()', () => {
spyOn(controller, 'getData');
jest.spyOn(controller, 'getData').mockReturnThis();
controller.companyId = 442;
expect(controller._companyId).toEqual(442);
@ -70,7 +64,7 @@ describe('Client', () => {
describe('getBalances()', () => {
it('should return the total client balance amount', () => {
spyOn(controller, 'getCurrentBalance').and.callThrough();
jest.spyOn(controller, 'getCurrentBalance');
controller._companyId = 442;
controller.$.model = {data:
[{
@ -100,7 +94,7 @@ describe('Client', () => {
describe('balances() setter', () => {
it('should set the balances data and not call the getBalances() method', () => {
spyOn(controller, 'getBalances');
jest.spyOn(controller, 'getBalances');
controller.$.riskModel.data = null;
controller.balances = [{
id: 1,
@ -121,7 +115,7 @@ describe('Client', () => {
});
it('should set the balances data and then call the getBalances() method', () => {
spyOn(controller, 'getBalances');
jest.spyOn(controller, 'getBalances').mockReturnThis();
controller.balances = [{
id: 1,
debit: 1000,

View File

@ -15,7 +15,7 @@ describe('Client', () => {
vnApp = _vnApp_;
$scope = $rootScope.$new();
$scope.watcher = {};
spyOn(vnApp, 'showError');
jest.spyOn(vnApp, 'showError');
controller = $componentController('vnClientBillingData', {$element, $scope});
controller.client = {id: 101, name: 'Client name', payMethodFk: 4};
$scope.watcher.orgData = {id: 101, name: 'Client name', payMethodFk: 4};

View File

@ -33,7 +33,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it(`should call submit() on the watcher then expect a callback`, () => {
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('client.card.basicData', {id: '1234'});

View File

@ -60,7 +60,7 @@ describe('Client', () => {
describe('closeContract()', () => {
it('should define the classificationId property of the controller and then call the show method()', () => {
controller.$scope.closeContract = {show: () => {}};
spyOn(controller.$scope.closeContract, 'show');
jest.spyOn(controller.$scope.closeContract, 'show');
expect(controller.classificationId).toBeFalsy();
controller.closeContract({id: 1});
@ -72,7 +72,7 @@ describe('Client', () => {
describe('returnDialog()', () => {
it('should call the returnDialog method and perform a PATCH query, then call _getClassifications method', () => {
spyOn(controller, '_getClassifications');
jest.spyOn(controller, '_getClassifications').mockReturnThis();
controller.classificationId = 1;
$httpBackend.when('PATCH', `CreditClassifications/1`).respond(200);
$httpBackend.expect('PATCH', `CreditClassifications/1`);

View File

@ -42,7 +42,7 @@ describe('Client', () => {
});
it('should call show() method when the client have a recovery', () => {
spyOn(controller.$scope.confirmation, 'show');
jest.spyOn(controller.$scope.confirmation, 'show');
$httpBackend.whenGET(`Recoveries/101/hasActiveRecovery`).respond(true);
$httpBackend.expectGET(`Recoveries/101/hasActiveRecovery`);
controller.onSubmit();
@ -52,7 +52,7 @@ describe('Client', () => {
});
it('should call addCredit() method when the client doesnt have a recovery', () => {
spyOn(controller, 'addCredit');
jest.spyOn(controller, 'addCredit');
$httpBackend.whenGET(`Recoveries/101/hasActiveRecovery`).respond(false);
$httpBackend.expectGET(`Recoveries/101/hasActiveRecovery`);
controller.onSubmit();
@ -64,7 +64,7 @@ describe('Client', () => {
describe('cancel()', () => {
it('should call goToIndex()', () => {
spyOn(controller, 'goToIndex');
jest.spyOn(controller, 'goToIndex');
controller.cancel();
expect(controller.goToIndex).toHaveBeenCalledWith();
@ -73,7 +73,7 @@ describe('Client', () => {
describe('returnDialog()', () => {
it('should call addCredit() when is called with accept', () => {
spyOn(controller, 'addCredit');
jest.spyOn(controller, 'addCredit');
controller.returnDialog('accept');
expect(controller.addCredit).toHaveBeenCalledWith();
@ -82,7 +82,7 @@ describe('Client', () => {
describe('addCredit()', () => {
it('should call the function go() on $state to go to the credit list', () => {
spyOn($state, 'go');
jest.spyOn($state, 'go');
client.credit = 1;
controller.addCredit();

View File

@ -23,7 +23,7 @@ describe('Client', () => {
it(`should not apply any changes if the received id is the same stored in _clientFk`, () => {
controller.client = 'I exist!';
controller._clientFk = 1;
spyOn(controller, 'getCard');
jest.spyOn(controller, 'getCard');
controller.clientFk = 1;
expect(controller.client).toEqual('I exist!');
@ -34,7 +34,7 @@ describe('Client', () => {
it(`should set the received id into _clientFk, set the client to null and then call getCard()`, () => {
controller.client = `Please don't`;
controller._clientFk = 1;
spyOn(controller, 'getCard');
jest.spyOn(controller, 'getCard');
controller.clientFk = 999;
expect(controller.client).toBeNull();
@ -45,7 +45,7 @@ describe('Client', () => {
describe('client()', () => {
it(`should save the client into _client and then call relocate()`, () => {
spyOn(controller.$.popover, 'relocate');
jest.spyOn(controller.$.popover, 'relocate');
controller.client = `i'm the client!`;
$timeout.flush();
@ -56,7 +56,7 @@ describe('Client', () => {
describe('show()', () => {
it(`should call the show()`, () => {
spyOn(controller.$.popover, 'show');
jest.spyOn(controller.$.popover, 'show');
controller.show();
expect(controller.$.popover.show).toHaveBeenCalledWith();

View File

@ -77,18 +77,15 @@
<tpl-body>
<div>
<h5 style="text-align: center">
<span translate>From date</span>
<span translate>Send consumer report</span>
</h5>
<vn-date-picker
vn-id="from"
vn-one
ng-model="$ctrl.from"
label="From hour"
label="From date"
vn-focus>
</vn-date-picker>
<h5 style="text-align: center">
<span translate>To date</span>
</h5>
<vn-date-picker
vn-id="to"
vn-one

View File

@ -1,2 +1,4 @@
Simple ticket: Ticket simple
Send consumer report: Enviar informe de consumo
From date: Fecha desde
To date: Fecha hasta

View File

@ -19,8 +19,8 @@ describe('Client', () => {
describe('client() setter', () => {
it('should set the client data and then call setDefaultParams() and getAllowedContentTypes()', () => {
spyOn(controller, 'setDefaultParams');
spyOn(controller, 'getAllowedContentTypes');
jest.spyOn(controller, 'setDefaultParams');
jest.spyOn(controller, 'getAllowedContentTypes');
controller.client = {
id: 15,
name: 'Bruce wayne'

View File

@ -19,8 +19,8 @@ describe('Client', () => {
describe('client() setter', () => {
it('should set the client data and then call setDefaultParams() and getAllowedContentTypes()', () => {
spyOn(controller, 'setDefaultParams');
spyOn(controller, 'getAllowedContentTypes');
jest.spyOn(controller, 'setDefaultParams');
jest.spyOn(controller, 'getAllowedContentTypes');
controller._client = undefined;
controller.client = {
id: 15

View File

@ -22,8 +22,8 @@ describe('Client', () => {
it('should make an HTTP Post query', () => {
const dmsId = 1;
const dmsIndex = 0;
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$.model, 'remove');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$.model, 'remove');
controller.clientDms = [{dmsFk: 1}];
controller.dmsIndex = dmsIndex;

View File

@ -24,14 +24,15 @@ export default class Controller extends Component {
const filter = encodeURIComponent(JSON.stringify(filterObj));
const query = `Clients/findOne?filter=${filter}`;
this.$http.get(query).then(res => {
if (res.data.id) {
const params = {clientId: res.data.id};
const question = $t('Found a client with this phone or email', params, null, null, 'sanitizeParameters');
this.client.despiteOfClient = params.clientId;
this.$.confirmDuplicatedClient.question = question;
this.$.confirmDuplicatedClient.show();
}
}).catch(error => {
if (error.status == 404)
this.save();
});
}

View File

@ -29,7 +29,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it('should call the save() method directly', () => {
spyOn(controller, 'save');
jest.spyOn(controller, 'save');
controller.onSubmit();
@ -37,8 +37,8 @@ describe('Client', () => {
});
it('should call the checkExistingClient() if the isTaxDataChecked property is checked', () => {
spyOn(controller, 'save');
spyOn(controller, 'checkExistingClient');
jest.spyOn(controller, 'save');
jest.spyOn(controller, 'checkExistingClient');
controller.client.isTaxDataChecked = true;
controller.onSubmit();
@ -51,7 +51,7 @@ describe('Client', () => {
describe('checkExistingClient()', () => {
it('should show a save confirmation when a duplicated client is found and then set the despiteOfClient property', () => {
controller.$.confirmDuplicatedClient = {show: () => {}};
spyOn(controller.$.confirmDuplicatedClient, 'show');
jest.spyOn(controller.$.confirmDuplicatedClient, 'show');
const filterObj = {
where: {
and: [
@ -74,7 +74,7 @@ describe('Client', () => {
describe('checkEtChanges()', () => {
it(`should show a propagation confirmation if isEqualizated property is changed and invoice by address is checked`, () => {
controller.$.propagateIsEqualizated = {show: () => {}};
spyOn(controller.$.propagateIsEqualizated, 'show');
jest.spyOn(controller.$.propagateIsEqualizated, 'show');
const orgData = $scope.watcher.orgData;
orgData.hasToInvoiceByAddress = true;
@ -86,7 +86,7 @@ describe('Client', () => {
});
it(`should call to the onAcceptEt() method if isEqualizated property is changed and invoice by address isn't checked`, () => {
spyOn(controller, 'onAcceptEt');
jest.spyOn(controller, 'onAcceptEt');
const orgData = $scope.watcher.orgData;
orgData.hasToInvoiceByAddress = false;

View File

@ -27,7 +27,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it('should call the function go() on $state to go to the greuges list', () => {
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('client.card.greuge.index');

View File

@ -15,7 +15,7 @@ describe('Client index', () => {
it('should navigate to the ticket index using params as filter', () => {
const client = {id: 101};
const event = new MouseEvent('click', {cancelable: true});
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller.filterTickets(client, event);

View File

@ -20,7 +20,7 @@ describe('Client', () => {
let params = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
controller.data = {townFk: 1, provinceFk: 1, countryFk: 1, code: '46460'};
spyOn(controller.vnApp, 'showMessage');
jest.spyOn(controller.vnApp, 'showMessage');
$httpBackend.when('PATCH', `postcodes`, params).respond(200, params);
$httpBackend.expect('PATCH', `postcodes`, params).respond(params);

View File

@ -27,7 +27,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it('should call the function go() on $state to go to the recovery list', () => {
spyOn($state, 'go');
jest.spyOn($state, 'go');
controller.onSubmit();
expect(controller.$state.go).toHaveBeenCalledWith('client.card.recovery.index');

View File

@ -23,7 +23,7 @@
<vn-autocomplete vn-one vn-id="sampleType"
ng-model="$ctrl.clientSample.typeFk"
model="ClientSample.typeFk"
fields="['code','hasCompany']"
fields="['code','hasCompany', 'hasPreview']"
url="Samples/visible"
show-field="description"
value-field="id"
@ -31,7 +31,7 @@
</vn-autocomplete>
<vn-autocomplete vn-one
ng-model="$ctrl.companyId"
model="ClientSample.companyId"
model="ClientSample.companyFk"
data="companiesData"
show-field="code"
value-field="id"
@ -42,7 +42,10 @@
</vn-card>
<vn-button-bar>
<vn-submit label="Send"></vn-submit>
<vn-button label="Preview" ng-click="$ctrl.showPreview()"></vn-button>
<vn-button ng-if="sampleType.selection.hasPreview"
label="Preview"
ng-click="$ctrl.showPreview()">
</vn-button>
<vn-button ui-sref="client.card.sample.index" label="Cancel"></vn-button>
</vn-button-bar>
</form>

View File

@ -26,13 +26,13 @@ class Controller extends Component {
}
get companyId() {
if (!this.clientSample.companyId)
this.clientSample.companyId = this.vnConfig.companyFk;
return this.clientSample.companyId;
if (!this.clientSample.companyFk)
this.clientSample.companyFk = this.vnConfig.companyFk;
return this.clientSample.companyFk;
}
set companyId(value) {
this.clientSample.companyId = value;
this.clientSample.companyFk = value;
}
onSubmit() {
@ -74,11 +74,11 @@ class Controller extends Component {
if (!sampleType)
return this.vnApp.showError(this.$translate.instant('Choose a sample'));
if (sampleType.hasCompany && !this.clientSample.companyId)
if (sampleType.hasCompany && !this.clientSample.companyFk)
return this.vnApp.showError(this.$translate.instant('Choose a company'));
if (sampleType.hasCompany)
params.companyId = this.clientSample.companyId;
params.companyId = this.clientSample.companyFk;
if (isPreview) params.isPreview = true;

View File

@ -52,7 +52,7 @@ describe('Client', () => {
describe('onSubmit()', () => {
it(`should call sendSample() method`, () => {
spyOn(controller, 'sendSample');
jest.spyOn(controller, 'sendSample');
controller.onSubmit();
expect(controller.sendSample).toHaveBeenCalledWith();
@ -61,7 +61,7 @@ describe('Client', () => {
describe('send()', () => {
it(`should not perform an HTTP query if no recipient is specified`, () => {
spyOn(controller.$http, 'get');
jest.spyOn(controller.$http, 'get');
controller.$.sampleType.selection = {
hasCompany: false,
@ -77,7 +77,7 @@ describe('Client', () => {
});
it(`should not perform an HTTP query if no sample is specified`, () => {
spyOn(controller.$http, 'get');
jest.spyOn(controller.$http, 'get');
controller.$.sampleType.selection = null;
controller.clientSample = {
@ -91,7 +91,7 @@ describe('Client', () => {
});
it(`should not perform an HTTP query if company is required and not specified`, () => {
spyOn(controller.$http, 'get');
jest.spyOn(controller.$http, 'get');
controller.$.sampleType.selection = {
hasCompany: true,
@ -107,7 +107,7 @@ describe('Client', () => {
expect(controller.$http.get).not.toHaveBeenCalled();
});
it(`should perform an HTTP query without passing companyId param`, () => {
it(`should perform an HTTP query without passing companyFk param`, () => {
controller.$.sampleType.selection = {
hasCompany: false,
code: 'MyReport'
@ -116,25 +116,34 @@ describe('Client', () => {
clientId: 101,
recipient: 'client@email.com'
};
const expectedParams = {
clientId: 101,
recipient: 'client@email.com'
};
const serializedParams = $httpParamSerializer(expectedParams);
const serializedParams = $httpParamSerializer(controller.clientSample);
$httpBackend.expect('GET', `email/MyReport?${serializedParams}`).respond(true);
controller.send(false, () => {});
$httpBackend.flush();
});
it(`should perform an HTTP query passing companyId param`, () => {
it(`should perform an HTTP query passing companyFk param`, () => {
controller.$.sampleType.selection = {
hasCompany: true,
code: 'MyReport'
};
controller.clientSample = {
clientId: 101,
recipient: 'client@email.com',
companyFk: 442
};
const expectedParams = {
clientId: 101,
recipient: 'client@email.com',
companyId: 442
};
const serializedParams = $httpParamSerializer(expectedParams);
const serializedParams = $httpParamSerializer(controller.clientSample);
$httpBackend.expect('GET', `email/MyReport?${serializedParams}`).respond(true);
controller.send(false, () => {});
$httpBackend.flush();
@ -143,7 +152,7 @@ describe('Client', () => {
describe('showPreview()', () => {
it(`should open a sample preview`, () => {
spyOn(controller.$.showPreview, 'show');
jest.spyOn(controller.$.showPreview, 'show');
controller.send = (isPreview, cb) => {
cb({
@ -158,7 +167,7 @@ describe('Client', () => {
describe('sendSample()', () => {
it(`should perform a query (GET) and call go() method`, () => {
spyOn(controller.$state, 'go');
jest.spyOn(controller.$state, 'go');
controller.send = (isPreview, cb) => {
cb({

View File

@ -27,7 +27,7 @@ describe('Client', () => {
let params = {destinationFk: 101, destination: 111111111, message: 'My SMS'};
controller.sms = {destinationFk: 101, destination: 111111111, message: 'My SMS'};
spyOn(controller.vnApp, 'showMessage');
jest.spyOn(controller.vnApp, 'showMessage');
$httpBackend.expect('POST', `Clients/101/sendSms`, params).respond(200, params);
controller.onResponse('accept');
@ -39,7 +39,7 @@ describe('Client', () => {
it('should call onResponse without the destination and show an error snackbar', () => {
controller.sms = {destinationFk: 101, message: 'My SMS'};
spyOn(controller.vnApp, 'showError');
jest.spyOn(controller.vnApp, 'showError');
controller.onResponse('accept');
@ -49,7 +49,7 @@ describe('Client', () => {
it('should call onResponse without the message and show an error snackbar', () => {
controller.sms = {destinationFk: 101, destination: 222222222};
spyOn(controller.vnApp, 'showError');
jest.spyOn(controller.vnApp, 'showError');
controller.onResponse('accept');

View File

@ -14,10 +14,10 @@ describe('Client', () => {
}));
describe('$onChanges()', () => {
it('should perform a GET query and define summary property', () => {
it('should perform a GET query and then define the summary property', () => {
let res = {name: 'Superman', classifications: []};
spyOn(controller, 'sumRisk');
jest.spyOn(controller, 'sumRisk').mockReturnThis();
$httpBackend.when('GET', `Clients/101/summary`).respond(200, res);
$httpBackend.expect('GET', `Clients/101/summary`);

View File

@ -12,13 +12,13 @@ describe('Component VnClientWebAccess', () => {
$scope = $rootScope.$new();
$httpBackend = _$httpBackend_;
vnApp = _vnApp_;
spyOn(vnApp, 'showError');
jest.spyOn(vnApp, 'showError');
controller = $componentController('vnClientWebAccess', {$scope});
}));
describe('$onChanges()', () => {
it(`should pass client's account data to account then call isCustomer function`, () => {
spyOn(controller, 'isCustomer');
jest.spyOn(controller, 'isCustomer');
controller.client = {client: 'Bruce Wayne', account: 'Wayne Industries'};
controller.account = {};
controller.$onChanges();

View File

@ -14,7 +14,7 @@ describe('Component vnClientWebPayment', () => {
$scope.model = crudModel;
$httpBackend = _$httpBackend_;
vnApp = _vnApp_;
spyOn(vnApp, 'showError');
jest.spyOn(vnApp, 'showError');
controller = $componentController('vnClientWebPayment', {$scope: $scope});
}));

View File

@ -68,6 +68,14 @@ module.exports = Self => {
type: 'Number',
description: 'The currency id to filter',
http: {source: 'query'}
}, {
arg: 'from',
type: 'Date',
description: `The from date filter`
}, {
arg: 'to',
type: 'Date',
description: `The to date filter`
}
],
returns: {
@ -91,6 +99,10 @@ module.exports = Self => {
return {[param]: {like: `%${value}%`}};
case 'created':
return {'e.created': {gte: value}};
case 'from':
return {'t.landed': {gte: value}};
case 'to':
return {'t.landed': {lte: value}};
case 'id':
case 'isBooked':
case 'isConfirmed':

View File

@ -0,0 +1,76 @@
module.exports = Self => {
Self.remoteMethod('getEntry', {
description: 'Returns an entry',
accessType: 'READ',
accepts: {
arg: 'id',
type: 'number',
required: true,
description: 'The entry id',
http: {source: 'path'}
},
returns: {
type: 'object',
root: true
},
http: {
path: `/:id/getEntry`,
verb: 'GET'
}
});
Self.getEntry = async id => {
let filter = {
where: {id: id},
include: [
{
relation: 'supplier',
scope: {
fields: ['id', 'nickname']
}
},
{
relation: 'travel',
scope: {
fields: ['id', 'name', 'shipped', 'landed', 'agencyFk', 'warehouseOutFk', 'warehouseInFk'],
include: [
{
relation: 'agency',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseOut',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseIn',
scope: {
fields: ['name']
}
}
]
}
},
{
relation: 'currency',
scope: {
fields: ['id', 'name']
}
},
{
relation: 'company',
scope: {
fields: ['id', 'code']
}
}
],
};
let entry = await Self.app.models.Entry.findOne(filter);
return entry;
};
};

View File

@ -0,0 +1,31 @@
const app = require('vn-loopback/server/server');
describe('travel getEntry()', () => {
const entryId = 1;
it('should check the entry contains the id', async() => {
const entry = await app.models.Entry.getEntry(entryId);
expect(entry.id).toEqual(entryId);
});
it('should check the entry contains the supplier name', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const supplierName = entry.supplier().nickname;
expect(supplierName).toEqual('Plants nick');
});
it('should check the entry contains the receiver warehouse name', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const receiverWarehouseName = entry.travel().warehouseIn().name;
expect(receiverWarehouseName).toEqual('Warehouse One');
});
it('should check the entry contains the company code', async() => {
const entry = await app.models.Entry.getEntry(entryId);
const companyCode = entry.company().code;
expect(companyCode).toEqual('VNL');
});
});

View File

@ -1,4 +1,5 @@
module.exports = Self => {
require('../methods/entry/filter')(Self);
require('../methods/entry/getEntry')(Self);
};

View File

@ -39,6 +39,9 @@
"commission": {
"type": "Number"
},
"isOrdered": {
"type": "Boolean"
},
"created": {
"type": "date"
},

View File

@ -11,11 +11,34 @@ class Controller extends ModuleCard {
fields: ['id', 'code']
}
}, {
relation: 'travel'
relation: 'travel',
scope: {
fields: ['id', 'landed', 'agencyFk', 'warehouseOutFk'],
include: [
{
relation: 'agency',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseOut',
scope: {
fields: ['name']
}
},
{
relation: 'warehouseIn',
scope: {
fields: ['name']
}
}
]
}
}, {
relation: 'supplier',
scope: {
fields: ['id', 'name']
fields: ['id', 'nickname']
}
}, {
relation: 'currency'

View File

@ -6,16 +6,37 @@
<a translate-attr="{title: 'Preview'}" ui-sref="entry.card.summary({id: $ctrl.entry.id})">
<vn-icon icon="desktop_windows"></vn-icon>
</a>
<span></span>
<vn-icon-menu
vn-id="more-button"
icon="more_vert"
show-filter="false"
value-field="callback"
translate-fields="['name']"
data="$ctrl.moreOptions"
on-change="$ctrl.onMoreChange(value)"
on-open="$ctrl.onMoreOpen()">
</vn-icon-menu>
</div>
<div class="body">
<div class="attributes">
<vn-label-value label="Id"
value="{{$ctrl.entry.id}}">
</vn-label-value>
<vn-label-value label="Reference"
value="{{$ctrl.entry.ref}}">
<vn-label-value label="Supplier"
value="{{$ctrl.entry.supplier.nickname}}">
</vn-label-value>
<vn-label-value label="Agency "
value="{{$ctrl.entry.travel.agency.name}}">
</vn-label-value>
<vn-label-value label="Landed"
value="{{$ctrl.entry.travel.landed | date: 'dd/MM/yyyy'}}">
</vn-label-value>
<vn-label-value label="Warehouse Out"
value="{{$ctrl.entry.travel.warehouseOut.name}}">
</vn-label-value>
</div>
<vn-quick-links
links="$ctrl.quicklinks">
</vn-quick-links>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More