Merge branch 'dev' of http://git.verdnatura.es/salix into test

This commit is contained in:
Carlos Jimenez 2018-01-08 08:14:13 +01:00
commit 82a1d4fdb7
276 changed files with 40989 additions and 32155 deletions

View File

@ -26,7 +26,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Datos básicos",
"description": "Basic data",
"icon": "person"
}
}, {
@ -37,7 +37,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Datos fiscales",
"description": "Fiscal data",
"icon": "account_balance"
}
}, {
@ -64,7 +64,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Consignatarios",
"description": "Addresses",
"icon": "local_shipping"
}
}, {
@ -83,7 +83,7 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Acceso web",
"description": "Web access",
"icon": "language"
}
}, {
@ -99,13 +99,67 @@
"client": "$ctrl.client"
},
"menu": {
"description": "Notas",
"description": "Notes",
"icon": "insert_drive_file"
}
}, {
"url": "/create",
"state": "clientCard.notes.create",
"component": "vn-note-create"
}, {
"url": "/credit",
"abstract": true,
"state": "clientCard.credit",
"component": "ui-view"
}, {
"url": "/list",
"state": "clientCard.credit.list",
"component": "vn-client-credit-list",
"params": {
"client": "$ctrl.client"
},
"menu": {
"description": "Credit",
"icon": "credit_card"
}
}, {
"url": "/create",
"state": "clientCard.credit.create",
"component": "vn-client-credit-create",
"params": {
"client": "$ctrl.client"
}
}, {
"url": "/greuge",
"abstract": true,
"state": "clientCard.greuge",
"component": "ui-view"
}, {
"url": "/list",
"state": "clientCard.greuge.list",
"component": "vn-client-greuge-list",
"params": {
"client": "$ctrl.client"
},
"menu": {
"description": "Greuge",
"icon": "work"
}
}, {
"url": "/create",
"state": "clientCard.greuge.create",
"component": "vn-client-greuge-create",
"params": {
"client": "$ctrl.client"
}
}, {
"url": "/mandate",
"state": "clientCard.mandate",
"component": "vn-client-mandate",
"menu": {
"description": "Mandate",
"icon": "pan_tool"
}
}
]
}

View File

@ -5,7 +5,7 @@
<vn-horizontal>
<vn-title vn-one>Addresses</vn-title>
</vn-horizontal>
<vn-horizontal ng-repeat="i in index.model track by i.id" class="pad-medium-top" style="align-items: center;">
<vn-horizontal ng-repeat="i in index.model.items track by i.id" class="pad-medium-top" style="align-items: center;">
<vn-one border-radius class="pad-small border-solid"
ng-class="{'bg-dark-item': i.isDefaultAddress,'bg-opacity-item': !i.isEnabled && !i.isDefaultAddress}">
<vn-horizontal style="align-items: center;">
@ -27,7 +27,9 @@
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-paging index="index"></vn-paging>
<vn-paging index="index" total="index.model.total"></vn-paging>
<vn-float-button
fixed-bottom-right
ui-sref="clientCard.addresses.create"

View File

@ -1,4 +1,3 @@
{
"Addresses": "Consignatarios",
"Set as default": "Establecer como predeterminado"
}

View File

