Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2322-order_index
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
This commit is contained in:
commit
7c72cd8f2d
|
@ -13,8 +13,15 @@ Required applications.
|
||||||
|
|
||||||
You will need to install globally the following items.
|
You will need to install globally the following items.
|
||||||
```
|
```
|
||||||
# sudo npm install -g jest gulp-cli
|
$ sudo npm install -g jest gulp-cli
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For the usage of jest --watch on macOs.
|
||||||
|
```
|
||||||
|
$ brew install watchman
|
||||||
|
```
|
||||||
|
* [watchman](https://facebook.github.io/watchman/)
|
||||||
|
|
||||||
## Linux Only Prerequisites
|
## Linux Only Prerequisites
|
||||||
|
|
||||||
Your user must be on the docker group to use it so you will need to run this command:
|
Your user must be on the docker group to use it so you will need to run this command:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
describe('Component vnField', () => {
|
describe('Component vnField', () => {
|
||||||
let $element;
|
|
||||||
let controller;
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
beforeEach(ngModule('vnCore'));
|
beforeEach(ngModule('vnCore'));
|
||||||
|
|
||||||
|
@ -13,12 +13,84 @@ describe('Component vnField', () => {
|
||||||
$element.remove();
|
$element.remove();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove this block
|
describe('field get/set', () => {
|
||||||
describe('clearDisabled binding', () => {
|
it('should do nothing when trying to set the same value again', () => {
|
||||||
it(`should enable the show property`, () => {
|
controller.field = '';
|
||||||
controller.clearDisabled = true;
|
jest.spyOn(controller, 'validateValue');
|
||||||
|
|
||||||
expect(controller.clearDisabled).toEqual(true);
|
controller.field = '';
|
||||||
|
|
||||||
|
expect(controller.validateValue).toHaveBeenCalledTimes(0);
|
||||||
|
expect(controller.classList).not.toContain('not-empty');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the class no empty and then call validateValue()', () => {
|
||||||
|
controller.field = '';
|
||||||
|
jest.spyOn(controller, 'validateValue');
|
||||||
|
|
||||||
|
controller.field = 'someField';
|
||||||
|
|
||||||
|
expect(controller.validateValue).toHaveBeenCalledTimes(1);
|
||||||
|
expect(controller.classList).toContain('not-empty');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('refreshHint()', () => {
|
||||||
|
it('should add the class invalid if there is an error in the controller', () => {
|
||||||
|
controller._error = true;
|
||||||
|
|
||||||
|
controller.refreshHint();
|
||||||
|
|
||||||
|
expect(controller.classList).toContain('invalid');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onFocus()', () => {
|
||||||
|
it('should add the class focus', () => {
|
||||||
|
controller.onFocus(true);
|
||||||
|
|
||||||
|
expect(controller.classList).toContain('focused');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add the class focus', () => {
|
||||||
|
controller.onFocus(false);
|
||||||
|
|
||||||
|
expect(controller.classList).not.toContain('focuses');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('buildInput()', () => {
|
||||||
|
it('should build an input based on the received type', () => {
|
||||||
|
controller.buildInput('number');
|
||||||
|
|
||||||
|
expect(controller.input.tagName).toEqual('INPUT');
|
||||||
|
expect(controller.input.type).toEqual('number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateValue()', () => {
|
||||||
|
it('should do nothing if there is no new error to show', () => {
|
||||||
|
jest.spyOn(controller, 'refreshHint');
|
||||||
|
controller.inputError = 'old validation message';
|
||||||
|
controller.buildInput('number');
|
||||||
|
controller.input.setCustomValidity('old validation message');
|
||||||
|
|
||||||
|
controller.validateValue();
|
||||||
|
|
||||||
|
expect(controller.refreshHint).not.toHaveBeenCalled();
|
||||||
|
expect(controller.inputError).toEqual('old validation message');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update the input error and call refreshHint', () => {
|
||||||
|
jest.spyOn(controller, 'refreshHint');
|
||||||
|
controller.inputError = 'OLD validation message';
|
||||||
|
controller.buildInput('number');
|
||||||
|
controller.input.setCustomValidity('NEW validation message');
|
||||||
|
|
||||||
|
controller.validateValue();
|
||||||
|
|
||||||
|
expect(controller.refreshHint).toHaveBeenCalled();
|
||||||
|
expect(controller.inputError).toEqual('NEW validation message');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,7 +9,7 @@ class Controller extends Descriptor {
|
||||||
set entity(value) {
|
set entity(value) {
|
||||||
super.entity = value;
|
super.entity = value;
|
||||||
|
|
||||||
if (this.$params.sendSMS)
|
if (value && this.$params.sendSMS)
|
||||||
this.showSMSDialog();
|
this.showSMSDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
returns: {
|
returns: {
|
||||||
type: 'string',
|
type: 'Object',
|
||||||
root: true
|
root: true
|
||||||
},
|
},
|
||||||
http: {
|
http: {
|
||||||
|
@ -53,6 +53,6 @@ module.exports = Self => {
|
||||||
if (!isAllowed)
|
if (!isAllowed)
|
||||||
throw new UserError(`You don't have enough privileges`, 'ACCESS_DENIED');
|
throw new UserError(`You don't have enough privileges`, 'ACCESS_DENIED');
|
||||||
|
|
||||||
return await models.TicketTracking.create(params);
|
return models.TicketTracking.create(params);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
module.exports = Self => {
|
||||||
|
Self.remoteMethodCtx('setDelivered', {
|
||||||
|
description: 'Changes the state of the received ticket ids to delivered',
|
||||||
|
accessType: 'WRITE',
|
||||||
|
accepts: [
|
||||||
|
{
|
||||||
|
arg: 'ticketIds',
|
||||||
|
description: 'the array of ticket ids to set as delivered',
|
||||||
|
type: ['Number'],
|
||||||
|
required: true,
|
||||||
|
http: {source: 'body'}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
returns: {
|
||||||
|
type: 'Object',
|
||||||
|
root: true
|
||||||
|
},
|
||||||
|
http: {
|
||||||
|
path: `/setDelivered`,
|
||||||
|
verb: 'POST'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Self.setDelivered = async(ctx, ticketIds) => {
|
||||||
|
let userId = ctx.req.accessToken.userId;
|
||||||
|
let models = Self.app.models;
|
||||||
|
|
||||||
|
let state = await models.State.findOne({
|
||||||
|
where: {
|
||||||
|
code: 'delivered'
|
||||||
|
},
|
||||||
|
fields: ['id', 'name', 'alertLevel', 'code']
|
||||||
|
});
|
||||||
|
|
||||||
|
let worker = await models.Worker.findOne({where: {userFk: userId}});
|
||||||
|
|
||||||
|
let promises = [];
|
||||||
|
for (let id of ticketIds) {
|
||||||
|
let promise = models.TicketTracking.changeState(ctx, {
|
||||||
|
stateFk: state.id,
|
||||||
|
workerFk: worker.id,
|
||||||
|
ticketFk: id
|
||||||
|
});
|
||||||
|
promises.push(promise);
|
||||||
|
}
|
||||||
|
await Promise.all(promises);
|
||||||
|
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
};
|
|
@ -0,0 +1,36 @@
|
||||||
|
const app = require('vn-loopback/server/server');
|
||||||
|
|
||||||
|
describe('ticket setDelivered()', () => {
|
||||||
|
let ticketOne;
|
||||||
|
let ticketTwo;
|
||||||
|
|
||||||
|
beforeAll(async done => {
|
||||||
|
let originalTicketOne = await app.models.Ticket.findById(8);
|
||||||
|
let originalTicketTwo = await app.models.Ticket.findById(10);
|
||||||
|
|
||||||
|
originalTicketOne.id = null;
|
||||||
|
originalTicketTwo.id = null;
|
||||||
|
ticketOne = await app.models.Ticket.create(originalTicketOne);
|
||||||
|
ticketTwo = await app.models.Ticket.create(originalTicketTwo);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async done => {
|
||||||
|
await app.models.Ticket.destroyById(ticketOne.id);
|
||||||
|
await app.models.Ticket.destroyById(ticketTwo.id);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the state which has been applied to the given tickets', async() => {
|
||||||
|
let ctx = {req: {accessToken: {userId: 49}}};
|
||||||
|
let delivered = await app.models.State.findOne({where: {code: 'delivered'}, fields: ['id']});
|
||||||
|
|
||||||
|
let params = [ticketOne.id, ticketTwo.id];
|
||||||
|
let state = await app.models.TicketTracking.setDelivered(ctx, params);
|
||||||
|
|
||||||
|
expect(state.id).toEqual(delivered.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module.exports = function(Self) {
|
module.exports = function(Self) {
|
||||||
require('../methods/ticket-tracking/changeState')(Self);
|
require('../methods/ticket-tracking/changeState')(Self);
|
||||||
|
require('../methods/ticket-tracking/setDelivered')(Self);
|
||||||
|
|
||||||
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
Self.validatesPresenceOf('stateFk', {message: 'State cannot be blank'});
|
||||||
Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'});
|
Self.validatesPresenceOf('workerFk', {message: 'Worker cannot be blank'});
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="addTurn.show()"
|
ng-click="addTurn.show()"
|
||||||
vn-acl="buyer"
|
vn-acl="buyer"
|
||||||
|
ng-show="$ctrl.isEditable"
|
||||||
vn-acl-action="remove"
|
vn-acl-action="remove"
|
||||||
name="addTurn"
|
name="addTurn"
|
||||||
translate>
|
translate>
|
||||||
|
@ -60,7 +61,7 @@
|
||||||
</vn-item>
|
</vn-item>
|
||||||
<vn-item
|
<vn-item
|
||||||
ng-click="makeInvoiceConfirmation.show()"
|
ng-click="makeInvoiceConfirmation.show()"
|
||||||
ng-show="!$ctrl.isInvoiced"
|
ng-show="$ctrl.isEditable"
|
||||||
vn-acl="invoicing"
|
vn-acl="invoicing"
|
||||||
vn-acl-action="remove"
|
vn-acl-action="remove"
|
||||||
name="makeInvoice"
|
name="makeInvoice"
|
||||||
|
|
|
@ -8,6 +8,7 @@ class Controller extends Descriptor {
|
||||||
|
|
||||||
set ticket(value) {
|
set ticket(value) {
|
||||||
this.entity = value;
|
this.entity = value;
|
||||||
|
this.isTicketEditable();
|
||||||
}
|
}
|
||||||
|
|
||||||
get entity() {
|
get entity() {
|
||||||
|
@ -22,14 +23,6 @@ class Controller extends Descriptor {
|
||||||
this.showSMSDialog();
|
this.showSMSDialog();
|
||||||
}
|
}
|
||||||
|
|
||||||
get isEditable() {
|
|
||||||
try {
|
|
||||||
return !this.ticket.tracking.state.alertLevel;
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isInvoiced() {
|
get isInvoiced() {
|
||||||
return this.ticket.refFk !== null;
|
return this.ticket.refFk !== null;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +38,12 @@ class Controller extends Descriptor {
|
||||||
return this.ticket.stowaway || this.ticket.ship;
|
return this.ticket.stowaway || this.ticket.ship;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isTicketEditable() {
|
||||||
|
this.$http.get(`Tickets/${this.$state.params.id}/isEditable`).then(res => {
|
||||||
|
this.isEditable = res.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
showChangeShipped() {
|
showChangeShipped() {
|
||||||
this.newShipped = this.ticket.shipped;
|
this.newShipped = this.ticket.shipped;
|
||||||
this.$.changeShippedDialog.show();
|
this.$.changeShippedDialog.show();
|
||||||
|
|
|
@ -28,8 +28,10 @@ describe('Ticket Component vnTicketDescriptor', () => {
|
||||||
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$state_) => {
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$state_) => {
|
||||||
$httpBackend = _$httpBackend_;
|
$httpBackend = _$httpBackend_;
|
||||||
$httpBackend.whenGET(`Tickets/${ticket.id}/canHaveStowaway`).respond(true);
|
$httpBackend.whenGET(`Tickets/${ticket.id}/canHaveStowaway`).respond(true);
|
||||||
|
$httpBackend.whenGET(`Tickets/1/isEditable`).respond(true);
|
||||||
|
|
||||||
$state = _$state_;
|
$state = _$state_;
|
||||||
|
$state.params.id = 1;
|
||||||
$state.getCurrentPath = () => [null, {state: {name: 'ticket'}}];
|
$state.getCurrentPath = () => [null, {state: {name: 'ticket'}}];
|
||||||
|
|
||||||
controller = $componentController('vnTicketDescriptor', {$element: null}, {ticket});
|
controller = $componentController('vnTicketDescriptor', {$element: null}, {ticket});
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
<vn-td class="expendable">{{::ticket.province}}</vn-td>
|
<vn-td class="expendable">{{::ticket.province}}</vn-td>
|
||||||
<vn-td>
|
<vn-td>
|
||||||
<span class="chip {{$ctrl.stateColor(ticket)}}">
|
<span class="chip {{$ctrl.stateColor(ticket)}}">
|
||||||
{{::ticket.state}}
|
{{ticket.state}}
|
||||||
</span>
|
</span>
|
||||||
</vn-td>
|
</vn-td>
|
||||||
<vn-td>{{::ticket.agencyMode}}</vn-td>
|
<vn-td>{{::ticket.agencyMode}}</vn-td>
|
||||||
|
@ -120,6 +120,13 @@
|
||||||
</vn-data-viewer>
|
</vn-data-viewer>
|
||||||
<div fixed-bottom-right>
|
<div fixed-bottom-right>
|
||||||
<vn-vertical style="align-items: center;">
|
<vn-vertical style="align-items: center;">
|
||||||
|
<vn-button class="round sm vn-mb-sm"
|
||||||
|
icon="print"
|
||||||
|
ng-show="$ctrl.totalChecked > 0"
|
||||||
|
ng-click="$ctrl.setDelivered()"
|
||||||
|
vn-tooltip="Set as delivered and open delivery note(s)"
|
||||||
|
tooltip-position="left">
|
||||||
|
</vn-button>
|
||||||
<vn-button class="round sm vn-mb-sm"
|
<vn-button class="round sm vn-mb-sm"
|
||||||
icon="icon-recovery"
|
icon="icon-recovery"
|
||||||
ng-show="$ctrl.totalChecked > 0"
|
ng-show="$ctrl.totalChecked > 0"
|
||||||
|
|
|
@ -4,6 +4,37 @@ import UserError from 'core/lib/user-error';
|
||||||
import './style.scss';
|
import './style.scss';
|
||||||
|
|
||||||
export default class Controller extends Section {
|
export default class Controller extends Section {
|
||||||
|
constructor($element, $, vnReport) {
|
||||||
|
super($element, $);
|
||||||
|
this.vnReport = vnReport;
|
||||||
|
}
|
||||||
|
setDelivered() {
|
||||||
|
const checkedTickets = this.checked;
|
||||||
|
let ids = [];
|
||||||
|
|
||||||
|
for (let ticket of checkedTickets)
|
||||||
|
ids.push(ticket.id);
|
||||||
|
|
||||||
|
this.$http.post('TicketTrackings/setDelivered', ids).then(res => {
|
||||||
|
let state = res.data;
|
||||||
|
for (let ticket of checkedTickets) {
|
||||||
|
ticket.stateFk = state.id;
|
||||||
|
ticket.state = state.name;
|
||||||
|
ticket.alertLevel = state.alertLevel;
|
||||||
|
ticket.alertLevelCode = state.code;
|
||||||
|
}
|
||||||
|
this.openDeliveryNotes(ids);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
openDeliveryNotes(ids) {
|
||||||
|
for (let id of ids) {
|
||||||
|
this.vnReport.show('delivery-note', {
|
||||||
|
ticketId: id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
openBalanceDialog() {
|
openBalanceDialog() {
|
||||||
const checkedTickets = this.checked;
|
const checkedTickets = this.checked;
|
||||||
const description = [];
|
const description = [];
|
||||||
|
@ -125,6 +156,7 @@ export default class Controller extends Section {
|
||||||
return [minHour, maxHour];
|
return [minHour, maxHour];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Controller.$inject = ['$element', '$scope', 'vnReport'];
|
||||||
|
|
||||||
ngModule.component('vnTicketIndex', {
|
ngModule.component('vnTicketIndex', {
|
||||||
template: require('./index.html'),
|
template: require('./index.html'),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import './index.js';
|
import './index.js';
|
||||||
describe('Component vnTicketIndex', () => {
|
describe('Component vnTicketIndex', () => {
|
||||||
let controller;
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
let $window;
|
let $window;
|
||||||
let tickets = [{
|
let tickets = [{
|
||||||
id: 1,
|
id: 1,
|
||||||
|
@ -21,7 +22,8 @@ describe('Component vnTicketIndex', () => {
|
||||||
|
|
||||||
beforeEach(ngModule('ticket'));
|
beforeEach(ngModule('ticket'));
|
||||||
|
|
||||||
beforeEach(inject(($componentController, _$window_) => {
|
beforeEach(inject(($componentController, _$window_, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
$window = _$window_;
|
$window = _$window_;
|
||||||
const $element = angular.element('<vn-ticket-index></vn-ticket-index>');
|
const $element = angular.element('<vn-ticket-index></vn-ticket-index>');
|
||||||
controller = $componentController('vnTicketIndex', {$element});
|
controller = $componentController('vnTicketIndex', {$element});
|
||||||
|
@ -85,6 +87,21 @@ describe('Component vnTicketIndex', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('setDelivered()/openDeliveryNotes()', () => {
|
||||||
|
it('should perform a post to setDelivered and open tabs with the delivery notes', () => {
|
||||||
|
controller.$.model = {data: tickets, refresh: () => {}};
|
||||||
|
|
||||||
|
$window.open = jest.fn();
|
||||||
|
|
||||||
|
$httpBackend.expect('POST', 'TicketTrackings/setDelivered').respond('ok');
|
||||||
|
controller.setDelivered();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[1].id}`);
|
||||||
|
expect($window.open).toHaveBeenCalledWith(`api/report/delivery-note?ticketId=${tickets[2].id}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('checked()', () => {
|
describe('checked()', () => {
|
||||||
it('should return an array of checked tickets', () => {
|
it('should return an array of checked tickets', () => {
|
||||||
controller.$.model = {data: tickets};
|
controller.$.model = {data: tickets};
|
||||||
|
|
|
@ -2,6 +2,7 @@ Weekly tickets: Tickets programados
|
||||||
Go to lines: Ir a lineas
|
Go to lines: Ir a lineas
|
||||||
Not available: No disponible
|
Not available: No disponible
|
||||||
Payment on account...: Pago a cuenta...
|
Payment on account...: Pago a cuenta...
|
||||||
|
Set as delivered and open delivery note(s): Marcar como servido/s y abrir albarán/es
|
||||||
Closure: Cierre
|
Closure: Cierre
|
||||||
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
|
You cannot make a payment on account from multiple clients: No puedes realizar un pago a cuenta de clientes diferentes
|
||||||
Filter by selection: Filtro por selección
|
Filter by selection: Filtro por selección
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Controller extends Component {
|
||||||
let salesIds = [];
|
let salesIds = [];
|
||||||
let modified = false;
|
let modified = false;
|
||||||
|
|
||||||
if (!this.newDiscount) return;
|
if (this.newDiscount == null) return;
|
||||||
|
|
||||||
for (let i = 0; i < this.edit.length; i++) {
|
for (let i = 0; i < this.edit.length; i++) {
|
||||||
if (this.newDiscount != this.edit[0].discount || this.bulk || !this.newDiscount) {
|
if (this.newDiscount != this.edit[0].discount || this.bulk || !this.newDiscount) {
|
||||||
|
|
|
@ -56,15 +56,19 @@ module.exports = Self => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let entitlementRate = 0;
|
||||||
absences.forEach(absence => {
|
absences.forEach(absence => {
|
||||||
const isHoliday = absence.absenceType().code === 'holiday';
|
const absenceType = absence.absenceType();
|
||||||
const isHalfHoliday = absence.absenceType().code === 'halfHoliday';
|
const isHoliday = absenceType.code === 'holiday';
|
||||||
|
const isHalfHoliday = absenceType.code === 'halfHoliday';
|
||||||
|
|
||||||
if (isHoliday)
|
if (isHoliday)
|
||||||
calendar.holidaysEnjoyed += 1;
|
calendar.holidaysEnjoyed += 1;
|
||||||
if (isHalfHoliday)
|
if (isHalfHoliday)
|
||||||
calendar.holidaysEnjoyed += 0.5;
|
calendar.holidaysEnjoyed += 0.5;
|
||||||
|
|
||||||
|
entitlementRate += absenceType.holidayEntitlementRate;
|
||||||
|
|
||||||
absence.dated = new Date(absence.dated);
|
absence.dated = new Date(absence.dated);
|
||||||
absence.dated.setHours(0, 0, 0, 0);
|
absence.dated.setHours(0, 0, 0, 0);
|
||||||
});
|
});
|
||||||
|
@ -119,6 +123,9 @@ module.exports = Self => {
|
||||||
|
|
||||||
workedDays += Math.floor((endedTime - startedTime) / dayTimestamp);
|
workedDays += Math.floor((endedTime - startedTime) / dayTimestamp);
|
||||||
|
|
||||||
|
if (workedDays > daysInYear())
|
||||||
|
workedDays = daysInYear();
|
||||||
|
|
||||||
// Workcenter holidays
|
// Workcenter holidays
|
||||||
let holidayList = contract.workCenter().holidays();
|
let holidayList = contract.workCenter().holidays();
|
||||||
for (let day of holidayList) {
|
for (let day of holidayList) {
|
||||||
|
@ -137,10 +144,22 @@ module.exports = Self => {
|
||||||
const maxHolidays = currentContract.holidays().days;
|
const maxHolidays = currentContract.holidays().days;
|
||||||
calendar.totalHolidays = maxHolidays;
|
calendar.totalHolidays = maxHolidays;
|
||||||
|
|
||||||
if (workedDays < 365)
|
workedDays -= entitlementRate;
|
||||||
calendar.totalHolidays = Math.round(2 * maxHolidays * (workedDays) / 365) / 2;
|
|
||||||
|
if (workedDays < daysInYear())
|
||||||
|
calendar.totalHolidays = Math.round(2 * maxHolidays * (workedDays) / daysInYear()) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
function daysInYear() {
|
||||||
|
const year = yearStarted.getFullYear();
|
||||||
|
|
||||||
|
return isLeapYear(year) ? 366 : 365;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [calendar, absences, holidays];
|
return [calendar, absences, holidays];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function isLeapYear(year) {
|
||||||
|
return year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
},
|
},
|
||||||
"code": {
|
"code": {
|
||||||
"type": "String"
|
"type": "String"
|
||||||
|
},
|
||||||
|
"holidayEntitlementRate": {
|
||||||
|
"type": "Number"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"acls": [
|
"acls": [
|
||||||
|
|
|
@ -76,7 +76,7 @@ class Controller extends Component {
|
||||||
let events = value.events;
|
let events = value.events;
|
||||||
|
|
||||||
if (events) {
|
if (events) {
|
||||||
for (event of events) {
|
for (let event of events) {
|
||||||
event.dated = toStamp(event.dated);
|
event.dated = toStamp(event.dated);
|
||||||
event.ended = toStamp(event.ended);
|
event.ended = toStamp(event.ended);
|
||||||
event.started = toStamp(event.started);
|
event.started = toStamp(event.started);
|
||||||
|
|
|
@ -0,0 +1,155 @@
|
||||||
|
import './index';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('component vnZoneCalendar', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-calendar></vn-zone-calendar>`);
|
||||||
|
controller = $componentController('vnZoneCalendar', {$element, $scope});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.days = [];
|
||||||
|
controller.exclusions = [];
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('date() setter', () => {
|
||||||
|
it('should set the month property and then call the refreshEvents() method', () => {
|
||||||
|
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||||
|
|
||||||
|
controller.date = new Date();
|
||||||
|
|
||||||
|
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||||
|
expect(controller.months.length).toEqual(4);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('step()', () => {
|
||||||
|
it('should set the date month to 4 months backwards', () => {
|
||||||
|
const now = new Date();
|
||||||
|
now.setMonth(now.getMonth() - 4);
|
||||||
|
|
||||||
|
controller.step(-1);
|
||||||
|
|
||||||
|
const expectedMonth = now.getMonth();
|
||||||
|
const currentMonth = controller.date.getMonth();
|
||||||
|
|
||||||
|
expect(currentMonth).toEqual(expectedMonth);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set the date month to 4 months forwards', () => {
|
||||||
|
const now = new Date();
|
||||||
|
now.setMonth(now.getMonth() + 4);
|
||||||
|
|
||||||
|
controller.step(1);
|
||||||
|
|
||||||
|
const expectedMonth = now.getMonth();
|
||||||
|
const currentMonth = controller.date.getMonth();
|
||||||
|
|
||||||
|
expect(currentMonth).toEqual(expectedMonth);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('data() setter', () => {
|
||||||
|
it('should set the events and exclusions and then call the refreshEvents() method', () => {
|
||||||
|
jest.spyOn(controller, 'refreshEvents').mockReturnThis();
|
||||||
|
|
||||||
|
controller.data = {
|
||||||
|
exclusions: [{
|
||||||
|
dated: new Date()
|
||||||
|
}],
|
||||||
|
events: [{
|
||||||
|
dated: new Date()
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(controller.refreshEvents).toHaveBeenCalledWith();
|
||||||
|
expect(controller.events).toBeDefined();
|
||||||
|
expect(controller.events.length).toEqual(1);
|
||||||
|
expect(controller.exclusions).toBeDefined();
|
||||||
|
expect(Object.keys(controller.exclusions).length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('refreshEvents()', () => {
|
||||||
|
it('should fill the days property with the events.', () => {
|
||||||
|
controller.data = [];
|
||||||
|
controller.firstDay = new Date();
|
||||||
|
|
||||||
|
const lastDay = new Date();
|
||||||
|
lastDay.setDate(lastDay.getDate() + 10);
|
||||||
|
controller.lastDay = lastDay;
|
||||||
|
|
||||||
|
const firstEventStamp = controller.firstDay.getTime();
|
||||||
|
const lastEventStamp = controller.lastDay.getTime();
|
||||||
|
controller.events = [{
|
||||||
|
type: 'day',
|
||||||
|
dated: firstEventStamp
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'day',
|
||||||
|
dated: lastEventStamp
|
||||||
|
}];
|
||||||
|
|
||||||
|
controller.refreshEvents();
|
||||||
|
const expectedDays = Object.keys(controller.days);
|
||||||
|
|
||||||
|
expect(expectedDays.length).toEqual(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should call the emit() method', () => {
|
||||||
|
jest.spyOn(controller, 'emit');
|
||||||
|
|
||||||
|
const $event = {};
|
||||||
|
const $days = [new Date()];
|
||||||
|
const $type = 'day';
|
||||||
|
const $weekday = 1;
|
||||||
|
|
||||||
|
controller.onSelection($event, $days, $type, $weekday);
|
||||||
|
|
||||||
|
expect(controller.emit).toHaveBeenCalledWith('selection',
|
||||||
|
{
|
||||||
|
$days: $days,
|
||||||
|
$event: {},
|
||||||
|
$events: [],
|
||||||
|
$exclusions: [],
|
||||||
|
$type: 'day',
|
||||||
|
$weekday: 1
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('hasEvents()', () => {
|
||||||
|
it('should return true for an existing event on a date', () => {
|
||||||
|
const dated = new Date();
|
||||||
|
|
||||||
|
controller.days[dated.getTime()] = true;
|
||||||
|
|
||||||
|
const result = controller.hasEvents(dated);
|
||||||
|
|
||||||
|
expect(result).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getClass()', () => {
|
||||||
|
it('should return the className "excluded" for an excluded date', () => {
|
||||||
|
const dated = new Date();
|
||||||
|
|
||||||
|
controller.exclusions = [];
|
||||||
|
controller.exclusions[dated.getTime()] = true;
|
||||||
|
|
||||||
|
const result = controller.getClass(dated);
|
||||||
|
|
||||||
|
expect(result).toEqual('excluded');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -33,6 +33,7 @@ class Controller extends Descriptor {
|
||||||
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
this.vnApp.showSuccess(this.$t('Zone deleted'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onCloneAccept() {
|
onCloneAccept() {
|
||||||
return this.$http.post(`Zones/${this.id}/clone`).
|
return this.$http.post(`Zones/${this.id}/clone`).
|
||||||
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
then(res => this.$state.go('zone.card.basicData', {id: res.data.id}));
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Zone descriptor', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$element = angular.element('<vn-zone-descriptor></vn-zone-descriptor');
|
||||||
|
controller = $componentController('vnZoneDescriptor', {$element});
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.id = 1;
|
||||||
|
controller.$.deleteZone = {
|
||||||
|
hide: () => {},
|
||||||
|
show: () => {}
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('onDelete()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the deleteZone show() method', () => {
|
||||||
|
jest.spyOn(controller.$.deleteZone, 'show');
|
||||||
|
|
||||||
|
const expectedData = [{id: 16}];
|
||||||
|
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||||
|
controller.onDelete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.deleteZone.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make an HTTP POST query and then call the deleteZone() method', () => {
|
||||||
|
jest.spyOn(controller, 'deleteZone').mockReturnThis();
|
||||||
|
|
||||||
|
const expectedData = [];
|
||||||
|
$httpBackend.when('GET', 'Tickets').respond(expectedData);
|
||||||
|
controller.onDelete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.deleteZone).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('deleteZone()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the showMessage() method', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||||
|
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||||
|
|
||||||
|
const stateName = 'zone.index';
|
||||||
|
$httpBackend.when('POST', 'Zones/1/deleteZone').respond(200);
|
||||||
|
controller.deleteZone();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith(stateName);
|
||||||
|
expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Zone deleted');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onCloneAccept()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the state go() method', () => {
|
||||||
|
jest.spyOn(controller.$state, 'go').mockReturnThis();
|
||||||
|
|
||||||
|
const stateName = 'zone.card.basicData';
|
||||||
|
const expectedData = {id: 1};
|
||||||
|
$httpBackend.when('POST', 'Zones/1/clone').respond(expectedData);
|
||||||
|
controller.onCloneAccept();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$state.go).toHaveBeenCalledWith(stateName, expectedData);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -6,12 +6,20 @@ class Controller extends Section {
|
||||||
super($element, $);
|
super($element, $);
|
||||||
this.vnWeekDays = vnWeekDays;
|
this.vnWeekDays = vnWeekDays;
|
||||||
this.editMode = 'include';
|
this.editMode = 'include';
|
||||||
|
}
|
||||||
|
|
||||||
this.path = `Zones/${this.$params.id}/events`;
|
$onInit() {
|
||||||
this.exclusionsPath = `Zones/${this.$params.id}/exclusions`;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return `Zones/${this.$params.id}/events`;
|
||||||
|
}
|
||||||
|
|
||||||
|
get exclusionsPath() {
|
||||||
|
return `Zones/${this.$params.id}/exclusions`;
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
let data = {};
|
let data = {};
|
||||||
this.$q.all([
|
this.$q.all([
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
import './index';
|
||||||
|
|
||||||
|
describe('component vnZoneEvents', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-events></vn-zone-events>`);
|
||||||
|
controller = $componentController('vnZoneEvents', {$element, $scope});
|
||||||
|
controller.$params = {id: 1};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('refresh()', () => {
|
||||||
|
it('should set the zone and then call both getSummary() and getWarehouses()', () => {
|
||||||
|
$httpBackend.expectGET(`Zones/1/events`).respond({id: 1});
|
||||||
|
$httpBackend.expectGET(`Zones/1/exclusions`).respond({id: 1});
|
||||||
|
controller.refresh();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
const data = controller.$.data;
|
||||||
|
|
||||||
|
expect(data.events).toBeDefined();
|
||||||
|
expect(data.exclusions).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should call the edit() method', () => {
|
||||||
|
jest.spyOn(controller, 'edit').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [{name: 'Event'}];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'include';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.edit).toHaveBeenCalledWith({name: 'Event'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the create() method', () => {
|
||||||
|
jest.spyOn(controller, 'create').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {dated: new Date()};
|
||||||
|
const days = [weekday];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'include';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.create).toHaveBeenCalledWith(type, days, weekday);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the exclusionDelete() method', () => {
|
||||||
|
jest.spyOn(controller, 'exclusionDelete').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [{id: 1}];
|
||||||
|
controller.editMode = 'delete';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.exclusionDelete).toHaveBeenCalledWith(exclusions);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call the exclusionCreate() method', () => {
|
||||||
|
jest.spyOn(controller, 'exclusionCreate').mockReturnThis();
|
||||||
|
|
||||||
|
const weekday = {};
|
||||||
|
const days = [{dated: new Date()}];
|
||||||
|
const type = 'EventType';
|
||||||
|
const events = [];
|
||||||
|
const exclusions = [];
|
||||||
|
controller.editMode = 'delete';
|
||||||
|
controller.onSelection(days, type, weekday, events, exclusions);
|
||||||
|
|
||||||
|
expect(controller.exclusionCreate).toHaveBeenCalledWith(days);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('create()', () => {
|
||||||
|
it('shoud set the selected property and then call the dialog show() method', () => {
|
||||||
|
controller.$.dialog = {show: jest.fn()};
|
||||||
|
|
||||||
|
const type = 'weekday';
|
||||||
|
const days = [new Date()];
|
||||||
|
const weekday = 1;
|
||||||
|
controller.create(type, days, weekday);
|
||||||
|
|
||||||
|
const selection = controller.selected;
|
||||||
|
const firstWeekday = selection.wdays[weekday];
|
||||||
|
|
||||||
|
expect(selection.type).toEqual('indefinitely');
|
||||||
|
expect(firstWeekday).toBeTruthy();
|
||||||
|
expect(controller.isNew).toBeTruthy();
|
||||||
|
expect(controller.$.dialog.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud set the selected property with the first day and then call the dialog show() method', () => {
|
||||||
|
controller.$.dialog = {show: jest.fn()};
|
||||||
|
|
||||||
|
const type = 'nonListedType';
|
||||||
|
const days = [new Date()];
|
||||||
|
const weekday = 1;
|
||||||
|
controller.create(type, days, weekday);
|
||||||
|
|
||||||
|
const selection = controller.selected;
|
||||||
|
|
||||||
|
expect(selection.type).toEqual('day');
|
||||||
|
expect(selection.dated).toEqual(days[0]);
|
||||||
|
expect(controller.isNew).toBeTruthy();
|
||||||
|
expect(controller.$.dialog.show).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onIncludeResponse()', () => {
|
||||||
|
it('shoud call the onDelete() method', () => {
|
||||||
|
jest.spyOn(controller, 'onDelete').mockReturnValue(
|
||||||
|
new Promise(accept => accept())
|
||||||
|
);
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.onIncludeResponse('delete');
|
||||||
|
|
||||||
|
expect(controller.onDelete).toHaveBeenCalledWith(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP POST query to create a new one and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.isNew = true;
|
||||||
|
|
||||||
|
$httpBackend.when('POST', `Zones/1/events`).respond(200);
|
||||||
|
controller.onIncludeResponse('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP PUT query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
controller.selected = {id: 1};
|
||||||
|
controller.isNew = false;
|
||||||
|
|
||||||
|
const eventId = 1;
|
||||||
|
$httpBackend.when('PUT', `Zones/1/events/${eventId}`).respond(200);
|
||||||
|
controller.onIncludeResponse('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onDeleteResponse()', () => {
|
||||||
|
it('shoud make an HTTP DELETE query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const eventId = 1;
|
||||||
|
$httpBackend.expect('DELETE', `Zones/1/events/1`).respond({id: 1});
|
||||||
|
controller.onDeleteResponse('accept', eventId);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exclusionCreate()', () => {
|
||||||
|
it('shoud make an HTTP POST query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const dates = [new Date()];
|
||||||
|
$httpBackend.expect('POST', `Zones/1/exclusions`).respond({id: 1});
|
||||||
|
controller.exclusionCreate(dates);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('exclusionDelete()', () => {
|
||||||
|
it('shoud make an HTTP DELETE query once and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
const exclusions = [{id: 1}];
|
||||||
|
const firstExclusionId = 1;
|
||||||
|
$httpBackend.when('DELETE', `Zones/1/exclusions/${firstExclusionId}`).respond(200);
|
||||||
|
controller.exclusionDelete(exclusions);
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shoud make an HTTP DELETE query for every event and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
jest.spyOn(controller.$http, 'delete').mockReturnValue(200);
|
||||||
|
|
||||||
|
const exclusions = [{id: 1}, {id: 2}, {id: 3}, {id: 4}];
|
||||||
|
controller.exclusionDelete(exclusions);
|
||||||
|
$scope.$apply();
|
||||||
|
|
||||||
|
expect(controller.$http.delete).toHaveBeenCalledTimes(4);
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,50 @@
|
||||||
|
import './index';
|
||||||
|
import crudModel from 'core/mocks/crud-model';
|
||||||
|
|
||||||
|
describe('component vnZoneLocation', () => {
|
||||||
|
let $scope;
|
||||||
|
let controller;
|
||||||
|
let $httpBackend;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$scope = $rootScope.$new();
|
||||||
|
const $element = angular.element(`<vn-zone-location></vn-zone-location>`);
|
||||||
|
controller = $componentController('vnZoneLocation', {$element, $scope});
|
||||||
|
controller.$.model = crudModel;
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('onSearch()', () => {
|
||||||
|
it('should call the applyFilter() method and then set the data', () => {
|
||||||
|
controller.$.treeview = {};
|
||||||
|
controller.onSearch({});
|
||||||
|
|
||||||
|
const treeviewData = controller.$.treeview.data;
|
||||||
|
|
||||||
|
expect(treeviewData).toBeDefined();
|
||||||
|
expect(treeviewData.length).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onFetch()', () => {
|
||||||
|
it('should call the applyFilter() method and then return the model data', () => {
|
||||||
|
const result = controller.onFetch();
|
||||||
|
|
||||||
|
expect(result.length).toEqual(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSelection()', () => {
|
||||||
|
it('should make an HTTP POST query', () => {
|
||||||
|
const item = {id: 123};
|
||||||
|
|
||||||
|
const expectedParams = {geoId: 123, isIncluded: true};
|
||||||
|
$httpBackend.expect('POST', `zones/1/toggleIsIncluded`, expectedParams).respond(200);
|
||||||
|
controller.onSelection(true, item);
|
||||||
|
$httpBackend.flush();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -51,4 +51,26 @@ describe('component vnZoneSummary', () => {
|
||||||
expect(controller.summary).toBeDefined();
|
expect(controller.summary).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('getWarehouses()', () => {
|
||||||
|
it('should make an HTTP get query and then store data on the controller', () => {
|
||||||
|
controller._zone = {id: 1};
|
||||||
|
const params = {
|
||||||
|
filter: {
|
||||||
|
include: {
|
||||||
|
relation: 'warehouse',
|
||||||
|
fields: ['name']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const serializedParams = $httpParamSerializer(params);
|
||||||
|
const query = `Zones/1/warehouses?${serializedParams}`;
|
||||||
|
$httpBackend.expect('GET', query).respond([{id: 1}]);
|
||||||
|
controller.getWarehouses();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.zoneWarehouses.length).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,13 +2,14 @@ import ngModule from '../module';
|
||||||
import Section from 'salix/components/section';
|
import Section from 'salix/components/section';
|
||||||
|
|
||||||
class Controller extends Section {
|
class Controller extends Section {
|
||||||
constructor($element, $) {
|
$onInit() {
|
||||||
super($element, $);
|
|
||||||
|
|
||||||
this.path = `Zones/${this.$params.id}/warehouses`;
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return `Zones/${this.$params.id}/warehouses`;
|
||||||
|
}
|
||||||
|
|
||||||
refresh() {
|
refresh() {
|
||||||
let filter = {include: 'warehouse'};
|
let filter = {include: 'warehouse'};
|
||||||
this.$http.get(this.path, {params: {filter}})
|
this.$http.get(this.path, {params: {filter}})
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import './index.js';
|
||||||
|
|
||||||
|
describe('Zone warehouses', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let $httpParamSerializer;
|
||||||
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(ngModule('zone'));
|
||||||
|
|
||||||
|
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
|
||||||
|
$httpBackend = _$httpBackend_;
|
||||||
|
$httpParamSerializer = _$httpParamSerializer_;
|
||||||
|
$element = angular.element('<vn-zone-warehouses></vn-zone-warehouses');
|
||||||
|
controller = $componentController('vnZoneWarehouses', {$element});
|
||||||
|
controller.zone = {id: 1};
|
||||||
|
controller.$params = {id: 1};
|
||||||
|
controller.$.dialog = {hide: jest.fn()};
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('refresh()', () => {
|
||||||
|
it('should make an HTTP GET query and then set the data', () => {
|
||||||
|
const params = {filter: {include: 'warehouse'}};
|
||||||
|
const serializedParams = $httpParamSerializer(params);
|
||||||
|
const path = `Zones/1/warehouses?${serializedParams}`;
|
||||||
|
$httpBackend.expect('GET', path).respond([{id: 1, name: 'Warehouse one'}]);
|
||||||
|
controller.refresh();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.$.data).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('onSave()', () => {
|
||||||
|
it('should make an HTTP POST query and then call the refresh() method', () => {
|
||||||
|
jest.spyOn(controller, 'refresh').mockReturnThis();
|
||||||
|
|
||||||
|
$httpBackend.expect('POST', `Zones/1/warehouses`).respond(200);
|
||||||
|
controller.onSave('accept');
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.selected).toBeNull();
|
||||||
|
expect(controller.isNew).toBeNull();
|
||||||
|
expect(controller.$.dialog.hide).toHaveBeenCalledWith();
|
||||||
|
expect(controller.refresh).toHaveBeenCalledWith();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('delete()', () => {
|
||||||
|
it('should make an HTTP DELETE query and then set deleteRow property to null value', () => {
|
||||||
|
controller.deleteRow = {id: 1};
|
||||||
|
controller.$.data = [{id: 1}];
|
||||||
|
$httpBackend.expect('DELETE', `Zones/1/warehouses/1`).respond(200);
|
||||||
|
controller.delete();
|
||||||
|
$httpBackend.flush();
|
||||||
|
|
||||||
|
expect(controller.deleteRow).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
|
@ -42,7 +42,7 @@
|
||||||
"@babel/preset-env": "^7.7.7",
|
"@babel/preset-env": "^7.7.7",
|
||||||
"@babel/register": "^7.7.7",
|
"@babel/register": "^7.7.7",
|
||||||
"angular-mocks": "^1.7.9",
|
"angular-mocks": "^1.7.9",
|
||||||
"babel-jest": "^24.9.0",
|
"babel-jest": "^26.0.1",
|
||||||
"babel-loader": "^8.0.6",
|
"babel-loader": "^8.0.6",
|
||||||
"babel-preset-es2015": "^6.24.1",
|
"babel-preset-es2015": "^6.24.1",
|
||||||
"css-loader": "^2.1.0",
|
"css-loader": "^2.1.0",
|
||||||
|
@ -70,7 +70,7 @@
|
||||||
"jasmine": "^3.5.0",
|
"jasmine": "^3.5.0",
|
||||||
"jasmine-reporters": "^2.3.2",
|
"jasmine-reporters": "^2.3.2",
|
||||||
"jasmine-spec-reporter": "^4.2.1",
|
"jasmine-spec-reporter": "^4.2.1",
|
||||||
"jest": "^24.9.0",
|
"jest": "^26.0.1",
|
||||||
"jest-junit": "^8.0.0",
|
"jest-junit": "^8.0.0",
|
||||||
"json-loader": "^0.5.7",
|
"json-loader": "^0.5.7",
|
||||||
"merge-stream": "^1.0.1",
|
"merge-stream": "^1.0.1",
|
||||||
|
|
Loading…
Reference in New Issue