@ -1,5 +1,4 @@
{
"Basic data": "Datos básicos",
"Comercial Name": "Nombre comercial",
"Tax number": "NIF/CIF",
"Social name": "Razón social",

View File

@ -19,28 +19,24 @@
label="Pay method">
</vn-autocomplete>
<vn-textfield vn-two label="IBAN" field="$ctrl.client.iban" vn-acl="administrative"></vn-textfield>
<vn-textfield vn-one label="Vencimiento" field="$ctrl.client.dueDay" vn-acl="administrative"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Crédito" field="$ctrl.client.credit" vn-acl="administrative"></vn-textfield>
<vn-textfield vn-one label="Crédito asegurado" field="$ctrl.client.creditInsurance" vn-acl="administrative"></vn-textfield>
<vn-textfield vn-one label="Due day" field="$ctrl.client.dueDay" vn-acl="administrative"></vn-textfield>
</vn-horizontal>
<vn-horizontal margin-medium-bottom>
<vn-one>
<vn-check label="Recibido core VNH" field="$ctrl.client.hasCoreVnh" vn-acl="administrative"></vn-check>
<vn-check label="Received core VNH" field="$ctrl.client.hasCoreVnh" vn-acl="administrative"></vn-check>
</vn-one>
<vn-one>
<vn-check label="Recibido core VNL" field="$ctrl.client.hasCoreVnl" vn-acl="administrative"></vn-check>
<vn-check label="Received core VNL" field="$ctrl.client.hasCoreVnl" vn-acl="administrative"></vn-check>
</vn-one>
<vn-one>
<vn-check label="Recibido B2B VNL" field="$ctrl.client.hasSepaVnl" vn-acl="administrative"></vn-check>
<vn-check label="Received B2B VNL" field="$ctrl.client.hasSepaVnl" vn-acl="administrative"></vn-check>
</vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Guardar" vn-acl="administrative"></vn-submit>
<vn-submit label="Save" vn-acl="administrative"></vn-submit>
</vn-button-bar>
</form>
<vn-dialog

View File

@ -17,9 +17,6 @@ export default class Controller {
this.billData.payMethodFk = this.client.payMethodFk;
this.billData.iban = this.client.iban;
this.billData.dueDay = this.client.dueDay;
this.billData.discount = this.client.discount;
this.billData.credit = this.client.credit;
this.billData.creditInsurance = this.client.creditInsurance;
}
}
submit() {

View File

@ -25,9 +25,6 @@ describe('Client', () => {
describe('copyData()', () => {
it(`should define billData using client's data`, () => {
controller.client = {
credit: 1000000000000,
creditInsurance: null,
discount: 99,
dueDay: 0,
iban: null,
payMethodFk: 1
@ -72,8 +69,8 @@ describe('Client', () => {
describe('returnDialog()', () => {
it('should request to send notification email', () => {
controller.client = {id: '123'};
$httpBackend.when('POST', `/mailer/manuscript/payment-update/${controller.client.id}`).respond('done');
$httpBackend.expectPOST(`/mailer/manuscript/payment-update/${controller.client.id}`);
$httpBackend.when('POST', `/mailer/notification/payment-update/${controller.client.id}`).respond('done');
$httpBackend.expectPOST(`/mailer/notification/payment-update/${controller.client.id}`);
controller.returnDialog('ACCEPT');
$httpBackend.flush();
});

View File

@ -10,5 +10,10 @@
"Yes, propagate": "Si, propagar",
"Equivalent tax spreaded": "Recargo de equivalencia propagado",
"Invoice by address": "Facturar por consignatario",
"Equalization tax": "Recargo de equivalencia"
"Equalization tax": "Recargo de equivalencia",
"Due day": "Vencimiento",
"Received core VNH": "Recibido core VNH",
"Received core VNL": "Recibido core VNL",
"Received B2B VNL": "Recibido B2B VNL",
"SAVE": "GUARDAR"
}

View File

@ -1,18 +1,16 @@
<vn-horizontal>
<vn-main-block>
<mg-ajax
path="/client/api/Clients/{{edit.params.id}}/card"
actions="$ctrl.client = edit.model"
options="mgEdit">
</mg-ajax>
<vn-auto style="min-width: 18em; padding-left: 1em; padding-bottom: 1em;">
<vn-descriptor
client="$ctrl.client"
active="$ctrl.client.active"
class="display-block" >
</vn-descriptor>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>
<vn-vertical style="max-width: 70em; margin: 0 auto;" ui-view></vn-vertical>
</vn-one>
</vn-horizontal>
<vn-horizontal>
<vn-auto class="left-block">
<vn-descriptor client="$ctrl.client"></vn-descriptor>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>
<vn-vertical ui-view></vn-vertical>
</vn-one>
</vn-horizontal>
</vn-main-block>

View File

@ -1,5 +1,4 @@
import ngModule from '../module';
import './style.css';
export default class Controller {
constructor() {

View File

@ -1,3 +0,0 @@
vn-descriptor {
font-family: vn-font-bold;
}

View File

@ -14,3 +14,8 @@ import './address-edit/address-edit';
import './notes/notes';
import './note-create/note-create';
import './web-access/web-access';
import './credit-list/credit-list';
import './credit-create/credit-create';
import './greuge-list/greuge-list';
import './greuge-create/greuge-create';
import './mandate/mandate';

View File

@ -0,0 +1,23 @@
<mg-ajax path="/client/api/Clients/{{patch.params.id}}" options="vnPatch"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.client"
form="form"
save="patch">
</vn-watcher>
<form name="form" ng-submit="watcher.submitGo('clientCard.credit.list')" pad-medium>
<vn-card >
<vn-vertical pad-large>
<vn-title>Add credit</vn-title>
<vn-horizontal>
<vn-textfield vn-one label="Credit" field="$ctrl.client.credit" type="number" vn-focus></vn-textfield>
<vn-one></vn-one>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
ngModule.component('vnClientCreditCreate', {
template: require('./credit-create.html'),
bindings: {
client: '<'
}
});

View File

@ -0,0 +1,3 @@
{
"Add credit": "Añadir crédito"
}

View File

@ -0,0 +1,27 @@
<mg-ajax path="/client/api/ClientCredits/filter" options="vnIndexNonAuto"></mg-ajax>
<vn-card pad-medium>
<vn-vertical pad-large>
<vn-title vn-one margin-large-bottom>Credit</vn-title>
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
<vn-column-header vn-one pad-medium-h field="amount" text="Credit"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="created" text="Since" default-order="ASC"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="employee.name" text="Employee" order-locked></vn-column-header>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal
vn-one class="list list-element text-center"
pad-small-bottom
ng-repeat="credit in index.model.instances track by credit.id">
<vn-one pad-medium-h>{{::credit.amount | number:2}} €</vn-one>
<vn-two pad-medium-h>{{::credit.created | date:'dd/MM/yyyy HH:mm' }}</vn-two>
<vn-two pad-medium-h>{{::credit.employee.name}} {{::credit.employee.surname}}</vn-two>
</vn-horizontal>
</vn-one>
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
</vn-vertical>
</vn-card>
<a ui-sref="clientCard.credit.create" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -0,0 +1,9 @@
import ngModule from '../module';
import FilterClientList from '../filterClientList';
class ClientCreditList extends FilterClientList {}
ngModule.component('vnClientCreditList', {
template: require('./credit-list.html'),
controller: ClientCreditList
});

View File

@ -0,0 +1,5 @@
{
"Since" : "Desde",
"Employee" : "Empleado",
"No results": "Sin resultados"
}

View File

@ -1,14 +1,18 @@
<vn-card>
<vn-vertical class="margin-medium" pad-medium-top pad-medium-bottom>
<vn-horizontal>
<a vn-one ui-sref="clients">
<i class="material-icons descriptor-icon">person</i>
</a>
<vn-vertical vn-two>
<div class="margin-none">{{::$ctrl.client.id}}</div>
<div class="margin-none">{{$ctrl.client.name}}</div>
<div class="margin-none">{{$ctrl.client.phone}}</div>
<vn-card margin-medium-v>
<vn-vertical>
<vn-auto class="descriptor-header pointer" ui-sref="clients">
<i class="material-icons">person</i>
</vn-auto>
<vn-auto pad-medium>
<vn-vertical>
<vn-horizontal ng-repeat="(field, title) in $ctrl.fieldsToShow" ng-if="$ctrl.client[field]">
<strong vn-auto>{{::title}}:</strong>
<vn-auto margin-small-left>
<span ng-if="field.includes('credit')">{{$ctrl.client[field] | number:2}} €</span>
<span ng-if="!field.includes('credit')">{{::$ctrl.client[field]}}</span>
</vn-auto>
</vn-horizontal>
</vn-vertical>
</vn-horizontal>
</vn-auto>
</vn-vertical>
</vn-card>

View File

@ -1,26 +1,33 @@
import ngModule from '../module';
import './style.scss';
export default class Controller {
constructor($scope, $http) {
this.$http = $http;
constructor($translate) {
this.$translate = $translate;
// CLient fields to display
this.fields = ['id', 'name', 'phone', 'credit', 'creditInsurance'];
this.fieldsToShow = {};
}
set active(value) {
if (this._active !== value && this._active !== undefined)
this.$http.put(`/client/api/Clients/${this.client.id}/activate`);
this._active = value;
// concat 2 Arrays without duplicates
_concatFields(a, b) {
return a.concat(b.filter(item => a.indexOf(item) < 0));
}
get active() {
return this._active;
$onInit() {
let fields = (this.moreFields && this.moreFields instanceof Array) ? this._concatFields(this.fields, this.moreFields) : this.fields;
fields.forEach(field => {
this.fieldsToShow[field] = this.$translate.instant(field);
});
}
}
Controller.$inject = ['$scope', '$http'];
Controller.$inject = ['$translate'];
ngModule.component('vnDescriptor', {
template: require('./descriptor.html'),
controller: Controller,
bindings: {
client: '<',
active: '<'
moreFields: '<?'
}
});

View File

@ -3,30 +3,32 @@ import './descriptor.js';
describe('Client', () => {
describe('Component vnDescriptor', () => {
let $componentController;
let $scope;
let $translate;
let controller;
beforeEach(() => {
angular.mock.module('client');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope) => {
beforeEach(angular.mock.inject((_$componentController_, _$translate_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
controller = $componentController('vnDescriptor', {$scope: $scope});
$translate = _$translate_;
controller = $componentController('vnDescriptor', {$translate: $translate});
}));
describe('set active', () => {
it('should check if active is defined and diferent from the new value', () => {
controller.client = {id: 1};
describe('onInit()', () => {
it('should create Object with basic fields', () => {
controller.client = {
id: 1,
name: "Peter Parker",
phone: null,
mobile: "666666",
credit: 300,
creditInsurance: null
};
controller.$onInit();
expect(controller._active).toBe(undefined);
controller.active = false;
expect(controller._active).toBe(false);
controller.active = true;
expect(controller._active).toBe(true);
expect(controller.fieldsToShow.id).toBe('id');
});
});
});

View File

@ -0,0 +1,10 @@
vn-descriptor {
.descriptor-header{
background: rgb(255,171,64);
color: white;
text-align: center;
i {
font-size: 51px;
}
}
}

View File

@ -0,0 +1,40 @@
// Generic object to list models, related to the client, with mgCrud
export default class FilterClientList {
constructor($scope, $timeout, $state) {
this.$ = $scope;
this.$timeout = $timeout;
this.$state = $state;
this.waitingMgCrud = 0;
this.clientFk = $state.params.id;
}
onOrder(field, order) {
this.filter(`${field} ${order}`);
}
filter(order) {
if (this.$.index && this.clientFk) {
this.waitingMgCrud = 0;
this.$.index.filter = {
page: 1,
size: 10,
clientFk: this.clientFk
};
if (order) {
this.$.index.filter.order = order;
}
this.$.index.accept();
} else if (!this.clientFk) {
throw new Error('Error: ClientFk not found');
} else if (this.waitingMgCrud > 3) {
throw new Error('Error: Magic Crud is not loaded');
} else {
this.waitingMgCrud++;
this.$timeout(() => {
this.filter(order);
}, 250);
}
}
}
FilterClientList.$inject = ['$scope', '$timeout', '$state'];

View File

@ -12,7 +12,7 @@
<vn-horizontal>
<vn-textfield autofocus vn-two label="Social name" field="$ctrl.client.socialName" vn-acl="administrative"></vn-textfield>
<vn-textfield vn-one label="Tax number" field="$ctrl.client.fi" vn-acl="administrative"></vn-textfield>
<vn-check vn-one label="Equalization tax" field="$ctrl.client.isEqualizated" vn-acl="administrative"></vn-check>
<vn-check vn-one label="Is equalizated" field="$ctrl.client.isEqualizated" vn-acl="administrative"></vn-check>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-two label="Street" field="$ctrl.client.street" vn-focus vn-acl="administrative"></vn-textfield>
@ -49,7 +49,7 @@
<vn-check label="Invoice by address" field="$ctrl.client.hasToInvoiceByAddress" vn-acl="administrative"></vn-check>
</vn-one>
<vn-one>
<vn-check label="Datos comprobados" field="$ctrl.client.isTaxDataChecked" vn-acl="administrative"></vn-check>
<vn-check label="Verified data" field="$ctrl.client.isTaxDataChecked" vn-acl="administrative"></vn-check>
</vn-one>
</vn-horizontal>
<vn-horizontal>
@ -57,7 +57,7 @@
<vn-check label="Has to invoice" field="$ctrl.client.hasToInvoice" vn-acl="administrative"></vn-check>
</vn-one>
<vn-one>
<vn-check vn-one label="Invoice by mail" field="$ctrl.client.invoiceByEmail" vn-acl="administrative"></vn-check>
<vn-check vn-one label="Invoice by mail" field="$ctrl.client.isToBeMailed" vn-acl="administrative"></vn-check>
</vn-one>
<vn-one>
<vn-check vn-one label="Vies" field="$ctrl.client.isVies" vn-acl="administrative"></vn-check>

View File

@ -0,0 +1,30 @@
<mg-ajax path="/client/api/greuges" options="vnPost"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.greuge"
form="form"
save="post">
</vn-watcher>
<form pad-medium ng-submit="$ctrl.onSubmit()">
<vn-card>
<vn-vertical pad-medium>
<vn-title vn-one margin-large-bottom>Add Greuge</vn-title>
<vn-horizontal>
<vn-textfield vn-one margin-medium-right label="Importe" field="$ctrl.greuge.amount" type="number" vn-focus></vn-textfield>
<vn-date-picker vn-one label="Date" model="$ctrl.greuge.shipped"></vn-date-picker>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one margin-medium-right label="Comment" field="$ctrl.greuge.description"></vn-textfield>
<vn-autocomplete vn-one
field="$ctrl.greuge.greugeTypeFk"
url="/client/api/greugeTypes"
label="Type"
>
</vn-autocomplete>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -0,0 +1,25 @@
import ngModule from '../module';
class ClientGreugeCreate {
constructor($scope, $state, $filter) {
this.$ = $scope;
this.$state = $state;
this.greuge = {
shipped: $filter('date')(new Date(), 'yyyy-MM-dd')
};
}
onSubmit() {
this.greuge.clientFk = this.$state.params.id;
this.$.watcher.submit().then(
() => {
this.$state.go('clientCard.greuge.list');
}
);
}
}
ClientGreugeCreate.$inject = ['$scope', '$state', '$filter'];
ngModule.component('vnClientGreugeCreate', {
template: require('./greuge-create.html'),
controller: ClientGreugeCreate
});

View File

@ -0,0 +1,38 @@
<mg-ajax path="/client/api/greuges/filter" options="vnIndexNonAuto"></mg-ajax>
<mg-ajax path="/client/api/greuges/{{edit.params.id}}/sumAmount" options="mgEdit"></mg-ajax>
<vn-card pad-medium>
<vn-vertical pad-medium>
<vn-title vn-one margin-large-bottom>Greuge</vn-title>
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
<vn-column-header vn-one pad-medium-h field="shipped" text="Date" default-order="ASC"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="description" text="Comment"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="amount" text="Amount"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="greugeTypeFk" text="Type"></vn-column-header>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal
class="list list-element text-center"
pad-small-bottom
ng-repeat="greuge in index.model.instances track by greuge.id"
>
<vn-one pad-medium-h>{{::greuge.shipped | date:'dd/MM/yyyy HH:mm' }}</vn-one>
<vn-two pad-medium-h>{{::greuge.description}}</vn-two>
<vn-one pad-medium-h>{{::greuge.amount | number:2}} €</vn-one>
<vn-one pad-medium-h>{{::greuge.greugeType.name}}</vn-one>
</vn-horizontal>
</vn-one>
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
<vn-horizontal vn-one class="list list-footer text-center">
<vn-one pad-medium-h></vn-one>
<vn-two pad-medium-h></vn-two>
<vn-one pad-medium-h ng-if="index.model.count > 0">{{edit.model.sumAmount | number:2}} €</vn-one>
<vn-one pad-medium-h></vn-one>
</vn-horizontal>
<vn-paging margin-large-top vn-one index="index" total="index.model.count"></vn-paging>
</vn-vertical>
</vn-card>
<a ui-sref="clientCard.greuge.create" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>

View File

@ -0,0 +1,9 @@
import ngModule from '../module';
import FilterClientList from '../filterClientList';
class ClientGreugeList extends FilterClientList {}
ngModule.component('vnClientGreugeList', {
template: require('./greuge-list.html'),
controller: ClientGreugeList
});

View File

@ -0,0 +1,7 @@
{
"Date" : "Fecha",
"Comment" : "Comentario",
"Amount" : "Importe",
"Type": "Tipo",
"Add Greuge": "Añadir Greuge"
}

View File

@ -2,7 +2,11 @@
"Active": "Activo",
"Client": "Cliente",
"Clients": "Clientes",
"Basic data": "Datos básicos",
"Fiscal data": "Datos Fiscales",
"Addresses": "Consignatarios",
"Web access": "Acceso web",
"Notes": "Notas",
"Has to invoice": "Factura",
"Invoice by mail": "Factura impresa",
"Country": "País",
@ -12,5 +16,9 @@
"Province": "Provincia",
"Save": "Guardar",
"Pay method" : "Forma de pago",
"Address": "Consignatario"
"Address": "Consignatario",
"Credit" : "Crédito",
"Secured credit": "Crédito asegurado",
"Verified data": "Datos comprobados",
"Mandate": "Mandato"
}

View File

@ -0,0 +1,5 @@
{
"Company": "Empresa",
"Register date": "Fecha alta",
"End date": "Fecha baja"
}

View File

@ -0,0 +1,31 @@
<mg-ajax path="/client/api/Mandates/filter" options="vnIndexNonAuto"></mg-ajax>
<vn-card pad-medium>
<vn-vertical pad-medium>
<vn-title vn-one margin-large-bottom>Mandate</vn-title>
<vn-grid-header on-order="$ctrl.onOrder(field, order)">
<vn-column-header vn-one pad-medium-h field="id" text="Id"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="companyFk" text="Company"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="mandateTypeFk" text="Type"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="created" text="Register date" default-order="ASC"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="finished" text="End date"></vn-column-header>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal
vn-one class="list list-element text-center"
pad-small-bottom
ng-repeat="mandate in index.model.instances track by mandate.id"
>
<vn-one pad-medium-h>{{::mandate.id}}</vn-one>
<vn-one pad-medium-h>{{::mandate.company.code}}</vn-one>
<vn-one pad-medium-h>{{::mandate.mandateType.name}}</vn-one>
<vn-one pad-medium-h>{{::mandate.created | date:'dd/MM/yyyy HH:mm' }}</vn-one>
<vn-one pad-medium-h>{{::mandate.finished | date:'dd/MM/yyyy HH:mm' || '-'}}</vn-one>
</vn-horizontal>
</vn-one>
<vn-one class="text-center pad-small-v" ng-if="index.model.count === 0" translate>No results</vn-one>
<vn-horizontal vn-one class="list list-footer"></vn-horizontal>
<vn-paging vn-one margin-large-top index="index" total="index.model.count"></vn-paging>
</vn-vertical>
</vn-card>

View File

@ -0,0 +1,7 @@
import ngModule from '../module';
import FilterClientList from '../filterClientList';
ngModule.component('vnClientMandate', {
template: require('./mandate.html'),
controller: FilterClientList
});

View File

@ -1,3 +0,0 @@
{
"Notes": "Notas"
}

View File

@ -1,7 +1,6 @@
{
"User": "Usuario",
"Enable web access": "Habilitar acceso web",
"Web access": "Acceso web",
"New password": "Nueva contraseña",
"Repeat password": "Repetir contraseña",
"Change password": "Cambiar contraseña"

View File

@ -1,11 +1,22 @@
<div class="{{$ctrl.className}}" ng-mouseover="$ctrl.mouseIsOver = true" ng-mouseleave="$ctrl.mouseIsOver = false">
<vn-horizontal ng-if="$ctrl.text" class="orderly" ng-click="$ctrl.onClick()">
<vn-none class="title" translate>
{{::$ctrl.text}}
<vn-horizontal ng-if="$ctrl.text" class="orderly">
<vn-none
class="title"
ng-class="{'noDrop': $ctrl.orderLocked, 'pointer' : !$ctrl.orderLocked}"
ng-click="$ctrl.onClick($event)" translate>
{{::$ctrl.text}}
</vn-none>
<vn-none>
<vn-icon icon="arrow_drop_down" ng-if="$ctrl.showArrow('DESC')"></vn-icon>
<vn-icon icon="arrow_drop_up" ng-if="$ctrl.showArrow('ASC')"></vn-icon>
<vn-none ng-if="!$ctrl.orderLocked">
<vn-icon
icon="arrow_drop_down"
ng-class="{'active': $ctrl.showArrow('DESC')}"
ng-click="$ctrl.onClick($event, 'DESC')"
></vn-icon>
<vn-icon
icon="arrow_drop_up"
ng-class="{'active': $ctrl.showArrow('ASC')}"
ng-click="$ctrl.onClick($event, 'ASC')"
></vn-icon>
</vn-none>
</vn-horizontal>
<ng-transclude ng-if="!$ctrl.text"></ng-transclude>

View File

@ -1,19 +1,29 @@
import {module} from '../module';
export default class ColumnHeader {
constructor() {
constructor($attrs) {
this.order = undefined;
this.mouseIsOver = false;
this.orderLocked = ($attrs.orderLocked !== undefined);
}
onClick() {
if (this.order === 'ASC') {
this.order = 'DESC';
} else {
this.order = 'ASC';
onClick(event, order) {
if (!this.orderLocked) {
if (order) {
this.order = order;
} else if (this.order === 'ASC') {
this.order = 'DESC';
} else {
this.order = 'ASC';
}
this.gridHeader.selectColum(this);
}
this.gridHeader.selectColum(this);
if (event)
event.preventDefault();
}
showArrow(type) {
if (this.orderLocked)
return false;
let showArrow = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order === type);
let showOther = (this.gridHeader && this.gridHeader.currentColumn && this.gridHeader.currentColumn.field === this.field && this.order !== type);
if (type === 'DESC' && this.mouseIsOver && !showOther) {
@ -22,13 +32,13 @@ export default class ColumnHeader {
return showArrow;
}
$onInit() {
if (this.defaultOrder) {
if (this.defaultOrder && !this.orderLocked) {
this.order = this.defaultOrder;
this.onClick();
}
}
}
ColumnHeader.$inject = [];
ColumnHeader.$inject = ['$attrs'];
module.component('vnColumnHeader', {
template: require('./column-header.html'),

View File

@ -3,6 +3,8 @@ import './column-header.js';
describe('Component vnColumnHeader', () => {
let $componentController;
let controller;
let $event;
let $attrs;
beforeEach(() => {
angular.mock.module('client');
@ -10,14 +12,18 @@ describe('Component vnColumnHeader', () => {
beforeEach(angular.mock.inject(_$componentController_ => {
$componentController = _$componentController_;
controller = $componentController('vnColumnHeader', {});
$event = {
preventDefault: () => {}
};
$attrs = {};
controller = $componentController('vnColumnHeader', {$attrs});
}));
describe('onClick()', () => {
it(`should change the ordenation to DESC (descendant) if it was ASC (ascendant)`, () => {
controller.gridHeader = {selectColum: () => {}};
controller.order = 'ASC';
controller.onClick();
controller.onClick($event);
expect(controller.order).toEqual('DESC');
});
@ -25,7 +31,7 @@ describe('Component vnColumnHeader', () => {
it(`should change the ordenation to ASC (ascendant) if it wasnt ASC`, () => {
controller.gridHeader = {selectColum: () => {}};
controller.order = 'DESC or any other value that might occur';
controller.onClick();
controller.onClick($event);
expect(controller.order).toEqual('ASC');
});
@ -34,7 +40,7 @@ describe('Component vnColumnHeader', () => {
controller.gridHeader = {selectColum: () => {}};
controller.order = 'Change me!';
spyOn(controller.gridHeader, 'selectColum');
controller.onClick();
controller.onClick($event);
expect(controller.gridHeader.selectColum).toHaveBeenCalledWith(controller);
});

View File

@ -4,7 +4,8 @@
ng-focus="$ctrl.hasFocus = true"
ng-blur="$ctrl.hasFocus = false"
ng-mouseenter="$ctrl.hasMouseIn = true"
ng-mouseleave="$ctrl.hasMouseIn = false"
ng-mouseleave="$ctrl.hasMouseIn = false"
ng-click="$ctrl.onClick()"
>
<input type="text"
class="mdl-textfield__input"

View File

@ -18,12 +18,14 @@ export const formatEquivalence = {
};
class DatePicker extends Component {
constructor($element, $translate, $filter, $timeout) {
constructor($element, $translate, $filter, $timeout, $attrs) {
super($element);
this.input = $element[0].querySelector('input');
this.$translate = $translate;
this.$filter = $filter;
this.$timeout = $timeout;
this.$attrs = $attrs;
this.enabled = true;
this._modelView = null;
this._model = undefined;
@ -59,6 +61,11 @@ class DatePicker extends Component {
onClear() {
this.modelView = null;
}
onClick() {
if (this.vp) {
this.vp.open();
}
}
mdlUpdate() {
let mdlField = this.element.firstChild.MaterialTextfield;
if (mdlField)
@ -163,21 +170,38 @@ class DatePicker extends Component {
}
);
}
if (this.$attrs.hasOwnProperty('today')) {
this.iniOptions.defaultDate = new Date();
}
this._optionsChecked = true;
return this.iniOptions;
}
$onInit() {
initPicker() {
this.iniOptions = this._getOptions();
this.isTimePicker = (this.iniOptions && this.iniOptions.enableTime && this.iniOptions.noCalendar);
this.vp = new Flatpickr(this.input, this.iniOptions);
if (this.iniOptions.defaultDate) {
this.modelView = this.vp.formatDate(this.iniOptions.defaultDate, this.iniOptions.dateFormat);
}
}
$onDestroy() {
destroyPicker() {
if (this.vp)
this.vp.destroy();
this.vp = undefined;
}
$onInit() {
this.initPicker();
}
$onDestroy() {
this.destroyPicker();
}
}
DatePicker.$inject = ['$element', '$translate', '$filter', '$timeout'];
DatePicker.$inject = ['$element', '$translate', '$filter', '$timeout', '$attrs'];
module.component('vnDatePicker', {
template: require('./datePicker.html'),

View File

@ -2,9 +2,10 @@ import './datePicker.js';
describe('Component vnDatePicker', () => {
let $componentController;
let $scope;
let $filter;
let $timeout;
let $element;
let $attrs;
let $translate;
let controller;
@ -12,13 +13,14 @@ describe('Component vnDatePicker', () => {
angular.mock.module('client');
});
beforeEach(angular.mock.inject((_$componentController_, $rootScope, _$timeout_, _$translate_) => {
beforeEach(angular.mock.inject((_$componentController_, _$filter_, _$timeout_, _$translate_) => {
$componentController = _$componentController_;
$scope = $rootScope.$new();
$filter = _$filter_;
$timeout = _$timeout_;
$element = angular.element(`<div><input></div>`);
$translate = _$translate_;
controller = $componentController('vnDatePicker', {$scope, $element, $translate, $timeout});
$attrs = {};
controller = $componentController('vnDatePicker', {$element, $translate, $filter, $timeout, $attrs});
}));
describe('_formatFlat2Angular()', () => {

View File

@ -0,0 +1,186 @@
describe('Directive validation', () => {
let scope;
let element;
let compile;
beforeEach(() => {
angular.mock.module('client');
});
compile = (_element, validations, value) => {
inject(($compile, $rootScope, aclService, _$timeout_, $window) => {
$window.validations = validations;
scope = $rootScope.$new();
scope.user = {name: value};
element = angular.element(_element);
$compile(element)(scope);
scope.$digest();
});
};
it(`should throw an error if the vnValidation doesn't have the right syntax`, () => {
let html = `<input type="name" ng-model="user.name" vn-validation="user"/>`;
expect(() => {
compile(html, {});
}).toThrow(new Error(`vnValidation: Attribute must have this syntax: [entity].[field]`));
});
it('should throw an error if the window.validations aint defined', () => {
let html = `<input type="name" ng-model="user.name" vn-validation="user.name"/>`;
expect(() => {
compile(html, {});
}).toThrow(new Error(`vnValidation: Entity 'User' doesn't exist`));
});
describe('Validator presence()', () => {
it('should not validate the user name as it is an empty string', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'presence'}]}}};
compile(html, validations, 'Spiderman');
scope.user.name = '';
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
});
describe('Validator absence()', () => {
it('should not validate the entity as it should be an empty string', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'absence'}]}}};
compile(html, validations, 'Spiderman');
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
it('should validate the entity as it is an empty string', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'absence'}]}}};
compile(html, validations, '');
scope.$digest();
expect(element[0].classList).toContain('ng-valid');
expect(element[0].classList).not.toContain('ng-invalid');
});
});
describe('Validator length()', () => {
it('should not validate the user name as it should have min length of 15', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'length', min: 10, max: 50, is: 15}]}}};
compile(html, validations, 'fifteen!');
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
it('should validate the user name as it has length of 15', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'length', min: 10, max: 50, is: 15}]}}};
compile(html, validations, 'fifteen length!');
scope.$digest();
expect(element[0].classList).toContain('ng-valid');
expect(element[0].classList).not.toContain('ng-invalid');
});
it('should not validate the user name as it should have min length of 10', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'length', min: 10}]}}};
compile(html, validations, 'shortname');
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
it('should validate the user name as its length is greater then the minimum', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'length', min: 10}]}}};
compile(html, validations, 'verylongname');
scope.$digest();
expect(element[0].classList).toContain('ng-valid');
expect(element[0].classList).not.toContain('ng-invalid');
});
it('should not validate the user name as its length is greater then the maximum', () => {
let html = `<form><input type="name" ng-model="user.name" vn-validation="user.name"/></form>`;
let validations = {User: {validations: {name: [{validation: 'length', max: 10}]}}};
compile(html, validations, 'toolongname');
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
});
describe('Validator numericality()', () => {
it('should not validate the phone number as it should a integer', () => {
let html = `<form><input type="text" ng-model="user.phone" vn-validation="user.phone"/></form>`;
let validations = {User: {validations: {phone: [{validation: 'numericality', is: 'what is this?'}]}}};
compile(html, validations, 'spiderman');
scope.user.phone = 'this is not a phone number!';
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
it('should validate the phone number as it an integer', () => {
let html = `<form><input type="text" ng-model="user.phone" vn-validation="user.phone"/></form>`;
let validations = {User: {validations: {phone: [{validation: 'numericality', is: 'what is this?'}]}}};
compile(html, validations, 'spiderman');
scope.user.phone = '555555555';
scope.$digest();
expect(element[0].classList).toContain('ng-valid');
expect(element[0].classList).not.toContain('ng-invalid');
});
});
describe('Validator inclusion()', () => {
it('should not validate the phone number as it is not an integer', () => {
let html = `<form><input type="text" ng-model="user.phone" vn-validation="user.phone"/></form>`;
let validations = {User: {validations: {phone: [{validation: 'inclusion'}]}}};
compile(html, validations, 'spiderman');
scope.user.phone = 'this is not a phone number!';
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
});
describe('Validator exclusion()', () => {
it('should validate the phone number as it is an integer', () => {
let html = `<form><input type="text" ng-model="user.phone" vn-validation="user.phone"/></form>`;
let validations = {User: {validations: {phone: [{validation: 'exclusion'}]}}};
compile(html, validations, 'spiderman');
scope.user.phone = '555555555';
scope.$digest();
expect(element[0].classList).toContain('ng-valid');
expect(element[0].classList).not.toContain('ng-invalid');
});
});
describe('Validator format()', () => {
it('should not validate the email number as it doesnt contain @', () => {
let html = `<form><input type="text" ng-model="user.email" vn-validation="user.email"/></form>`;
let validations = {User: {validations: {email: [{validation: 'format', with: '@'}]}}};
compile(html, validations, 'spiderman');
scope.user.email = 'userverdnatura.es';
scope.$digest();
expect(element[0].classList).toContain('ng-invalid');
expect(element[0].classList).not.toContain('ng-valid');
});
});
});

View File

@ -40,7 +40,7 @@ export function directive(interpolate, compile, $window) {
let errorShown = false;
input.$options.$$options.allowInvalid = true;
input.$validators.entity = function(value) {
input.$validators.entity = value => {
try {
validateAll(value, validations);
return true;
@ -51,9 +51,9 @@ export function directive(interpolate, compile, $window) {
}
};
scope.$watch(function() {
scope.$watch(() => {
return (form.$submitted || input.$dirty) && input.$invalid;
}, function(value) {
}, value => {
let parent = element.parent();
if (value) {

View File

@ -1,4 +1,4 @@
<vn-vertical class="dropdown-body" ng-show="$ctrl.show">
<vn-vertical class="dropdown-body" ng-if="$ctrl.show">
<vn-auto ng-show="$ctrl.filter" class="filter">
<vn-horizontal>
<input vn-one placeholder="{{'Search' | translate}}" type="text" ng-model="$ctrl.search"/>

View File

@ -7,20 +7,24 @@ export default class DropDown {
this.$filter = $filter;
this.$timeout = $timeout;
this.container = $element[0].querySelector('ul.dropdown');
this._search = null;
this.itemsFiltered = [];
this._activeOption = -1;
this._focusingFilter = false;
this._tryToShow = 0;
}
get container() {
return this.$element[0].querySelector('ul.dropdown');
}
get show() {
return this._show;
}
set show(value) {
let oldValue = this.show;
// I wait up to 1 second if the dropdown opens but there is no data to show
// It wait up to 1 second if the dropdown opens but there is no data to show
if (value && !oldValue && !this.itemsFiltered.length && this._tryToShow < 4) {
this.$timeout(() => {
this._tryToShow++;
@ -29,10 +33,7 @@ export default class DropDown {
} else {
this._tryToShow = 0;
this._show = value;
this._setFocusInFilterInput(value, oldValue);
this.$timeout(() => {
this._calculatePosition(value, oldValue);
});
this._toggleDropDown(value, oldValue);
}
}
@ -68,16 +69,41 @@ export default class DropDown {
});
}
_setFocusInFilterInput(value, oldValue) {
if (value && !this._focusingFilter && oldValue !== value && this.filter) {
let inputFilterSearch = this.$element[0].querySelector('input');
this._focusingFilter = true;
_toggleDropDown(value, oldValue) {
if (value && !this._focusingFilter && !oldValue && this.filter) {
// open dropDown
this.$timeout(() => { // wait angular ngIf
this._setFocusInFilterInput();
this._eventScroll(value);
});
} else if (!value && oldValue) {
// close dropDown
this._eventScroll(value);
}
this.$timeout(() => {
this._calculatePosition(value, oldValue);
});
}
_eventScroll(add) {
if (add) {
this.container.addEventListener('scroll', e => this.loadFromScroll(e));
} else {
this.container.removeEventListener('scroll', e => this.loadFromScroll(e));
}
}
_setFocusInFilterInput() {
let inputFilterSearch = this.$element[0].querySelector('input');
this._focusingFilter = true;
if (inputFilterSearch)
this.$timeout(() => {
inputFilterSearch.focus();
this._focusingFilter = false;
}, 250);
}
}
_background(create) {
let el = document.getElementById('ddBack');
if (el) {
@ -184,10 +210,12 @@ export default class DropDown {
}
setScrollPosition() {
let child = this.$element[0].querySelector('ul.dropdown li.active');
let childRect = child.getBoundingClientRect();
let containerRect = this.container.getBoundingClientRect();
if (typeof child.scrollIntoView === 'function' && (childRect.top > containerRect.top + containerRect.height || childRect.top < containerRect.top)) {
child.scrollIntoView();
if (child) {
let childRect = child.getBoundingClientRect();
let containerRect = this.container.getBoundingClientRect();
if (typeof child.scrollIntoView === 'function' && (childRect.top > containerRect.top + containerRect.height || childRect.top < containerRect.top)) {
child.scrollIntoView();
}
}
}
selectItem(item) {
@ -222,14 +250,10 @@ export default class DropDown {
$onInit() {
if (this.parent)
this.parent.addEventListener('keydown', e => this.onKeydown(e));
if (this.container)
this.container.addEventListener('scroll', e => this.loadFromScroll(e));
}
$onDestroy() {
if (this.parent)
this.parent.removeEventListener('keydown', e => this.onKeydown(e));
if (this.container)
this.container.removeEventListener('scroll', e => this.loadFromScroll(e));
}
}

View File

@ -140,14 +140,6 @@ describe('Component vnDropDown', () => {
});
describe('$onChanges()', () => {
it(`should set the top css of the $element`, () => {
let argumentObject = {show: true, top: {currentValue: 100}};
spyOn(controller.$element, 'css');
controller.$onChanges(argumentObject);
expect(controller.$element.css).toHaveBeenCalledWith('top', '100px');
});
it(`should set the width css of the $element`, () => {
let argumentObject = {show: true, itemWidth: {currentValue: 100}};
spyOn(controller.$element, 'css');
@ -295,26 +287,40 @@ describe('Component vnDropDown', () => {
controller.selectItem(item);
expect(controller.selected).toEqual(item);
expect(controller._show).toEqual(true);
expect(controller._show).not.toBeDefined();
});
});
describe('loadItems()', () => {
it(`should set controller._show to true`, () => {
it(`should set controller.show to true`, () => {
controller.show = false;
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.loadItems();
expect(controller._show).toEqual(true);
expect(controller.show).toEqual(true);
});
it(`should call loadMore() and then set controller._show to true`, () => {
it(`should call loadMore() and then set controller._show to true if there are items`, () => {
controller.showLoadMore = () => {};
controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.itemsFiltered = [{id: 1, name: 'Batman'}, {id: 2, name: 'Bruce'}, {id: 3, name: 'Logan'}, {id: 4, name: 'Wolverine'}];
controller.loadItems();
expect(controller._show).toEqual(true);
expect(controller.loadMore).toHaveBeenCalledWith();
});
it(`should call loadMore() and then set controller._show to undefined if there are not items`, () => {
controller.showLoadMore = () => {};
controller.loadMore = () => {};
spyOn(controller, 'loadMore');
controller.itemsFiltered = [];
controller.loadItems();
expect(controller._show).not.toBeDefined();
expect(controller.loadMore).toHaveBeenCalledWith();
});
});
describe('$onInit()', () => {

View File

@ -2,7 +2,6 @@ vn-grid-header {
border-bottom: 3px solid #9D9D9D;
font-weight: bold;
.orderly{
cursor: pointer;
text-align: center;
white-space: nowrap;
justify-content: center;
@ -11,13 +10,18 @@ vn-grid-header {
}
}
vn-icon{
line-height: 17px;
font-size: 17px;
margin: 0;
padding: 0;
display: inline;
i {
padding-top: 3px;
padding: 0;
margin: -2px -17px 0 0;
opacity: 0.2;
cursor: pointer;
}
&.active {
i {
opacity: 1;
}
}
}
[min-none]{

View File

@ -12,7 +12,7 @@ export default class App {
this.$rootScope = $rootScope;
}
show(message) {
if (this.snackbar) this.snackbar.show({message: message});
if (this.snackbar) this.snackbar.show({message: message, timeout: 400});
}
showMessage(message) {
this.show(message);

View File

@ -0,0 +1,9 @@
import {module} from '../module';
const isFullEmpty = item => {
return (!item && item !== 0) || (typeof item === 'object' && !Object.keys(item).length);
};
export default isFullEmpty;
export const NAME = 'isFullEmpty';
module.value(NAME, isFullEmpty);

View File

@ -0,0 +1,50 @@
describe('Service acl', () => {
let aclService;
beforeEach(() => {
angular.mock.module('vnCore');
});
beforeEach(angular.mock.module($provide => {
$provide.value('aclConstant', {});
}));
beforeEach(inject((_aclService_, $httpBackend) => {
aclService = _aclService_;
}));
it("should return false as the service doesn't have roles", () => {
expect(aclService.routeHasPermission('http://www.verdnatura.es')).toBeFalsy();
});
it("should return true as the service has roles but the route has no acl", () => {
aclService.roles = {customer: true};
expect(aclService.routeHasPermission('http://www.verdnatura.es')).toBeTruthy();
});
it("should return false as the service roles have no length", () => {
aclService.roles = {};
let route = {url: 'http://www.verdnatura.es', acl: []};
expect(aclService.routeHasPermission(route)).toBeFalsy();
});
it("should call the service aclPermission() function and return false as the service has roles and the rote has acl without length", () => {
aclService.roles = {customer: true, employee: true};
let route = {url: 'http://www.verdnatura.es', acl: []};
spyOn(aclService, 'aclPermission').and.callThrough();
expect(aclService.routeHasPermission(route)).toBeFalsy();
expect(aclService.aclPermission).toHaveBeenCalledWith(route.acl);
});
it("should call the service aclPermission() function to return true as the service has roles matching with the ones in acl", () => {
aclService.roles = {customer: true, employee: true};
let route = {url: 'http://www.verdnatura.es', acl: ['customer']};
spyOn(aclService, 'aclPermission').and.callThrough();
expect(aclService.routeHasPermission(route)).toBeTruthy();
expect(aclService.aclPermission).toHaveBeenCalledWith(route.acl);
});
});

View File

@ -1,19 +1,20 @@
import {validator} from 'vendor';
export const validators = {
presence: function(value, conf) {
presence: value => {
if (validator.isEmpty(value))
throw new Error(`Value can't be empty`);
},
absence: function(value, conf) {
absence: value => {
if (!validator.isEmpty(value))
throw new Error(`Value should be empty`);
},
length: function(value, conf) {
length: (value, conf) => {
let options = {
min: conf.min || conf.is,
max: conf.max || conf.is
};
if (!validator.isLength(value, options)) {
if (conf.is) {
throw new Error(`Value should be ${conf.is} characters long`);
@ -26,26 +27,26 @@ export const validators = {
}
}
},
numericality: function(value, conf) {
numericality: (value, conf) => {
if (conf.int) {
if (!validator.isInt(value))
throw new Error(`Value should be integer`);
} else if (!validator.isNumeric(value))
throw new Error(`Value should be a number`);
},
inclusion: function(value, conf) {
inclusion: (value, conf) => {
if (!validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
exclusion: function(value, conf) {
exclusion: (value, conf) => {
if (validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
format: function(value, conf) {
format: (value, conf) => {
if (!validator.matches(value, conf.with))
throw new Error(`Invalid value`);
},
custom: function(value, conf) {
custom: (value, conf) => {
if (!conf.bindedFunction(value))
throw new Error(`Invalid value`);
}

View File

@ -7,13 +7,18 @@ vn-textfield {
width: auto;
top: 0px;
right: -6px;
margin: 22px 0px;
background: transparent;
margin: 21px 0px;
background: white;
opacity: 1;
z-index: 9999;
color: #aaa;
}
.material-icons {
font-size: 18px;
float: right;
margin-right: 5px;
}
.material-icons:hover {
color: rgba(0,0,0, .87);
}
}

View File

@ -3,6 +3,7 @@ import Component from '../lib/component';
import getModifiedData from '../lib/modified';
import copyObject from '../lib/copy';
import isEqual from '../lib/equals';
import isFullEmpty from '../lib/fullEmpty';
/**
* Component that checks for changes on a specific model property and
@ -68,9 +69,9 @@ export default class Watcher extends Component {
*
* @param {String} state The state name
*/
submitGo(state) {
submitGo(state, params) {
return this.submit().then(
() => this.$state.go(state)
() => this.$state.go(state, params || {})
);
}
/**
@ -95,7 +96,7 @@ export default class Watcher extends Component {
let changedData = getModifiedData(this.data, this.orgData);
if (this.save) {
this.save.model = changedData;
this.save.model = this.copyInNewObject(changedData);
return new Promise((resolve, reject) => {
this.save.accept().then(
json => this.writeData({data: json}, resolve),
@ -154,7 +155,7 @@ export default class Watcher extends Component {
if (data && typeof data === 'object') {
Object.keys(data).forEach(
val => {
if (data[val] !== "" && data[val] !== undefined && data[val] !== null) {
if (!isFullEmpty(data[val])) {
if (typeof data[val] === 'object') {
newCopy[val] = this.copyInNewObject(data[val]);
} else {

View File

@ -100,11 +100,11 @@ describe('Component vnWatcher', () => {
it(`should call controller.$state.go() function after calling controllers submit() function`, done => {
spyOn(controller, 'submit').and.returnValue(Promise.resolve());
spyOn(controller.$state, 'go');
let state = 'the state';
let state = 'the.State';
controller.submitGo(state)
.then(() => {
expect(controller.submit).toHaveBeenCalledWith();
expect(controller.$state.go).toHaveBeenCalledWith(state);
expect(controller.$state.go).toHaveBeenCalledWith(state, {});
done();
});
});
@ -290,4 +290,3 @@ describe('Component vnWatcher', () => {
});
});
});
// 309

1
client/item/index.js Normal file
View File

@ -0,0 +1 @@
export * from './src/item';

49
client/item/routes.json Normal file
View File

@ -0,0 +1,49 @@
{
"module": "item",
"name": "Items",
"icon": "/static/images/icon_item.png",
"routes": [
{
"url": "/item",
"state": "item",
"abstract": true,
"component": "ui-view"
},
{
"url": "/list",
"state": "item.index",
"component": "vn-item-list"
}, {
"url": "/create",
"state": "item.create",
"component": "vn-item-create"
}, {
"url": "/:id",
"state": "item.card",
"abstract": true,
"component": "vn-item-card"
}, {
"url" : "/data",
"state": "item.card.data",
"component": "vn-item-data",
"params": {
"item": "$ctrl.item"
},
"menu": {
"description": "Basic data",
"icon": "folder"
}
}, {
"url" : "/image",
"state": "item.card.image",
"component": "vn-item-image",
"params": {
"item": "$ctrl.item"
},
"menu": {
"description": "Images",
"icon": "image"
}
}
]
}

View File

@ -0,0 +1,16 @@
<vn-main-block>
<vn-horizontal>
<vn-auto class="left-block">
<vn-card margin-medium-v>
<a class="item-product-link pad-large text-center" ui-sref="item.index">
<b>{{$ctrl.item.name}}</b>
<img ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}" />
</a>
</vn-card>
<vn-left-menu></vn-left-menu>
</vn-auto>
<vn-one>
<vn-vertical margin-medium ui-view></vn-vertical>
</vn-one>
</vn-horizontal>
</vn-main-block>

View File

@ -0,0 +1,32 @@
import ngModule from '../module';
class ItemCard {
constructor($http, $state) {
this.$http = $http;
this.$state = $state;
this.item = {};
}
$onInit() {
let filter = {
include: [
{relation: "itemType"},
{relation: "origin"},
{relation: "ink"},
{relation: "producer"},
{relation: "intrastat"}
]
};
this.$http.get(`/item/api/Items/${this.$state.params.id}?filter=${JSON.stringify(filter)}`).then(
res => {
this.item = res.data;
}
);
}
}
ItemCard.$inject = ['$http', '$state'];
ngModule.component('vnItemCard', {
template: require('./item-card.html'),
controller: ItemCard
});

View File

@ -0,0 +1,66 @@
<mg-ajax path="/item/api/Items" options="vnPost"></mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.item"
form="form"
save="post">
</vn-watcher>
<form name="form" ng-submit="$ctrl.onSubmit()" margin-medium>
<div style="max-width: 70em; margin: 0 auto;">
<vn-card>
<vn-vertical pad-large>
<vn-title>Create item</vn-title>
<vn-horizontal>
<vn-textfield vn-one label="Size" field="$ctrl.item.size" vn-focus></vn-textfield>
<vn-textfield vn-five label="Category" field="$ctrl.item.category"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Stems" field="$ctrl.item.stems"></vn-textfield>
<vn-textfield vn-five label="Description" field="$ctrl.item.description"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/ItemTypes"
label="Type"
show-field="name"
value-field="id"
field="$ctrl.item.typeFk"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Inks"
label="Ink"
show-field="name"
value-field="id"
field="$ctrl.item.inkFk"
>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/Origins"
label="Origin"
show-field="name"
value-field="id"
field="$ctrl.item.originFk"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Producers"
label="Producer"
show-field="name"
value-field="id"
field="$ctrl.item.producerFk"
>
</vn-autocomplete>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Create"></vn-submit>
</vn-button-bar>
</div>
</form>

View File

@ -0,0 +1,18 @@
import ngModule from '../module';
class ItemCreate {
constructor() {
this.item = {};
}
onSubmit() {
this.$.watcher.submit().then(
json => this.$state.go('item.card.basic', {id: json.data.id})
);
}
}
ngModule.component('vnItemCreate', {
template: require('./item-create.html'),
controller: ItemCreate
});

View File

@ -0,0 +1,84 @@
<mg-ajax
path="/item/api/Items/{{patch.params.id}}"
options="vnPatch"
override="{filter: {include: [{relation: 'itemType'}, {relation: 'origin'}, {relation: 'ink'}, {relation: 'producer'}]}}"
>
</mg-ajax>
<vn-watcher
vn-id="watcher"
data="$ctrl.item"
form="form"
save="patch">
</vn-watcher>
<form name="form" ng-submit="watcher.submit()" ng-cloak>
<vn-card>
<vn-vertical pad-large>
<vn-title>Basic data</vn-title>
<vn-horizontal>
<vn-textfield vn-three label="Name" field="$ctrl.item.name" vn-focus></vn-textfield>
<vn-textfield vn-one label="Size" field="$ctrl.item.size"></vn-textfield>
<vn-textfield vn-one label="Stems" field="$ctrl.item.stems"></vn-textfield>
<vn-textfield vn-one label="Category" field="$ctrl.item.category"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Description" field="$ctrl.item.description"></vn-textfield>
<vn-autocomplete vn-one
url="/item/api/Intrastats"
label="Intrastat"
show-field="description"
value-field="id"
field="$ctrl.item.intrastatFk"
initial-data="$ctrl.item.intrastat"
order = "description DESC"
filter-search="{where: {description: {regexp: 'search'}}}"
>
<tpl-item>{{$parent.$parent.item.description}}</tpl-item>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/ItemTypes"
label="Type"
show-field="name"
value-field="id"
field="$ctrl.item.typeFk"
initial-data="$ctrl.item.itemType"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Inks"
label="Ink"
show-field="name"
value-field="id"
field="$ctrl.item.inkFk"
initial-data="$ctrl.item.ink"
>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/Origins"
label="Origin"
show-field="name"
value-field="id"
field="$ctrl.item.originFk"
initial-data="$ctrl.item.origin"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Producers"
label="Producer"
show-field="name"
value-field="id"
field="$ctrl.item.producer"
>
</vn-autocomplete>
</vn-horizontal>
</vn-vertical>
</vn-card>
<vn-button-bar>
<vn-submit label="Save"></vn-submit>
</vn-button-bar>
</form>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
ngModule.component('vnItemData', {
template: require('./item-data.html'),
bindings: {
item: '<'
}
});

View File

@ -0,0 +1,58 @@
<div pad-large style="min-width: 30em">
<form ng-submit="$ctrl.onSearch()">
<vn-horizontal>
<vn-textfield vn-one label="Id" model="$ctrl.filter.id" vn-focus></vn-textfield>
<vn-textfield vn-three label="Description" model="$ctrl.filter.description"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield vn-one label="Category" type="number" model="$ctrl.filter.category"></vn-textfield>
<vn-textfield vn-one label="Size" type="number" model="$ctrl.filter.itemSize"></vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/ItemTypes"
label="Type"
show-field="name"
value-field="id"
field="$ctrl.filter.typeFk"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Inks"
label="Ink"
show-field="name"
value-field="id"
field="$ctrl.filter.inkFk"
>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete vn-one
url="/item/api/Origins"
label="Origin"
show-field="name"
value-field="id"
field="$ctrl.filter.originFk"
>
</vn-autocomplete>
<vn-autocomplete vn-one
url="/item/api/Producers"
label="Producer"
show-field="name"
value-field="id"
field="$ctrl.filter.producerFk"
>
</vn-autocomplete>
</vn-horizontal>
<vn-horizontal margin-large-top>
<vn-submit label="Search"></vn-submit>
</vn-horizontal>
</form>
</div>

View File

@ -0,0 +1,16 @@
import ngModule from '../module';
class ItemFilterPanel {
constructor() {
this.onSubmit = () => {};
}
onSearch() {
this.onSubmit(this.filter);
}
}
ngModule.component('vnItemFilterPanel', {
template: require('./filter-panel.html'),
controller: ItemFilterPanel
});

View File

@ -0,0 +1,5 @@
{
"Ink": "Tinta",
"Origin": "Origen",
"Producer": "Productor"
}

7
client/item/src/item.js Normal file
View File

@ -0,0 +1,7 @@
export * from './module';
import './list/list';
import './filter-panel/filter-panel';
import './create/item-create';
import './card/item-card';
import './data/item-data';

View File

@ -0,0 +1,14 @@
<vn-horizontal pad-medium border-solid-bottom>
<vn-auto margin-medium-right ng-if="$ctrl.item.image">
<img ng-src="http://verdnatura.es/vn-image-data/catalog/200x200/{{$ctrl.item.image}}" />
</vn-auto>
<vn-one>
<div><span translate>Id</span>: <b>{{$ctrl.item.id}}</b></div>
<div><span translate>Name</span>: <b>{{$ctrl.item.name}}</b></div>
<div><span translate>Description</span>: <b>{{$ctrl.item.description}}</b></div>
<div><span translate>Size</span>: <b>{{$ctrl.item.size}}</b></div>
<div><span translate>Type</span>: <b>{{$ctrl.item.itemType.name}}</b></div>
</vn-one>
</vn-horizontal>

View File

@ -0,0 +1,8 @@
import ngModule from '../module';
ngModule.component('vnItemProduct', {
template: require('./item-product.html'),
bindings: {
item: '<'
}
});

View File

@ -0,0 +1,26 @@
<mg-ajax path="/item/api/Items/filter" options="mgIndex"></mg-ajax>
<div margin-medium>
<div style="max-width: 40em; margin: 0 auto;">
<vn-card>
<vn-horizontal pad-medium>
<vn-searchbar vn-one
index="index"
on-search="$ctrl.search(index)"
advanced="true"
popover="vn-item-filter-panel"
ignore-keys = "['page', 'size', 'search']"
>
</vn-searchbar>
</vn-horizontal>
</vn-card>
<vn-card margin-medium-top>
<a class="item-product-link" ng-repeat="item in index.model.instances" ui-sref="item.card.data({ id: {{item.id}} })" >
<vn-item-product title="View item" item="item"></vn-item-product>
</a>
</vn-card>
<vn-paging index="index" total="index.model.count"></vn-paging>
</div>
<a ui-sref="item.create" fixed-bottom-right>
<vn-float-button icon="add"></vn-float-button>
</a>
</div>

View File

@ -0,0 +1,17 @@
import ngModule from '../module';
import './item-product';
import './style.css';
class ItemList {
constructor() {
this.model = {};
}
search(index) {
index.accept();
}
}
ngModule.component('vnItemList', {
template: require('./list.html'),
controller: ItemList
});

View File

@ -0,0 +1,20 @@
vn-item-product {
display: block;
}
a.item-product-link {
display: block;
text-decoration: none;
color: inherit;
}
a.item-product-link:hover {
color: white;
background-color: #424242;
}
vn-item-product img {
max-width: 150px;
}
.vn-item-product-name {
font-family: vn-font-bold;
}

View File

@ -0,0 +1,8 @@
{
"Items": "Artículos",
"Item": "Artículo",
"Category": "Categoría",
"Description": "Descripción",
"Size": "Tamaño",
"Type": "Tipo"
}

View File

@ -0,0 +1,5 @@
import {ng} from 'vendor';
import 'core';
const ngModule = ng.module('item', ['vnCore']);
export default ngModule;

View File

@ -5,5 +5,6 @@
"client": [],
"production": [],
"route": [],
"locator": []
"locator": [],
"item": []
}

View File

@ -31,7 +31,7 @@
</vn-horizontal>
<vn-horizontal vn-one margin-large-bottom>
<vn-one>
<vn-production-actions tickets="$ctrl.tickets" states="$ctrl.sharedData.states" hour-items="$ctrl.sharedData.hourItems"></vn-production-actions>
<vn-production-actions></vn-production-actions>
</vn-one>
<vn-two></vn-two>
</vn-horizontal>

View File

@ -22,5 +22,9 @@
"Province" : "Provincia",
"Filter" : "Filtrar",
"Cancel" : "Cancelar",
"Worker" : "Trabajador",
"Town" : "Población",
"Client ID" : "ID Cliente",
"Ticket with incidence" : "Ticket con incidencia"
}

View File

@ -1,7 +1,7 @@
<vn-horizontal class="actionPanel">
<vn-button vn-none margin-medium-right label="Printed" ng-click="$ctrl.doAction('markPrinted')"></vn-button>
<vn-none margin-medium-right>
<vn-icon-menu icon="assignment" items="$ctrl.states" selected="$ctrl.actionState"></vn-icon-menu>
<vn-icon-menu icon="assignment" items="$ctrl.parent.sharedData.states" selected="$ctrl.actionState"></vn-icon-menu>
</vn-none>
<vn-none margin-medium-right>
<vn-icon-button icon="textsms" ng-click="$ctrl.doAction('addComment')"></vn-icon-button>
@ -10,6 +10,6 @@
<vn-icon-menu icon="person" url="/client/api/Clients/employeeList" selected="$ctrl.actionWorker"></vn-icon-menu>
</vn-none>
<vn-none margin-medium-right>
<vn-icon-menu icon="query_builder" items="$ctrl.hourItems" selected="$ctrl.actionHours"></vn-icon-menu>
<vn-icon-menu icon="query_builder" items="$ctrl.parent.sharedData.hourItems" selected="$ctrl.actionHours"></vn-icon-menu>
</vn-none>
</vn-horizontal>

View File

@ -35,45 +35,35 @@ export default class ProductionActions {
return this._actionWorker;
}
_changeState(ids, sateteId, stateName, index) {
this.$http.put(`/production/api/TicketStates/${sateteId}/changeState`, {tickets: ids}).then(
_changeState(ids, sateteId) {
this.$http.put(`/production/api/TicketStates/${sateteId}/changeState`, {tickets: ids})
.then(
() => {
index.forEach(
i => {
this.tickets[i].state = stateName;
this.tickets[i].stateFk = sateteId;
}
);
this.parent.searchTickets();
}
);
}
_sendMessage(tickets) {
this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets}).then(
() => {
this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
}
);
this.$http.post(`/production/api/FakeProductions/messageSend`, {tickets: tickets})
.then(
() => {
this.vnApp.showMessage(this.$translate.instant('Success: message send!'));
}
);
}
_changeTime(ids, time, index) {
this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids}).then(
this.$http.put(`/production/api/Tickets/${time}/changeTime`, {tickets: ids})
.then(
() => {
index.forEach(
i => {
this.tickets[i].hour = time;
}
);
this.parent.searchTickets();
}
);
}
_changeWorker(ids, workerFk, index) {
this.$http.put(`/production/api/Tickets/${workerFk}/changeWorker`, {tickets: ids}).then(
this.$http.put(`/production/api/Tickets/${workerFk}/changeWorker`, {tickets: ids})
.then(
() => {
index.forEach(
i => {
this.tickets[i].workerFk = this.actionWorker.id;
this.tickets[i].worker = this.actionWorker.name;
}
);
this.parent.searchTickets();
}
);
}
@ -82,7 +72,7 @@ export default class ProductionActions {
let ids = [];
let index = [];
let tickets = [];
this.tickets.forEach(
this.parent.tickets.forEach(
(val, i) => {
if (val.checked) {
ids.push(val.ticketFk);
@ -94,13 +84,13 @@ export default class ProductionActions {
if (tickets.length) {
switch (actionName) {
case 'changeState' :
this._changeState(ids, this.actionState.id, this.actionState.name, index);
this._changeState(ids, this.actionState.id);
break;
case 'addComment':
this._sendMessage(tickets);
break;
case 'markPrinted':
this._changeState(ids, 4, 'Impreso', index);
this._changeState(ids, 4);
break;
case 'changeTime':
this._changeTime(ids, this.actionHours.name, index);
@ -121,10 +111,8 @@ ProductionActions.$inject = ['$http', '$translate', 'vnApp'];
ngModule.component('vnProductionActions', {
template: require('./production-actions.html'),
bindings: {
tickets: '<',
states: '<',
hourItems: '<'
},
controller: ProductionActions
controller: ProductionActions,
require: {
parent: '^^vnProductionIndex'
}
});

View File

@ -8,6 +8,7 @@
<vn-column-header vn-two pad-medium-h field="agency" text="Agency"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="routeFk" text="Route ID"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="salesPerson" text="Commercial"></vn-column-header>
<vn-column-header vn-two pad-medium-h field="worker" text="Worker"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="hour" text="Hour"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="state" text="State"></vn-column-header>
<vn-column-header vn-one pad-medium-h field="lines" text="Lines"></vn-column-header>
@ -16,7 +17,7 @@
<vn-none min-none></vn-none>
</vn-grid-header>
<vn-one class="list list-content">
<vn-horizontal vn-one class="list list-element text-center" ng-repeat="ticket in $ctrl.pageTable.model track by ticket.id" ng-class="{warning: ticket.problem==='RIESGO'}">
<vn-horizontal vn-one class="list list-element text-center" ng-repeat="ticket in $ctrl.pageTable.model" ng-class="{warning: ticket.problem==='RIESGO'}">
<vn-none>
<vn-icon margin-small-left icon="report_problem" ng-if="ticket.problem" vn-tooltip="{{ticket.problem}}" tooltip-position="right"></vn-icon>
</vn-none>
@ -27,8 +28,9 @@
<vn-two pad-medium-h>{{::ticket.agency}}</vn-two>
<vn-one pad-medium-h>{{::ticket.routeFk}}</vn-one>
<vn-two pad-medium-h>{{::ticket.salesPerson | ucwords}}</vn-two>
<vn-one pad-medium-h>{{ticket.hour}}</vn-one>
<vn-one pad-medium-h>{{ticket.state}}</vn-one>
<vn-two pad-medium-h>{{::ticket.worker | ucwords}}</vn-two>
<vn-one pad-medium-h>{{::ticket.hour}}</vn-one>
<vn-one pad-medium-h>{{::ticket.state}}</vn-one>
<vn-one pad-medium-h>{{::ticket.lines}}</vn-one>
<vn-one pad-medium-h>{{::ticket.m3}}</vn-one>
<vn-one pad-medium-h>{{::ticket.boxes}}</vn-one>
@ -44,10 +46,15 @@
<span translate="Resultados"></span>:
<span>{{$ctrl.footer.total}}</span>
</vn-one>
<vn-seven pad-medium-h></vn-seven>
<vn-two pad-medium-h></vn-two>
<vn-one pad-medium-h></vn-one>
<vn-two pad-medium-h></vn-two>
<vn-two pad-medium-h></vn-two>
<vn-one pad-medium-h></vn-one>
<vn-one pad-medium-h></vn-one>
<vn-one pad-medium-h text-center>{{$ctrl.footer.lines}}</vn-one>
<vn-one pad-medium-h text-center>{{$ctrl.footer.meters}}</vn-one>
<vn-one></vn-one>
<vn-one pad-medium-h></vn-one>
<vn-none></vn-none>
</vn-horizontal>
<vn-one>

View File

@ -9,7 +9,7 @@ export default class MenuActions {
switchItem() {
if (!this.items || !this.items.length) return;
let stateName = this.$state.current.name.replace('create', 'list').replace('edit', 'list');
let stateName = this.$state.current.name.replace('.create', '.list').replace('.edit', '.list');
for (let i = 0; i < this.items.length; i++) {
this.items[i].active = (this.items[i].href === stateName);

View File

@ -47,9 +47,8 @@ function config($stateProvider, $urlRouterProvider, aclServiceProvider, modulesF
for (let i = 0; i < count; i++) {
let route = fileRoutes[i];
if (aclService.routeHasPermission(route)) {
$stateProvider.state(route.state, {
let configRoute = {
url: route.url,
abstract: route.abstract || false,
template: `<${route.component} ${getParams(route)}></${route.component}>`,
resolve: {
loader: loader(moduleName, validations)
@ -57,7 +56,13 @@ function config($stateProvider, $urlRouterProvider, aclServiceProvider, modulesF
data: {
routes: fileRoutes
}
});
};
if (route.abstract)
configRoute.abstract = true;
if (route.routeParams)
configRoute.params = route.routeParams;
$stateProvider.state(route.state, configRoute);
} else if (route.state === mainModule.state) {
break;
}

View File

@ -12,5 +12,10 @@
"Routes" : "Rutas",
"Production" : "Producción",
"Modules access" : "Acceso a módulos",
"Locator": "Localizador"
"Locator": "Localizador",
"Items": "Artículos",
"name": "Nombre",
"credit": "Crédito",
"phone": "Teléfono",
"creditInsurance": "Crédito Asegurado"
}

View File

@ -43,3 +43,14 @@ export const locator = () => {
};
core.splitingRegister.register('locator', locator);
export const item = () => {
return new Promise(resolve => {
require.ensure([], () => {
require('item');
resolve('item');
}, 'item');
});
};
core.splitingRegister.register('item', item);

View File

@ -95,3 +95,21 @@ html [vn-center], .vn-center{
html [pointer], .pointer{
cursor: pointer;
}
html [noDrop], .noDrop{
cursor: no-drop;
}
vn-main-block {
display:block;
max-width: 1920px;
width:100%;
margin: 0 auto;
.left-block {
max-width: 20em;
min-width: 18em;
padding-left: 1em;
padding-bottom: 1em;
}
}

View File

@ -88,6 +88,18 @@ services:
- "3006"
ports:
- "3006:3006"
item:
environment:
- NODE_ENV=${NODE_ENV}
container_name: "${BRANCH_NAME}-item"
image: "item:${TAG}"
build:
context: ./services
dockerfile: /item/Dockerfile
expose:
- "3007"
ports:
- "3007:3007"
nginx:
container_name: "${BRANCH_NAME}-nginx"
image: "nginx:${TAG}"

View File

@ -4,6 +4,7 @@
// delete me, this comment is to add a commit
export default {
vnTextfield: 'vn-textfield > div > input',
vnTextarea: 'vn-textarea',
vnSubmit: 'vn-submit > input',
vnTopbar: 'vn-topbar > header',
vnIcon: 'vn-icon',
@ -14,5 +15,6 @@ export default {
vnFloatButton: 'vn-float-button > button',
vnMenuItem: 'vn-menu-item > li > a',
vnAutocomplete: 'vn-autocomplete',
vnCheck: 'vn-check'
vnCheck: 'vn-check',
vnIconButton: 'vn-icon-button'
};

View File

@ -122,11 +122,27 @@ Nightmare.action('waitForNumberOfElements', function(selector, count, done) {
Nightmare.action('waitForTextInElement', function(selector, name, done) {
this.wait((resultSelector, expectedName) => {
return document.querySelectorAll(resultSelector)[0].innerText.toLowerCase().includes(expectedName.toLowerCase());
return document.querySelector(resultSelector).innerText.toLowerCase().includes(expectedName.toLowerCase());
}, selector, name)
.then(done);
});
Nightmare.action('changeLanguageToEnglish', function(done) {
this.wait(selectors.globalItems.languageButton)
.evaluate(selector => {
return document.querySelector(selector).title;
}, selectors.globalItems.languageButton)
.then(result => {
if (result === 'Cambiar idioma') {
this.click(selectors.globalItems.languageButton)
.then(done);
}
if (result === 'Change language') {
this.then(done);
}
});
});
Nightmare.action('waitForSnackbarReset', function(done) {
this.wait(() => {
return document.querySelector('vn-snackbar').innerText === '';

View File

@ -13,7 +13,7 @@ export default function createNightmare(width = 1100, height = 600) {
fail(message);
}
if (type === 'log') {
console.log(message);
// console.log(message);
}
});
return nightmare;

View File

@ -10,6 +10,7 @@ export default {
globalItems: {
topBar: `${components.vnTopbar}`,
logOutButton: `${components.vnIcon}[icon="exit_to_app"]`,
languageButton: `${components.vnIcon}[icon="language"]`,
snackbarIsActive: '.mdl-snackbar--active > .mdl-snackbar__text',
applicationsMenuButton: `${components.vnIcon}[icon="apps"]`,
applicationsMenuVisible: `${components.vnMainMenu} .is-visible > div`,
@ -30,35 +31,95 @@ export default {
socialName: `${components.vnTextfield}[name="socialName"]`,
userName: `${components.vnTextfield}[name="userName"]`,
email: `${components.vnTextfield}[name="email"]`,
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > ${components.vnTextfield}`,
salesBruceBannerOption: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`,
createButton: `${components.vnSubmit}`
},
basicData: {
basicDataButton: `${components.vnMenuItem}[ui-sref="clientCard.basicData"]`,
nameInput: `${components.vnTextfield}[name="name"]`,
taxNumberInput: `${components.vnTextfield}[name="fi"]`,
socialNameInput: `${components.vnTextfield}[name="socialName"]`,
contactInput: `${components.vnTextfield}[name="contact"]`,
phoneInput: `${components.vnTextfield}[name="phone"]`,
mobileInput: `${components.vnTextfield}[name="mobile"]`,
faxInput: `${components.vnTextfield}[name="fax"]`,
emailInput: `${components.vnTextfield}[name="email"]`,
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"]`,
salesPersonInput: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > ${components.vnTextfield}`,
salesBruceBannerOption: `${components.vnAutocomplete}[field="$ctrl.client.salesPersonFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(1)`,
channelInput: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] > vn-vertical > ${components.vnTextfield}`,
channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-one:nth-child(2) > ul > li:nth-child(3)`,
channelMetropolisOption: `${components.vnAutocomplete}[field="$ctrl.client.contactChannelFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(3)`,
saveButton: `${components.vnSubmit}`
},
fiscalData: {
fiscalDataButton: `${components.vnMenuItem}[ui-sref="clientCard.fiscalData"]`,
hasToInvoiceCheckboxLabel: `${components.vnCheck}[label='Has to invoice'] > label`,
hasToInvoiceCheckboxInput: `${components.vnCheck}[label='Has to invoice'] > label > label > input`,
invoiceByMailCheckboxLabel: `${components.vnCheck}[label='Invoice by mail'] > label`,
invoiceByMailCheckboxInput: `${components.vnCheck}[label='Invoice by mail'] > label > label > input`,
socialNameInput: `${components.vnTextfield}[name="socialName"]`,
fiscalIdInput: `${components.vnTextfield}[name="fi"]`,
equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
acceptPropagationButton: `body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-fiscal-data > vn-dialog > div > form > div.button-bar > tpl-buttons > button:nth-child(2)`,
addressInput: `${components.vnTextfield}[name="street"]`,
cityInput: `${components.vnTextfield}[name="city"]`,
postcodeInput: `${components.vnTextfield}[name="postcode"]`,
provinceInput: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] > vn-vertical > ${components.vnTextfield}`,
provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-one:nth-child(2) > ul > li:nth-child(5)`,
provinceFifthOption: `${components.vnAutocomplete}[field="$ctrl.client.provinceFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(5)`,
countryInput: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] > vn-vertical > ${components.vnTextfield}`,
countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] > vn-vertical > vn-drop-down > vn-vertical > vn-one:nth-child(3) > ul > li:nth-child(3)`,
countryThirdOption: `${components.vnAutocomplete}[field="$ctrl.client.countryFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(3)`,
activeCheckboxLabel: `${components.vnCheck}[label='Active'] > label`,
invoiceByAddressCheckboxInput: `${components.vnCheck}[label='Invoice by address'] > label > input`,
verifiedDataCheckboxInput: `${components.vnCheck}[label='Verified data'] > label > input`,
hasToInvoiceCheckboxLabel: `${components.vnCheck}[label='Has to invoice'] > label`,
invoiceByMailCheckboxLabel: `${components.vnCheck}[label='Invoice by mail'] > label`,
viesCheckboxInput: `${components.vnCheck}[label='Vies'] > label > input`,
saveButton: `${components.vnSubmit}`
},
payMethod: {
payMethodButton: `${components.vnMenuItem}[ui-sref="clientCard.billingData"]`,
payMethodInput: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > ${components.vnTextfield}`,
payMethodIBANOption: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(5)`,
payMethodOptionOne: `${components.vnAutocomplete}[field="$ctrl.client.payMethodFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`,
IBANInput: `${components.vnTextfield}[name="iban"]`,
dueDayInput: `${components.vnTextfield}[name="dueDay"]`,
cancelNotificationButton: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > vn-client-billing-data > vn-dialog > div > form > div.button-bar > tpl-buttons > button:nth-child(1)',
saveButton: `${components.vnSubmit}`
},
addresses: {
addressesButton: `${components.vnMenuItem}[ui-sref="clientCard.addresses.list"]`,
createAddress: `${components.vnFloatButton}`,
defaultCheckboxInput: `${components.vnCheck}[label='Default'] > label > input`,
consigneeInput: `${components.vnTextfield}[name="consignee"]`,
streetAddressInput: `${components.vnTextfield}[name="street"]`,
postcodeInput: `${components.vnTextfield}[name="postcode"]`,
cityInput: `${components.vnTextfield}[name="city"]`,
provinceInput: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] > vn-vertical > ${components.vnTextfield}`,
provinceSecondOption: `${components.vnAutocomplete}[field="$ctrl.address.provinceFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`,
agencyInput: `${components.vnAutocomplete}[field="$ctrl.address.agencyFk"] > vn-vertical > ${components.vnTextfield}`,
agenctySecondOption: `${components.vnAutocomplete}[field="$ctrl.address.agencyFk"] > vn-vertical > vn-drop-down > vn-vertical:not(.ng-hide) > vn-auto:nth-child(2) > ul > li:nth-child(2)`,
phoneInput: `${components.vnTextfield}[name="phone"]`,
mobileInput: `${components.vnTextfield}[name="mobile"]`,
defaultAddress: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-addresses > vn-vertical > vn-card > div > vn-vertical > vn-horizontal:nth-child(2) > vn-one > vn-horizontal > vn-one > div:nth-child(2)',
secondMakeDefaultStar: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-addresses > vn-vertical > vn-card > div > vn-vertical > vn-horizontal:nth-child(3) > vn-one > vn-horizontal > vn-none > i',
firstEditButton: `${components.vnIconButton}[icon='edit']`,
secondEditButton: `vn-horizontal:nth-child(3) > vn-one > vn-horizontal > a > ${components.vnIconButton}[icon='edit']`,
activeCheckbox: `${components.vnCheck}[label='Enabled'] > label > input`,
equalizationTaxCheckboxLabel: `${components.vnCheck}[label='Is equalizated'] > label > input`,
saveButton: `${components.vnSubmit}`
},
webAccess: {
webAccessButton: `${components.vnMenuItem}[ui-sref="clientCard.webAccess"]`,
enableWebAccessCheckbox: `${components.vnCheck}[label='Enable web access'] > label > input`,
userNameInput: `${components.vnTextfield}[name="name"]`,
saveButton: `${components.vnSubmit}`
},
notes: {
notesButton: `${components.vnMenuItem}[ui-sref="clientCard.notes.list"]`,
addNoteFloatButton: `${components.vnFloatButton}`,
noteInput: `${components.vnTextarea}[label="Note"]`,
saveButton: `${components.vnSubmit}`,
firstNoteText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-notes > vn-card > div > vn-vertical > vn-one:nth-child(2) > vn-horizontal:nth-child(2) > b'
},
credit: {
creditButton: `${components.vnMenuItem}[ui-sref="clientCard.credit.list"]`,
addCreditFloatButton: `${components.vnFloatButton}`,
creditInput: `${components.vnTextfield}[name="credit"]`,
saveButton: `${components.vnSubmit}`,
firstCreditText: 'body > vn-app > vn-vertical > vn-vertical > vn-client-card > vn-main-block > vn-horizontal > vn-one > vn-vertical > ui-view > vn-client-credit-list > vn-card > div > vn-vertical > vn-one > vn-horizontal:nth-child(1) > vn-one'
}
};

View File

@ -5,6 +5,8 @@ import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('create client path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
@ -31,6 +33,15 @@ describe('create client path', () => {
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should access to the clients index by clicking the clients button', done => {
nightmare
.click(selectors.moduleAccessView.clientsSectionButton)
@ -75,7 +86,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('No hay cambios que guardar');
expect(result).toEqual('No changes to save');
done();
})
.catch(catchErrors(done));
@ -89,7 +100,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Error: La instancia`);
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
@ -104,7 +115,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Error: La instancia`);
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
@ -119,7 +130,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Error: La instancia`);
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
@ -134,7 +145,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Error: La instancia`);
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
@ -149,7 +160,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual(`Algunos campos no son válidos`);
expect(result).toEqual('Some fields are invalid');
done();
})
.catch(catchErrors(done));
@ -164,7 +175,22 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Error: La instancia`);
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the create button having all the form fields empty but sales person', done => {
nightmare
.waitToClick(selectors.createClientView.salesPersonInput)
.waitToClick(selectors.createClientView.salesBruceBannerOption)
.wait(200)
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
@ -184,7 +210,7 @@ describe('create client path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`¡Datos guardados!`);
expect(result).toContain('Data saved!');
done();
})
.catch(catchErrors(done));
@ -218,4 +244,3 @@ describe('create client path', () => {
.catch(catchErrors(done));
});
});

View File

@ -5,6 +5,8 @@ import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Edit basicData path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
@ -31,6 +33,15 @@ describe('Edit basicData path', () => {
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
@ -76,12 +87,12 @@ describe('Edit basicData path', () => {
nightmare
.wait(selectors.basicData.nameInput)
.clearInput(selectors.basicData.nameInput)
.type(selectors.basicData.nameInput, 'Carol Danvers Edited')
.type(selectors.basicData.nameInput, 'Ororo Munroe')
.click(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
@ -96,67 +107,37 @@ describe('Edit basicData path', () => {
.wait(selectors.basicData.nameInput)
.getInputValue(selectors.basicData.nameInput)
.then(result => {
expect(result).toEqual('Carol Danvers Edited');
expect(result).toEqual('Ororo Munroe');
done();
})
.catch(catchErrors(done));
});
it('should edit the tax number', done => {
it('should edit the contact name', done => {
nightmare
.wait(selectors.basicData.taxNumberInput)
.clearInput(selectors.basicData.taxNumberInput)
.type(selectors.basicData.taxNumberInput, 'AVG tax Edited')
.wait(selectors.basicData.contactInput)
.clearInput(selectors.basicData.contactInput)
.type(selectors.basicData.contactInput, 'Black Panther')
.click(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the tax number have been edited', done => {
it('should confirm the contact name have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.taxNumberInput)
.getInputValue(selectors.basicData.taxNumberInput)
.wait(selectors.basicData.contactInput)
.getInputValue(selectors.basicData.contactInput)
.then(result => {
expect(result).toEqual('AVG tax Edited');
done();
})
.catch(catchErrors(done));
});
it('should edit the social name', done => {
nightmare
.wait(selectors.basicData.socialNameInput)
.clearInput(selectors.basicData.socialNameInput)
.type(selectors.basicData.socialNameInput, 'Avengers Team Edited')
.click(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the social name have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.socialNameInput)
.getInputValue(selectors.basicData.socialNameInput)
.then(result => {
expect(result).toEqual('Avengers Team Edited');
expect(result).toEqual('Black Panther');
done();
})
.catch(catchErrors(done));
@ -171,7 +152,7 @@ describe('Edit basicData path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
@ -201,7 +182,7 @@ describe('Edit basicData path', () => {
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
@ -222,46 +203,16 @@ describe('Edit basicData path', () => {
.catch(catchErrors(done));
});
it('should add the fax number', done => {
nightmare
.wait(selectors.basicData.faxInput)
.clearInput(selectors.basicData.faxInput)
.type(selectors.basicData.faxInput, '432198765')
.click(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the fax number have been added', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.faxInput)
.getInputValue(selectors.basicData.faxInput)
.then(result => {
expect(result).toEqual('432198765');
done();
})
.catch(catchErrors(done));
});
it('should edit the email', done => {
nightmare
.wait(selectors.basicData.emailInput)
.clearInput(selectors.basicData.emailInput)
.type(selectors.basicData.emailInput, 'CarolDanversEdited@verdnatura.es')
.type(selectors.basicData.emailInput, 'Storm@verdnatura.es')
.click(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
@ -276,35 +227,52 @@ describe('Edit basicData path', () => {
.wait(selectors.basicData.emailInput)
.getInputValue(selectors.basicData.emailInput)
.then(result => {
expect(result).toEqual('CarolDanversEdited@verdnatura.es');
expect(result).toEqual('Storm@verdnatura.es');
done();
})
.catch(catchErrors(done));
});
// it('should select the sales person', done => {
// nightmare
// .wait(selectors.basicData.salesPersonInput)
// .select(selectors.basicData.salesPersonInput, '') // not working quite yet
// .click(selectors.basicData.saveButton)
// .wait(selectors.globalItems.snackbarIsActive)
// .getInnerText(selectors.globalItems.snackbarIsActive)
// .then(result => {
// expect(result).toEqual('¡Datos guardados!');
// done();
// })
// .catch(catchErrors(done));
// });
it('should select the sales person', done => {
nightmare
.waitToClick(selectors.basicData.salesPersonInput)
.waitToClick(selectors.basicData.salesBruceBannerOption)
.wait(200)
.waitToClick(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the sales person have been selected', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.waitToClick(selectors.basicData.basicDataButton)
.wait(200)
.getInputValue(selectors.basicData.salesPersonInput)
.then(result => {
expect(result).toEqual('Bruce Banner');
done();
})
.catch(catchErrors(done));
});
it('should select the channel', done => {
nightmare
.waitToClick(selectors.basicData.channelInput)
.waitToClick(selectors.basicData.channelMetropolisOption)
.wait(400)
.waitToClick(selectors.basicData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
@ -313,10 +281,10 @@ describe('Edit basicData path', () => {
it('should confirm the channel have been selected', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.fiscalData.fiscalDataButton)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.basicDataButton)
.waitToClick(selectors.basicData.basicDataButton)
.wait(400)
.getInputValue(selectors.basicData.channelInput)
.then(result => {
expect(result).toEqual('Metropolis newspaper');

View File

@ -0,0 +1,579 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Edit fiscalData path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
describe('Confirm all addresses have EQtax for future propagation test', () => {
it(`should click on the search result to access to the client's addresses`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.addresses.addressesButton)
.waitForURL('/addresses/list')
.url()
.then(url => {
expect(url).toContain('/addresses/list');
done();
})
.catch(catchErrors(done));
});
it(`should click on the 1st edit icon to check EQtax is checked`, done => {
nightmare
.waitToClick(selectors.addresses.firstEditButton)
.wait(selectors.addresses.equalizationTaxCheckboxLabel)
.wait(200)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.addresses.equalizationTaxCheckboxLabel)
.then(value => {
expect(value).toBeTruthy();
done();
})
.catch(catchErrors(done));
});
it(`should go back to addresses then select the second one and confirm the EQtax is checked`, done => {
nightmare
.waitToClick(selectors.addresses.addressesButton)
.waitToClick(selectors.addresses.secondEditButton)
.wait(selectors.addresses.equalizationTaxCheckboxLabel)
.wait(200)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.addresses.equalizationTaxCheckboxLabel)
.then(value => {
expect(value).toBeTruthy();
done();
})
.catch(catchErrors(done));
});
});
it(`should click on the fiscal data button to start editing`, done => {
nightmare
.waitToClick(selectors.fiscalData.fiscalDataButton)
.waitForURL('fiscal-data')
.url()
.then(url => {
expect(url).toContain('fiscal-data');
done();
})
.catch(catchErrors(done));
});
it('should edit the social name', done => {
nightmare
.wait(selectors.fiscalData.socialNameInput)
.clearInput(selectors.fiscalData.socialNameInput)
.type(selectors.fiscalData.socialNameInput, 'Hulk edited')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the social name have been edited', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.socialNameInput)
.getInputValue(selectors.fiscalData.socialNameInput)
.then(result => {
expect(result).toEqual('Hulk edited');
done();
})
.catch(catchErrors(done));
});
it('should edit the fiscal id', done => {
nightmare
.wait(selectors.fiscalData.fiscalIdInput)
.clearInput(selectors.fiscalData.fiscalIdInput)
.type(selectors.fiscalData.fiscalIdInput, '94980061C')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the fiscal id have been edited', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.fiscalIdInput)
.getInputValue(selectors.fiscalData.fiscalIdInput)
.then(result => {
expect(result).toEqual('94980061C');
done();
})
.catch(catchErrors(done));
});
it('should uncheck the Equalization tax checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.equalizationTaxCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should propagate the Equalization tax', done => {
nightmare
.waitToClick(selectors.fiscalData.acceptPropagationButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm Equalization tax checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.equalizationTaxCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.equalizationTaxCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
describe('Confirm all addresses havent got EQtax as uncheck was propagated', () => {
it(`should click on the addresses button to access to the client's addresses`, done => {
nightmare
.waitToClick(selectors.addresses.addressesButton)
.waitForURL('/addresses/list')
.url()
.then(url => {
expect(url).toContain('/addresses/list');
done();
})
.catch(catchErrors(done));
});
it(`should click on the 1st edit icon to check EQtax is unchecked`, done => {
nightmare
.waitToClick(selectors.addresses.firstEditButton)
.wait(selectors.addresses.equalizationTaxCheckboxLabel)
.wait(200)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.addresses.equalizationTaxCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it(`should go back to addresses then select the second one and confirm the EQtax is checked`, done => {
nightmare
.waitToClick(selectors.addresses.addressesButton)
.waitToClick(selectors.addresses.secondEditButton)
.wait(selectors.addresses.equalizationTaxCheckboxLabel)
.wait(200)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.addresses.equalizationTaxCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
});
it('should go to fiscal data then edit the address', done => {
nightmare
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.clearInput(selectors.fiscalData.addressInput)
.type(selectors.fiscalData.addressInput, 'Somewhere edited')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the address have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.getInputValue(selectors.fiscalData.addressInput)
.then(result => {
expect(result).toEqual('Somewhere edited');
done();
})
.catch(catchErrors(done));
});
it('should edit the city', done => {
nightmare
.wait(selectors.fiscalData.cityInput)
.clearInput(selectors.fiscalData.cityInput)
.type(selectors.fiscalData.cityInput, 'N/A')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the city have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.cityInput)
.getInputValue(selectors.fiscalData.cityInput)
.then(result => {
expect(result).toEqual('N/A');
done();
})
.catch(catchErrors(done));
});
it('should edit the postcode', done => {
nightmare
.wait(selectors.fiscalData.postcodeInput)
.clearInput(selectors.fiscalData.postcodeInput)
.type(selectors.fiscalData.postcodeInput, '12345')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the postcode have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.postcodeInput)
.getInputValue(selectors.fiscalData.postcodeInput)
.then(result => {
expect(result).toEqual('12345');
done();
})
.catch(catchErrors(done));
});
it(`should edit the province`, done => {
nightmare
.waitToClick(selectors.fiscalData.provinceInput)
.waitToClick(selectors.fiscalData.provinceFifthOption)
.wait(200)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it(`should confirm the province have been selected`, done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(200)
.getInputValue(selectors.fiscalData.provinceInput)
.then(result => {
expect(result).toEqual('Province two');
done();
})
.catch(catchErrors(done));
});
it('should uncheck the active checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.activeCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm active checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.activeCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.activeCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should check the invoice by address checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.invoiceByAddressCheckboxInput)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm invoice by address checkbox is checked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.invoiceByAddressCheckboxInput)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.invoiceByAddressCheckboxInput)
.then(value => {
expect(value).toBeTruthy();
done();
})
.catch(catchErrors(done));
});
it('should check the Verified data checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.verifiedDataCheckboxInput)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm Verified data checkbox is checked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.verifiedDataCheckboxInput)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.verifiedDataCheckboxInput)
.then(value => {
expect(value).toBeTruthy();
done();
})
.catch(catchErrors(done));
});
it('should uncheck the Has to invoice checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.hasToInvoiceCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm Has to invoice checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.hasToInvoiceCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.hasToInvoiceCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should uncheck the Invoice by mail checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.invoiceByMailCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm Invoice by mail checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.invoiceByMailCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.invoiceByMailCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should check the Vies checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.viesCheckboxInput)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm Vies checkbox is checked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.viesCheckboxInput)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.viesCheckboxInput)
.then(value => {
expect(value).toBeTruthy();
done();
})
.catch(catchErrors(done));
});
});

View File

@ -0,0 +1,194 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Edit pay method path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's pay method`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.payMethod.payMethodButton)
.waitForURL('billing-data')
.url()
.then(url => {
expect(url).toContain('billing-data');
done();
})
.catch(catchErrors(done));
});
it(`should edit the Pay method to any without IBAN`, done => {
nightmare
.waitToClick(selectors.payMethod.payMethodInput)
.waitToClick(selectors.payMethod.payMethodOptionOne)
.wait(200)
.waitToClick(selectors.payMethod.saveButton)
.waitToClick(selectors.payMethod.cancelNotificationButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it(`should confirm the Pay method have been selected`, done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.payMethod.payMethodButton)
.wait(200)
.getInputValue(selectors.payMethod.payMethodInput)
.then(result => {
expect(result).toEqual('PayMethod one');
done();
})
.catch(catchErrors(done));
});
it(`should receive an error when changing payMethod to IBAN without an IBAN entered`, done => {
nightmare
.waitToClick(selectors.payMethod.payMethodInput)
.waitToClick(selectors.payMethod.payMethodIBANOption)
.wait(200)
.waitToClick(selectors.payMethod.saveButton)
.waitToClick(selectors.payMethod.cancelNotificationButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it(`should add the IBAN`, done => {
nightmare
.type(selectors.payMethod.IBANInput, 'ES91 2100 0418 4502 0005 1332')
.waitToClick(selectors.payMethod.saveButton)
.waitToClick(selectors.payMethod.cancelNotificationButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it(`should confirm the IBAN pay method is sucessfully saved`, done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.payMethod.payMethodButton)
.wait(200)
.getInputValue(selectors.payMethod.payMethodInput)
.then(result => {
expect(result).toEqual('PayMethod with IBAN');
done();
})
.catch(catchErrors(done));
});
// BUG IBAN validation seems to break down whenever the due day is edited plus due day shouldnt accep values above 31.
// it(`should edit the due day`, done => {
// nightmare
// .clearInput(selectors.payMethod.dueDayInput)
// .type(selectors.payMethod.dueDayInput, '25')
// .waitToClick(selectors.payMethod.saveButton)
// .waitToClick(selectors.payMethod.cancelNotificationButton)
// .wait(selectors.globalItems.snackbarIsActive)
// .getInnerText(selectors.globalItems.snackbarIsActive)
// .then(result => {
// expect(result).toEqual('Data saved!');
// done();
// })
// .catch(catchErrors(done));
// });
// it('should confirm the due day have been edited', done => {
// nightmare
// .waitForSnackbarReset()
// .waitToClick(selectors.basicData.basicDataButton)
// .wait(selectors.basicData.nameInput)
// .waitToClick(selectors.payMethod.payMethodButton)
// .wait(selectors.payMethod.dueDayInput)
// .getInputValue(selectors.payMethod.dueDayInput)
// .then(result => {
// expect(result).toEqual('25');
// done();
// })
// .catch(catchErrors(done));
// });
});

View File

@ -0,0 +1,301 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Edit addresses path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's pay method`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.addresses.addressesButton)
.waitForURL('addresses/list')
.url()
.then(url => {
expect(url).toContain('addresses/list');
done();
})
.catch(catchErrors(done));
});
it(`should click on the add new address button to access to the new address form`, done => {
nightmare
.waitToClick(selectors.addresses.createAddress)
.waitForURL('addresses/create')
.url()
.then(url => {
expect(url).toContain('addresses/create');
done();
})
.catch(catchErrors(done));
});
it('should check the default checkbox then receive an error after clicking save button as the form is empty', done => {
nightmare
.waitToClick(selectors.addresses.defaultCheckboxInput)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but consignee', done => {
nightmare
.waitForSnackbarReset()
.type(selectors.addresses.consigneeInput, 'Bruce Bunner')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but Street', done => {
nightmare
.waitForSnackbarReset()
.clearInput(selectors.addresses.consigneeInput)
.type(selectors.addresses.streetAddressInput, '320 Park Avenue New York')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but postcode', done => {
nightmare
.waitForSnackbarReset()
.clearInput(selectors.addresses.streetAddressInput)
.type(selectors.addresses.postcodeInput, '10022')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but city', done => {
nightmare
.waitForSnackbarReset()
.clearInput(selectors.addresses.postcodeInput)
.type(selectors.addresses.cityInput, 'New York')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but province', done => {
nightmare
.waitForSnackbarReset()
.clearInput(selectors.addresses.cityInput)
.waitToClick(selectors.addresses.provinceInput)
.waitToClick(selectors.addresses.provinceSecondOption)
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but province and agency', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.addresses.agencyInput)
.waitToClick(selectors.addresses.agenctySecondOption)
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but province, agency and phone', done => {
nightmare
.waitForSnackbarReset()
.type(selectors.addresses.phoneInput, '999887744')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it('should receive an error when clicking the save button having all the form fields empty but province, agency and mobile', done => {
nightmare
.waitForSnackbarReset()
.clearInput(selectors.addresses.phoneInput)
.type(selectors.addresses.mobileInput, '999887744')
.click(selectors.createClientView.createButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
it(`should create a new address with all it's data`, done => {
nightmare
.waitForSnackbarReset()
.type(selectors.addresses.consigneeInput, 'Bruce Bunner')
.type(selectors.addresses.streetAddressInput, '320 Park Avenue New York')
.type(selectors.addresses.postcodeInput, '10022')
.type(selectors.addresses.cityInput, 'New York')
.type(selectors.addresses.phoneInput, '999887744')
.click(selectors.addresses.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Data saved!');
done();
})
.catch(catchErrors(done));
});
it(`should click on the addresses button confirm the new address exists and it's the default one`, done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.addresses.addressesButton)
.wait(selectors.addresses.defaultAddress)
.getInnerText(selectors.addresses.defaultAddress)
.then(result => {
expect(result).toContain('320 Park Avenue New York');
done();
})
.catch(catchErrors(done));
});
it(`should click on the make default icon of the second address then confirm it is the default one now`, done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.addresses.secondMakeDefaultStar)
.waitForTextInElement(selectors.addresses.defaultAddress, 'Somewhere in Thailand')
.getInnerText(selectors.addresses.defaultAddress)
.then(result => {
expect(result).toContain('Somewhere in Thailand');
done();
})
.catch(catchErrors(done));
});
it(`should click on the edit icon of the default address`, done => {
nightmare
.waitForTextInElement(selectors.addresses.defaultAddress, 'Somewhere in Thailand')
.waitToClick(selectors.addresses.firstEditButton)
.waitForURL('/edit')
.url()
.then(result => {
expect(result).toContain('/edit');
done();
})
.catch(catchErrors(done));
});
it(`should click on the active checkbox and receive an error to save it becouse it is the default address`, done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.addresses.activeCheckbox)
.waitToClick(selectors.addresses.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain('Error');
done();
})
.catch(catchErrors(done));
});
});

View File

@ -0,0 +1,146 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Edit web access path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's web access`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.webAccess.webAccessButton)
.waitForURL('web-access')
.url()
.then(url => {
expect(url).toContain('web-access');
done();
})
.catch(catchErrors(done));
});
it(`should click on the Enable web access checkbox to uncheck it`, done => {
nightmare
.waitToClick(selectors.webAccess.enableWebAccessCheckbox)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toContain(`Data saved!`);
done();
})
.catch(catchErrors(done));
});
it('should confirm Enable web access checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.webAccess.webAccessButton)
.wait(selectors.webAccess.enableWebAccessCheckbox)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.webAccess.enableWebAccessCheckbox)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should edit the User name', done => {
nightmare
.wait(selectors.webAccess.userNameInput)
.clearInput(selectors.webAccess.userNameInput)
.type(selectors.webAccess.userNameInput, 'Hulk')
.click(selectors.webAccess.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the User name have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.webAccess.webAccessButton)
.wait(selectors.webAccess.userNameInput)
.getInputValue(selectors.webAccess.userNameInput)
.then(result => {
expect(result).toEqual('Hulk');
done();
})
.catch(catchErrors(done));
});
});

View File

@ -0,0 +1,123 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
describe('Add notes path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's notes`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.notes.notesButton)
.waitForURL('notes/list')
.url()
.then(url => {
expect(url).toContain('notes/list');
done();
})
.catch(catchErrors(done));
});
it(`should click on the add note button`, done => {
nightmare
.waitToClick(selectors.notes.addNoteFloatButton)
.waitForURL('/notes/create')
.url()
.then(url => {
expect(url).toContain('/notes/create');
done();
})
.catch(catchErrors(done));
});
it(`should create a note`, done => {
nightmare
.type(selectors.notes.noteInput, 'Meeting with Black Widow 21th 9am')
.click(selectors.notes.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the note was created', done => {
nightmare
.waitForSnackbarReset()
.wait(selectors.notes.firstNoteText)
.getInnerText(selectors.notes.firstNoteText)
.then(value => {
expect(value).toEqual('Meeting with Black Widow 21th 9am');
done();
})
.catch(catchErrors(done));
});
});

View File

@ -0,0 +1,124 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
import { fail } from 'assert';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
fdescribe('Add credit path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should make sure the language is English', done => {
nightmare
.changeLanguageToEnglish()
.then(() => {
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Petter Parker', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Petter Parker')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's credit`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Petter Parker')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.credit.creditButton)
.waitForURL('credit/list')
.url()
.then(url => {
expect(url).toContain('credit/list');
done();
})
.catch(catchErrors(done));
});
it(`should click on the add credit button`, done => {
nightmare
.waitToClick(selectors.credit.addCreditFloatButton)
.waitForURL('/credit/create')
.url()
.then(url => {
expect(url).toContain('/credit/create');
done();
})
.catch(catchErrors(done));
});
it(`should edit the credit`, done => {
nightmare
.type(selectors.credit.creditInput, 999)
.click(selectors.credit.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('Data saved!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the credit was updated', done => {
nightmare
.waitForSnackbarReset()
.wait(selectors.credit.firstCreditText)
.getInnerText(selectors.credit.firstCreditText)
.then(value => {
expect(value).toContain(999);
done();
})
.catch(catchErrors(done));
});
});

View File

@ -1,283 +0,0 @@
import config from '../helpers/config.js';
import createNightmare from '../helpers/nightmare';
import selectors from '../helpers/selectors.js';
import {catchErrors} from '../../services/utils/jasmineHelpers';
const nightmare = createNightmare();
const moduleAccessViewHashURL = '#!/';
describe('Edit fiscalData path', () => {
describe('warm up', () => {
it('should warm up login and fixtures', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.waitToClick(selectors.globalItems.logOutButton)
.then(() => {
done();
})
.catch(catchErrors(done));
});
});
it('should log in', done => {
nightmare
.login()
.waitForURL(moduleAccessViewHashURL)
.url()
.then(url => {
expect(url).toEqual(config.url + moduleAccessViewHashURL);
done();
})
.catch(catchErrors(done));
});
it('should click on the Clients button of the top bar menu', done => {
nightmare
.waitToClick(selectors.globalItems.applicationsMenuButton)
.wait(selectors.globalItems.applicationsMenuVisible)
.waitToClick(selectors.globalItems.clientsButton)
.wait(selectors.clientsIndex.createClientButton)
.url()
.then(url => {
expect(url).toEqual(config.url + '#!/clients');
done();
})
.catch(catchErrors(done));
});
it('should search for the user Bruce Banner', done => {
nightmare
.wait(selectors.clientsIndex.searchResult)
.type(selectors.clientsIndex.searchClientInput, 'Bruce Banner')
.click(selectors.clientsIndex.searchButton)
.waitForNumberOfElements(selectors.clientsIndex.searchResult, 1)
.countSearchResults(selectors.clientsIndex.searchResult)
.then(result => {
expect(result).toEqual(1);
done();
})
.catch(catchErrors(done));
});
it(`should click on the search result to access to the client's fiscal data`, done => {
nightmare
.waitForTextInElement(selectors.clientsIndex.searchResult, 'Bruce Banner')
.waitToClick(selectors.clientsIndex.searchResult)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.waitForURL('fiscal-data')
.url()
.then(url => {
expect(url).toContain('fiscal-data');
done();
})
.catch(catchErrors(done));
});
it('should uncheck the hasToInvoice checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.hasToInvoiceCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm hasToInvoice checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.hasToInvoiceCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.hasToInvoiceCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should uncheck the invoiceByMail checkbox', done => {
nightmare
.waitToClick(selectors.fiscalData.invoiceByMailCheckboxLabel)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm invoiceByMail checkbox is unchecked', done => {
nightmare
.waitForSnackbarReset()
.waitToClick(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.waitToClick(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.invoiceByMailCheckboxLabel)
.evaluate(selector => {
return document.querySelector(selector).checked;
}, selectors.fiscalData.invoiceByMailCheckboxLabel)
.then(value => {
expect(value).toBeFalsy();
done();
})
.catch(catchErrors(done));
});
it('should edit the address', done => {
nightmare
.wait(selectors.fiscalData.addressInput)
.clearInput(selectors.fiscalData.addressInput)
.type(selectors.fiscalData.addressInput, 'Alpha Flight Low-Orbit')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the address have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.getInputValue(selectors.fiscalData.addressInput)
.then(result => {
expect(result).toEqual('Alpha Flight Low-Orbit');
done();
})
.catch(catchErrors(done));
});
it('should edit the city', done => {
nightmare
.wait(selectors.fiscalData.cityInput)
.clearInput(selectors.fiscalData.cityInput)
.type(selectors.fiscalData.cityInput, 'N/A')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the city have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.cityInput)
.getInputValue(selectors.fiscalData.cityInput)
.then(result => {
expect(result).toEqual('N/A');
done();
})
.catch(catchErrors(done));
});
it('should edit the postcode', done => {
nightmare
.wait(selectors.fiscalData.postcodeInput)
.clearInput(selectors.fiscalData.postcodeInput)
.type(selectors.fiscalData.postcodeInput, '12345')
.click(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual('¡Datos guardados!');
done();
})
.catch(catchErrors(done));
});
it('should confirm the postcode have been edited', done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.postcodeInput)
.getInputValue(selectors.fiscalData.postcodeInput)
.then(result => {
expect(result).toEqual('12345');
done();
})
.catch(catchErrors(done));
});
it(`should edit the province`, done => {
nightmare
.waitToClick(selectors.fiscalData.provinceInput)
.waitToClick(selectors.fiscalData.provinceFifthOption)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual(`¡Datos guardados!`);
done();
})
.catch(catchErrors(done));
});
it(`should confirm the province have been selected`, done => {
nightmare
.waitForSnackbarReset()
.click(selectors.basicData.basicDataButton)
.wait(selectors.basicData.nameInput)
.click(selectors.fiscalData.fiscalDataButton)
.wait(100)
.getInputValue(selectors.fiscalData.provinceInput)
.then(result => {
expect(result).toEqual('Province two');
done();
})
.catch(catchErrors(done));
});
it(`should edit the country`, done => {
nightmare
.waitToClick(selectors.fiscalData.countryInput)
.waitToClick(selectors.fiscalData.countryThirdOption)
.waitToClick(selectors.fiscalData.saveButton)
.wait(selectors.globalItems.snackbarIsActive)
.getInnerText(selectors.globalItems.snackbarIsActive)
.then(result => {
expect(result).toEqual(`¡Datos guardados!`);
done();
})
.catch(catchErrors(done));
});
it(`should confirm the country have been selected`, done => {
nightmare
.waitForSnackbarReset()
.click(selectors.fiscalData.fiscalDataButton)
.wait(selectors.fiscalData.addressInput)
.click(selectors.fiscalData.basicDataButton)
.wait(100)
.getInputValue(selectors.fiscalData.countryInput)
.then(result => {
expect(result).toEqual('Holanda');
done();
})
.catch(catchErrors(done));
});
});

View File

@ -22,7 +22,7 @@ jasmine.loadConfig({
'./e2e/**/*[sS]pec.js'
],
helpers: [
// '/services/utils/jasmineHelpers.js'
'/services/utils/jasmineHelpers.js'
]
});

View File

@ -152,6 +152,35 @@ gulp.task('test', callback => {
return require('./services_tests').start();
});
// e2e tests
gulp.task('e2e', callback => {
runSequence('docker', 'runDockerLogs', 'endToEndTests', callback);
});
gulp.task('runDockerLogs', callback => {
let timer = 0;
let waitForLocaldb = setInterval(() => {
if (timer < 15000) {
timer += 1000;
exec('docker logs dblocal', (err, stdout, stderr) => {
if (stdout.includes('starting as process 1')) {
console.log(stdout);
clearInterval(waitForLocaldb);
callback(err);
}
});
} else {
clearInterval(waitForLocaldb);
}
}, 1000);
});
gulp.task('endToEndTests', callback => {
exec('node e2e_tests', err => {
callback(err);
});
});
// docker dblocal
gulp.task('docker', callback => {
runSequence('deleteDockerDb', 'deleteDockerImageDb', 'buildDockerDb', 'runDockerDb', callback);

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