Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix into 2088-ticket_datosBasicos

This commit is contained in:
Bernat Exposito Domenech 2020-03-12 12:04:35 +01:00
commit 3ab80e1479
364 changed files with 6825 additions and 2967 deletions

View File

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

View File

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

View File

@ -10,8 +10,7 @@ module.exports = Self => {
type: 'Number',
description: 'The document id',
http: {source: 'path'}
},
{
}, {
arg: 'warehouseId',
type: 'Number',
description: 'The warehouse id'
@ -44,9 +43,9 @@ module.exports = Self => {
}
});
Self.updateFile = async(ctx, id, warehouseId, companyId,
dmsTypeId, reference, description, hasFileAttached, options) => {
Self.updateFile = async(ctx, id, options) => {
const models = Self.app.models;
const args = ctx.args;
let tx;
let myOptions = {};
@ -60,20 +59,20 @@ module.exports = Self => {
}
try {
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, dmsTypeId);
const hasWriteRole = await models.DmsType.hasWriteRole(ctx, args.dmsTypeId);
if (!hasWriteRole)
throw new UserError(`You don't have enough privileges`);
const dms = await Self.findById(id, null, myOptions);
await dms.updateAttributes({
dmsTypeFk: dmsTypeId,
companyFk: companyId,
warehouseFk: warehouseId,
reference: reference,
description: description
dmsTypeFk: args.dmsTypeId,
companyFk: args.companyId,
warehouseFk: args.warehouseId,
reference: args.reference,
description: args.description
}, myOptions);
if (hasFileAttached)
if (args.hasFileAttached)
await uploadNewFile(ctx, dms, myOptions);
if (tx) await tx.commit();

View File

@ -1,46 +1,53 @@
{
"name": "Province",
"description": "Provinces of every country",
"base": "VnModel",
"options": {
"mysql": {
"table": "province"
}
},
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
"name": "Province",
"description": "Provinces of every country",
"base": "VnModel",
"options": {
"mysql": {
"table": "province"
}
},
"name": {
"type": "string",
"required": true
}
},
"relations": {
"country": {
"type": "belongsTo",
"model": "Country",
"foreignKey": "countryFk"
"properties": {
"id": {
"type": "Number",
"id": true,
"description": "Identifier"
},
"name": {
"type": "string",
"required": true
}
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
"relations": {
"country": {
"type": "belongsTo",
"model": "Country",
"foreignKey": "countryFk"
},
"warehouse": {
"type": "belongsTo",
"model": "Warehouse",
"foreignKey": "warehouseFk"
},
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
},
"zone": {
"type": "belongsTo",
"model": "Zone",
"foreignKey": "zoneFk"
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
"scopes": {
"location": {
"include": {
"relation": "country"
}
}
},
"acls": [
{
"accessType": "READ",
"principalType": "ROLE",
"principalId": "$everyone",
"permission": "ALLOW"
}
]
}

View File

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

View File

@ -0,0 +1,2 @@
INSERT INTO `salix`.`ACL` (`model`, `property`, `accessType`, `permission`, `principalType`, `principalId`)
VALUES ('EntryLog', '*', 'READ', 'ALLOW', 'ROLE', 'buyer');

View File

@ -0,0 +1,182 @@
DROP procedure IF EXISTS `vn`.`workerTimeControl_check`;
DELIMITER $$
CREATE DEFINER=`root`@`%` PROCEDURE `vn`.`workerTimeControl_check`(vUserFk INT, vTabletFk VARCHAR(100), vTimed DATETIME)
BEGIN
/**
* Verifica si el empleado puede fichar en el momento actual, si puede fichar llama a vn.workerTimeControlAdd
* @param vUserFk Identificador del trabajador
* @return Retorna si encuentra un problema 'odd','maxTimeWork','breakDay','breakWeek' ;
* En caso de tener algun problema retorna el primero que encuentra
*/
DECLARE vLastIn DATETIME ;
DECLARE vLastOut DATETIME ;
DECLARE vDayWorkMax INT;
DECLARE vDayBreak INT;
DECLARE vWeekBreak INT ;
DECLARE vWeekMaxBreak INT;
DECLARE vWeekScope INT;
DECLARE vWeekMaxScope INT;
DECLARE vDayStayMax INT;
DECLARE vAskInOut INT;
DECLARE vTimedWorked INT;
DECLARE vCalendarStateType VARCHAR(20) DEFAULT NULL;
DECLARE vDepartmentFk INT;
DECLARE vTo VARCHAR(50) DEFAULT NULL;
DECLARE vUserName VARCHAR(50) DEFAULT NULL;
DECLARE vBody VARCHAR(255) DEFAULT NULL;
IF (vTimed IS NULL) THEN
SET vTimed = NOW();
END IF;
SELECT dayBreak, weekBreak, weekScope, dayWorkMax, dayStayMax, weekMaxBreak, weekMaxScope, askInOut
INTO vDayBreak, vWeekBreak, vWeekScope, vDayWorkMax, vDayStayMax, vWeekMaxBreak, vWeekMaxScope, vAskInOut
FROM vn.workerTimeControlParams;
SELECT MAX(timed) INTO vLastIn
FROM vn.workerTimeControl
WHERE userFk = vUserFk AND
direction = 'in';
SELECT MAX(timed) INTO vLastOut
FROM vn.workerTimeControl
WHERE userFk = vUserFk AND
direction = 'out';
SELECT email INTO vTo
FROM vn.worker w
WHERE w.id = (SELECT bossFk FROM vn.worker WHERE id = vUserFk);
SELECT CONCAT(firstName,' ',lastName) INTO vUserName
FROM vn.worker w
WHERE w.id = vUserFk;
-- VERIFICAR CONTRATO EN VIGOR
IF (SELECT COUNT(*)
FROM postgresql.business b
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
JOIN postgresql.person p ON p.person_id = pr.person_id
JOIN vn.worker w ON w.id = p.id_trabajador
WHERE w.userFk = vUserFk AND
b.date_start <= CURDATE() AND
IFNULL(b.date_end,CURDATE()) >= CURDATE()
) = 0 THEN
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No hay un contrato en vigor") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw("No hay un contrato en vigor");
END IF;
-- VERIFICAR DEPARTAMENTO
IF vTabletFk IS NOT NULL THEN
IF ( SELECT COUNT(*)
FROM vn.tabletDepartment td
JOIN vn.workerTimeControlUserInfo wtcu ON wtcu.departmentFk = td.departmentFk
WHERE td.tabletFk = vTabletFk AND wtcu.userFk = vUserFk
) = 0 THEN
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"No perteneces a este departamento.") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw("No perteneces a este departamento.");
END IF;
END IF;
SELECT IFNULL(dayBreak, vDayBreak) INTO vDayBreak
FROM postgresql.business b
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
JOIN postgresql.person p ON p.person_id = pr.person_id
JOIN postgresql. business_labour bl ON b.business_id = bl.business_id
JOIN postgresql.professional_category pc ON bl.professional_category_id = pc.professional_category_id
WHERE p.id_trabajador = vUserFk AND
b.date_start <= DATE(vTimed) AND
IFNULL(b.date_end, DATE(vTimed)) >= DATE(vTimed);
-- VERIFICAR DESCANSO DIARIO
-- 12 / 9 horas dependiendo del valor de vDayBreak
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vDayBreak THEN
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vDayBreak/3600,0) ," h") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw(CONCAT("Descansos ", FORMAT(vDayBreak/3600,0) ," h"));
END IF;
-- VERIFICAR FICHADAS IMPARES DEL ÃÆÅ¡LTIMO DÃÆÍA QUE SE FICHÃÆââ¬Å“
IF (SELECT MOD(COUNT(*),2) -- <>0
FROM vn.workerTimeControl
WHERE userFk = vUserFk AND
timed >= vLastIn
) THEN
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Dias con fichadas impares") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw("Dias con fichadas impares");
END IF;
-- VERIFICAR VACACIONES
SELECT cs.type INTO vCalendarStateType
FROM postgresql.calendar_employee ce
JOIN postgresql.business b USING(business_id)
JOIN postgresql.profile pr ON pr.profile_id = b.client_id
JOIN postgresql.person p ON p.person_id = pr.person_id
JOIN postgresql.calendar_state cs USING(calendar_state_id)
JOIN vn.worker w ON w.id = p.id_trabajador
WHERE ce.date = CURDATE() AND
cs.isAllowedToWork = FALSE AND
w.userFk = vUserFk
LIMIT 1;
IF(LENGTH(vCalendarStateType)) THEN
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Vacaciones") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw(vCalendarStateType);
END IF;
-- VERIFICAR DESCANSO SEMANAL
SET @vHasBreakWeek:= FALSE;
SET @vLastTimed:= UNIX_TIMESTAMP((vTimed - INTERVAL vWeekScope SECOND));
DROP TEMPORARY TABLE IF EXISTS tmp.trash;
CREATE TEMPORARY TABLE tmp.trash
SELECT IF(vWeekBreak-(UNIX_TIMESTAMP(timed)-@vLastTimed) <= 0, @vHasBreakWeek:=TRUE, TRUE) alias,
@vLastTimed:= UNIX_TIMESTAMP(timed)
FROM workerTimeControl
WHERE timed>= (vTimed - INTERVAL vWeekScope SECOND) AND
userFk= vUserFk AND
direction IN ('in','out')
ORDER BY timed ASC;
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vWeekBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÃÆââ¬Â°S DE LA ÃÆÅ¡LTIMA FICHADA
SET @vHasBreakWeek:= FALSE;
SET @vLastTimed:= UNIX_TIMESTAMP((vTimed - INTERVAL vWeekMaxScope SECOND));
DROP TEMPORARY TABLE tmp.trash;
CREATE TEMPORARY TABLE tmp.trash
SELECT IF(vWeekMaxBreak-(UNIX_TIMESTAMP(timed)-@vLastTimed) <= 0, @vHasBreakWeek:=TRUE, TRUE) alias,
@vLastTimed:= UNIX_TIMESTAMP(timed)
FROM workerTimeControl
WHERE timed>= (vTimed - INTERVAL vWeekMaxScope SECOND) AND
userFk= vUserFk AND
direction IN ('in','out')
ORDER BY timed ASC;
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastOut) < vWeekMaxBreak AND @vHasBreakWeek = FALSE THEN -- REVISA SI EL DESCANSO SE HA REALIZADO DESPUÃÆââ¬Â°S DE LA ÃÆÅ¡LTIMA FICHADA
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vWeekMaxBreak/3600,0) ," h") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.throw(CONCAT( "Descansos ", FORMAT(vWeekMaxBreak/3600,0) ," h"));
END IF;
-- ENVIAMOS CORREO AL BOSSFK
SELECT CONCAT(vUserName,' No ha podido fichar por el siguiente problema: ',"Descansos ", FORMAT(vWeekBreak/3600,0) ," h") INTO vBody;
CALL vn.mail_insert(vTo,vTo,'error al fichar',vBody);
CALL util.warn(CONCAT( "Descansos ", FORMAT(vWeekBreak/3600,0) ," h"));
END IF;
DROP TEMPORARY TABLE tmp.trash;
-- Preguntar direcciÃÆón de la fichada
IF UNIX_TIMESTAMP(vTimed) - UNIX_TIMESTAMP(vLastIn) >= vAskInOut AND (SELECT MOD(COUNT(*),2)
FROM vn.workerTimeControl WHERE userFk = vUserFk AND timed >= vLastIn) THEN
CALL util.warn("AskInOut");
END IF ;
END$$
DELIMITER ;

File diff suppressed because one or more lines are too long

View File

@ -39,8 +39,8 @@ INSERT INTO `account`.`user`(`id`,`name`, `nickname`, `password`,`role`,`active`
FROM `account`.`role` WHERE id <> 20
ORDER BY id;
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9
INSERT INTO `vn`.`worker`(`id`,`code`, `firstName`, `lastName`, `userFk`, `bossFk`, `email`)
SELECT id,UPPER(LPAD(role, 3, '0')), name, name, id, 9, 'test@nightmare.es'
FROM `vn`.`user`;
UPDATE `vn`.`worker` SET bossFk = NULL WHERE id = 20;
@ -68,13 +68,13 @@ INSERT INTO `account`.`user`(`id`,`name`,`nickname`, `password`,`role`,`active`,
(111, 'Missing', 'Missing', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en'),
(112, 'Trash', 'Trash', 'ac754a330530832ba1bf7687f577da91', 2, 0, NULL, 'en');
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`)
INSERT INTO `vn`.`worker`(`id`, `code`, `firstName`, `lastName`, `userFk`,`bossFk`, `phone`, `email`)
VALUES
(106, 'LGN', 'David Charles', 'Haller', 106, 19, 432978106),
(107, 'ANT', 'Hank' , 'Pym' , 107, 19, 432978107),
(108, 'DCX', 'Charles' , 'Xavier', 108, 19, 432978108),
(109, 'HLK', 'Bruce' , 'Banner', 109, 19, 432978109),
(110, 'JJJ', 'Jessica' , 'Jones' , 110, 19, 432978110);
(106, 'LGN', 'David Charles', 'Haller', 106, 19, 432978106, 'test@nightmare.es'),
(107, 'ANT', 'Hank' , 'Pym' , 107, 19, 432978107, 'test@nightmare.es'),
(108, 'DCX', 'Charles' , 'Xavier', 108, 19, 432978108, 'test@nightmare.es'),
(109, 'HLK', 'Bruce' , 'Banner', 109, 19, 432978109, 'test@nightmare.es'),
(110, 'JJJ', 'Jessica' , 'Jones' , 110, 19, 432978110, 'test@nightmare.es');
INSERT INTO `vn`.`country`(`id`, `country`, `isUeeMember`, `code`, `currencyFk`, `ibanLength`)
VALUES
@ -197,14 +197,16 @@ INSERT INTO `vn`.`town`(`id`, `name`, `provinceFk`)
(1, 'Valencia', 1),
(2, 'Silla', 1),
(3, 'Algemesi', 1),
(4, 'Alzira', 1);
(4, 'Alzira', 1),
(5, 'Quito', 5);
INSERT INTO `vn`.`postCode`(`code`, `townFk`, `geoFk`)
VALUES
('46000', 1, 6),
('46460', 2, 6),
('46680', 3, 6),
('46600', 4, 7);
('46600', 4, 7),
('EC170150', 5, 8);
INSERT INTO `vn`.`clientType`(`id`, `code`, `type`)
VALUES
@ -554,30 +556,30 @@ INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `des
INSERT INTO `vn`.`ticketTracking`(`ticketFk`, `stateFk`, `workerFk`, `created`)
VALUES
(1, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(2, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(3, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
(4, 16, 5 , DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
(5, 16, 18, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
(6, 16, 18, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
(7, 10, 18, CURDATE()),
(8, 5, 19, CURDATE()),
(9, 5, 19, CURDATE()),
(10, 5, 19, CURDATE()),
(11, 3, 19, CURDATE()),
(12, 3, 19, CURDATE()),
(13, 3, 19, CURDATE()),
(14, 3, 19, CURDATE()),
(15, 3, 19, CURDATE()),
(16, 3, 19, CURDATE()),
(17, 3, 19, CURDATE()),
(18, 3, 19, CURDATE()),
(19, 17, 19, CURDATE()),
(20, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(21, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(22, 1, 19, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
(23, 16, 21, CURDATE()),
(24, 16, 21, CURDATE());
(1, 16, 5 , DATE_ADD(NOW(), INTERVAL -1 MONTH)),
(2, 16, 5 , DATE_ADD(NOW(), INTERVAL -1 MONTH)),
(3, 16, 5 , DATE_ADD(NOW(), INTERVAL -2 MONTH)),
(4, 16, 5 , DATE_ADD(NOW(), INTERVAL -3 MONTH)),
(5, 16, 18, DATE_ADD(NOW(), INTERVAL -4 MONTH)),
(6, 16, 18, DATE_ADD(NOW(), INTERVAL -1 MONTH)),
(7, 10, 18, NOW()),
(8, 5, 19, NOW()),
(9, 5, 19, NOW()),
(10, 5, 19, NOW()),
(11, 3, 19, NOW()),
(12, 3, 19, NOW()),
(13, 3, 19, NOW()),
(14, 3, 19, NOW()),
(15, 3, 19, NOW()),
(16, 3, 19, NOW()),
(17, 3, 19, NOW()),
(18, 3, 19, NOW()),
(19, 17, 19, NOW()),
(20, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
(21, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
(22, 1, 19, DATE_ADD(NOW(), INTERVAL +1 MONTH)),
(23, 16, 21, NOW()),
(24, 16, 21, NOW());
INSERT INTO `vn`.`stowaway`(`id`, `shipFk`, `created`)
VALUES
@ -1103,11 +1105,11 @@ INSERT INTO `vn`.`annualAverageInvoiced`(`clientFk`, `invoiced`)
(104, 500),
(105, 5000);
INSERT INTO `vn`.`supplier`(`id`, `name`,`account`,`countryFk`,`nif`,`isFarmer`,`retAccount`,`commission`, `created`, `postcodeFk`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`)
INSERT INTO `vn`.`supplier`(`id`, `name`, `nickname`,`account`,`countryFk`,`nif`,`isFarmer`,`retAccount`,`commission`, `created`, `postcodeFk`, `isActive`, `street`, `city`, `provinceFk`, `postCode`, `payMethodFk`, `payDemFk`)
VALUES
(1, 'Plants SL', 4000000001, 1, 'A11111111', 0, NULL, 0, CURDATE(), 1111, 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1),
(2, 'Flower King', 4000000002, 1, 'B22222222', 0, NULL, 0, CURDATE(), 2222, 1, 'supplier address 2', 'LONDON', 2, 45671, 1, 2),
(442, 'Verdnatura Levante SL', 4000000442, 1, 'C33333333', 0, NULL, 0, CURDATE(), 3333, 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2);
(1, 'Plants SL', 'Plants nick', 4000000001, 1, 'A11111111', 0, NULL, 0, CURDATE(), 1111, 1, 'supplier address 1', 'PONTEVEDRA', 1, 15214, 1, 1),
(2, 'Flower King', 'The king', 4000000002, 1, 'B22222222', 0, NULL, 0, CURDATE(), 2222, 1, 'supplier address 2', 'LONDON', 2, 45671, 1, 2),
(442, 'Verdnatura Levante SL', 'Verdnatura', 4000000442, 1, 'C33333333', 0, NULL, 0, CURDATE(), 3333, 1, 'supplier address 3', 'SILLA', 1, 43022, 1, 2);
INSERT INTO `cache`.`cache_calc`(`id`, `cache_id`, `cacheName`, `params`, `last_refresh`, `expires`, `created`, `connection_id`)
VALUES
@ -1580,6 +1582,13 @@ INSERT INTO `postgresql`.`business_labour`(`business_id`, `notes`, `department_i
SELECT b.business_id, NULL, 23, 1, 0, 1, 1, 1, 1
FROM `postgresql`.`business` `b`;
UPDATE `postgresql`.`business_labour` bl
JOIN `postgresql`.`business` b ON b.business_id = bl.business_id
JOIN `postgresql`.`profile` pr ON pr.profile_id = b.client_id
JOIN `postgresql`.`person` p ON p.person_id = pr.person_id
SET bl.`professional_category_id` = 31
WHERE p.`Id_trabajador` = 110;
INSERT INTO `postgresql`.`media`(`media_id`, `media_type_id`, `value`, `sort`)
VALUES
(1, 10, 600123321, 0),
@ -1677,12 +1686,12 @@ INSERT INTO `vn`.`zoneIncluded` (`zoneFk`, `geoFk`, `isIncluded`)
INSERT INTO `vn`.`zoneEvent`(`zoneFk`, `type`, `dated`)
VALUES
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
(1, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=6, 6, 13) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9 ) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=2, 2, 9) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=3, 3, 10) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=4, 4, 11) - DAYOFWEEK(CURDATE())) DAY)),
(2, 'day', DATE_ADD(CURDATE(), INTERVAL (IF(DAYOFWEEK(CURDATE())<=5, 5, 12) - DAYOFWEEK(CURDATE())) DAY)),
@ -1901,11 +1910,11 @@ INSERT INTO `vn`.`dmsType`(`id`, `name`, `path`, `readRoleFk`, `writeRoleFk`, `c
VALUES
(1, 'Facturas Recibidas', 'recibidas', NULL, NULL, 'invoiceIn'),
(2, 'Doc oficial', 'oficial', NULL, NULL, 'officialDoc'),
(3, 'Laboral', 'laboral', NULL, NULL, 'hhrrData'),
(3, 'Laboral', 'laboral', 37, 37, 'hhrrData'),
(4, 'Albaranes recibidos', 'entradas', NULL, NULL, 'deliveryNote'),
(5, 'Otros', 'otros', 1, 1, 'miscellaneous'),
(6, 'Pruebas', 'pruebas', NULL, NULL, 'tests'),
(7, 'IAE Clientes', 'IAE_Clientes', NULL, NULL, 'economicActivitiesTax'),
(7, 'IAE Clientes', 'IAE_Clientes', 1, 1, 'economicActivitiesTax'),
(8, 'Fiscal', 'fiscal', NULL, NULL, 'fiscal'),
(9, 'Vehiculos', 'vehiculos', NULL, NULL, 'vehicles'),
(10, 'Plantillas', 'plantillas', NULL, NULL, 'templates'),
@ -1951,9 +1960,9 @@ INSERT INTO `vn`.`queuePriority`(`id`, `priority`)
(2, 'Normal'),
(3, 'Baja');
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`)
INSERT INTO `vn`.`workerTimeControlParams` (`id`, `dayBreak`, `weekBreak`, `weekScope`, `dayWorkMax`, `dayStayMax`, `weekMaxBreak`, `weekMaxScope`, `askInOut`)
VALUES
(1, 43200, 129600, 734400, 43200, 50400);
(1, 43200, 129600, 734400, 43200, 50400, 259200, 1296000, 36000);
INSERT IGNORE INTO `vn`.`greugeConfig` (`id`, `freightPickUpPrice`) VALUES ('1', '11');
@ -1973,11 +1982,21 @@ INSERT INTO `vn`.`travelThermograph`(`thermographFk`, `created`, `warehouseFk`,
('138350-0', DATE_ADD(CURDATE(), INTERVAL -1 MONTH), 1, 1, 'WARM', NULL, 5),
('138350-0', CURDATE(), 1, NULL, 'COOL', NULL, NULL);
REPLACE INTO `vn`.`incoterms` (`code`, `name`)
REPLACE INTO `vn`.`incoterms`(`code`, `name`)
VALUES
('FAS', 'Free Alongside Ship');
REPLACE INTO `vn`.`customsAgent` (`id`, `fiscalName`, `street`, `nif`, `phone`, `email`)
REPLACE INTO `vn`.`customsAgent`(`id`, `fiscalName`, `street`, `nif`, `phone`, `email`)
VALUES
(1, 'Agent one', '1007 Mountain Drive, Gotham', 'N1111111111', '111111111', 'agentone@gotham.com'),
(2, 'Agent two', '1007 Mountain Drive, Gotham', 'N2222222222', '222222222', 'agenttwo@gotham.com');
(2, 'Agent two', '1007 Mountain Drive, Gotham', 'N2222222222', '222222222', 'agenttwo@gotham.com');
INSERT INTO `vn`.`tabletDepartment`(`tabletFk`, `departmentFk`)
VALUES
(1, 23),
(2, 1);
INSERT INTO `vn`.`tablet`(`uuid`, `name`, `place`, `macwifi`)
VALUES
('1', 'TEST', 'ON THE FIXTURES', '0'),
('2', 'DEV', 'OTHER TABLET', '0');

File diff suppressed because it is too large Load Diff

View File

@ -43,7 +43,6 @@ describe('ticket ticketCreateWithUser()', () => {
let ticketResult = result[ticketResultIndex][0];
expect(ticketResult.id).toBeGreaterThan(21);
expect(ticketResult.clientFk).toEqual(params.clientFk);
expect(ticketResult.warehouseFk).toEqual(params.warehouseFk);

View File

@ -0,0 +1,40 @@
const app = require('vn-loopback/server/server');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
describe('timeBusiness_calculateByUser()', () => {
it('should return the expected hours for today', async() => {
let start = new Date();
start.setHours(0, 0, 0, 0);
let end = new Date();
end.setHours(0, 0, 0, 0);
let stmts = [];
let stmt;
stmts.push('START TRANSACTION');
let params = {
workerID: 106,
start: start,
end: end
};
stmt = new ParameterizedSQL('CALL vn.timeBusiness_calculateByUser(?, ?, ?)', [
params.workerID,
params.start,
params.end
]);
stmts.push(stmt);
let tableIndex = stmts.push('SELECT * FROM tmp.timeBusinessCalculate') - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let [timeBusinessCalculateTable] = result[tableIndex];
expect(timeBusinessCalculateTable.timeBusinessSeconds).toEqual(28800);
});
});

View File

@ -0,0 +1,107 @@
const app = require('vn-loopback/server/server');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
describe('timeControl_calculateByUser()', () => {
it(`should return today's worked hours`, async() => {
let start = new Date();
start.setHours(0, 0, 0, 0);
start.setDate(start.getDate() - 1);
let end = new Date();
end.setHours(0, 0, 0, 0);
end.setDate(end.getDate() + 1);
let stmts = [];
let stmt;
stmts.push('START TRANSACTION');
stmts.push(`
DROP TEMPORARY TABLE IF EXISTS
tmp.timeControlCalculate,
tmp.timeBusinessCalculate
`);
let params = {
workerID: 106,
start: start,
end: end
};
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
params.workerID,
params.start,
params.end
]);
stmts.push(stmt);
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let [timeControlCalculateTable] = result[tableIndex];
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(29400);
});
it(`should return the worked hours between last sunday and monday`, async() => {
let lastSunday = new Date();
let daysSinceSunday = lastSunday.getDay();
if (daysSinceSunday === 0) // this means today is sunday but you need the previous sunday :)
daysSinceSunday = 7;
lastSunday.setHours(23, 0, 0, 0);
lastSunday.setDate(lastSunday.getDate() - daysSinceSunday);
let monday = new Date();
let daysSinceMonday = daysSinceSunday - 1; // aiming for monday (today could be monday)
monday.setHours(7, 0, 0, 0);
monday.setDate(monday.getDate() - daysSinceMonday);
let stmts = [];
let stmt;
stmts.push('START TRANSACTION');
stmts.push(`
DROP TEMPORARY TABLE IF EXISTS
tmp.timeControlCalculate,
tmp.timeBusinessCalculate
`);
const workerID = 107;
stmt = new ParameterizedSQL(`
INSERT INTO vn.workerTimeControl(userFk, timed, manual, direction)
VALUES
(?, ?, 1, 'in'),
(?, ?, 1, 'out')
`, [
workerID,
lastSunday,
workerID,
monday
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.timeControl_calculateByUser(?, ?, ?)', [
workerID,
lastSunday,
monday
]);
stmts.push(stmt);
let tableIndex = stmts.push('SELECT * FROM tmp.timeControlCalculate') - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Ticket.rawStmt(sql);
let [timeControlCalculateTable] = result[tableIndex];
expect(timeControlCalculateTable.timeWorkSeconds).toEqual(30000);
});
});

View File

@ -0,0 +1,587 @@
const app = require('vn-loopback/server/server');
const ParameterizedSQL = require('loopback-connector').ParameterizedSQL;
describe('worker workerTimeControl_check()', () => {
it(`should throw an error if the worker can't sign on that tablet`, async() => {
let stmts = [];
let stmt;
const workerId = 110;
const tabletId = 2;
let err;
stmts.push('START TRANSACTION');
try {
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
await app.models.Worker.rawStmt(sql);
} catch (e) {
err = e;
}
expect(err.sqlMessage).toEqual('No perteneces a este departamento.');
});
it('should check that the worker can sign on that tablet', async() => {
let stmts = [];
let stmt;
const workerId = 110;
const tabletId = 1;
let err;
stmts.push('START TRANSACTION');
try {
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
await app.models.Worker.rawStmt(sql);
} catch (e) {
err = e;
}
expect(err).not.toBeDefined();
});
it('should throw an error if the worker with a special category has not finished the 9h break', async() => {
// dayBreak to 9h in postgresql.professional_category
const workerId = 110;
const tabletId = 1;
let stmts = [];
let stmt;
let sql;
let error;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-17,NOW()),0,"in"),
(?,TIMESTAMPADD(SECOND,-32399,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
error = e;
}
expect(error.sqlMessage).toEqual('Descansos 9 h');
});
it('should check f the worker with a special category has finished the 9h break', async() => {
// dayBreak to 9h in postgresql.professional_category
const workerId = 110;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-17,NOW()),0,"in"),
(?,TIMESTAMPADD(SECOND,-32401,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err).not.toBeDefined();
});
it('should throw an error if the worker has not finished the 12h break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let sql;
let error;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"in"),
(?,TIMESTAMPADD(SECOND,-43199,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
error = e;
}
expect(error.sqlMessage).toEqual('Descansos 12 h');
});
it('should throw an error if the worker has finished the 12h break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"in"),
(?,TIMESTAMPADD(SECOND,-43201,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err).not.toBeDefined();
});
it('should throw an error if the worker has odd entry records', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in")`, [
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err.sqlMessage).toEqual('Dias con fichadas impares');
});
it('should throw an error if the worker try to sign on a holiday day', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO postgresql.calendar_employee(business_id,calendar_state_id,date)
VALUES
(?,1,CURDATE())`, [
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err.sqlMessage).toEqual('Holidays');
});
it('should throw an error if the worker try to sign with your contract ended', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`UPDATE postgresql.business SET date_end=DATE_ADD(CURDATE(), INTERVAL -1 DAY) WHERE business_id=?`, [
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-20,NOW()),0,"out")`, [
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err.sqlMessage).toEqual('No hay un contrato en vigor');
});
it('should throw an error if the worker has not finished the 36h weekly break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
stmts.push('SET @warn := NULL');
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out")`, [
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
let warningMessageIndex = stmts.push('SELECT @warn AS warning') - 1;
stmts.push('ROLLBACK');
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Worker.rawStmt(sql);
expect(result[warningMessageIndex][0].warning).toEqual('Descansos 36 h');
});
it('should check if the worker has finished the 36h weekly break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
stmts.push('SET @warn := NULL');
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out")`, [
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
let warningMessageIndex = stmts.push('SELECT @warn AS warning') - 1;
let sql = ParameterizedSQL.join(stmts, ';');
let result = await app.models.Worker.rawStmt(sql);
expect(result[warningMessageIndex][0].warning).toBe(null);
});
it('should throw an error if the worker has not finished the 72h biweekly break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-216,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-208,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-240,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-232,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-264,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-256,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-289,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-280,NOW()),0,"out")`, [
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
stmts.push('SELECT @warn AS warning') - 1;
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err.sqlMessage).toEqual('Descansos 72 h');
});
it('should check if the worker has finished the 72h biweekly break', async() => {
const workerId = 109;
const tabletId = 1;
let stmts = [];
let stmt;
let err;
stmts.push('START TRANSACTION');
stmt = new ParameterizedSQL(`INSERT INTO vn.workerTimeControl(userFk,timed,manual,direction)
VALUES
(?,TIMESTAMPADD(HOUR,-24,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-16,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-48,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-40,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-72,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-64,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-96,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-88,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-120,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-112,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-144,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-136,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-168,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-160,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-192,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-184,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-216,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-208,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-240,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-232,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-264,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-256,NOW()),0,"out"),
(?,TIMESTAMPADD(HOUR,-288,NOW()),0,"in"),
(?,TIMESTAMPADD(HOUR,-280,NOW()),0,"out")`, [
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId,
workerId
]);
stmts.push(stmt);
stmt = new ParameterizedSQL('CALL vn.workerTimeControl_check(?, ?, NULL)', [
workerId,
tabletId
]);
stmts.push(stmt);
stmts.push('ROLLBACK');
stmts.push('SELECT @warn AS warning') - 1;
let sql = ParameterizedSQL.join(stmts, ';');
try {
await app.models.Worker.rawStmt(sql);
} catch (e) {
await app.models.Worker.rawSql('ROLLBACK');
err = e;
}
expect(err).not.toBeDefined();
});
});

View File

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

View File

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

View File

@ -9,6 +9,7 @@ export default {
invoiceOutButton: '.modules-menu > li[ui-sref="invoiceOut.index"]',
claimsButton: '.modules-menu > li[ui-sref="claim.index"]',
returnToModuleIndexButton: 'a[ui-sref="order.index"]',
homeButton: 'vn-topbar > div.side.start > a',
userMenuButton: '#user',
userLocalWarehouse: '.user-popover vn-autocomplete[ng-model="$ctrl.localWarehouseFk"]',
userLocalBank: '.user-popover vn-autocomplete[ng-model="$ctrl.localBankFk"]',
@ -43,8 +44,8 @@ export default {
taxNumber: 'vn-client-create vn-textfield[ng-model="$ctrl.client.fi"]',
socialName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.socialName"]',
street: 'vn-client-create vn-textfield[ng-model="$ctrl.client.street"]',
postcode: 'vn-client-create vn-textfield[ng-model="$ctrl.client.postcode"]',
city: 'vn-client-create vn-textfield[ng-model="$ctrl.client.city"]',
postcode: 'vn-client-create vn-datalist[ng-model="$ctrl.client.postcode"]',
city: 'vn-client-create vn-datalist[ng-model="$ctrl.client.city"]',
province: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
country: 'vn-client-create vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
userName: 'vn-client-create vn-textfield[ng-model="$ctrl.client.userName"]',
@ -75,8 +76,8 @@ export default {
equalizationTaxCheckbox: 'vn-client-fiscal-data vn-check[ng-model="$ctrl.client.isEqualizated"]',
acceptPropagationButton: '.vn-confirm.shown button[response=accept]',
address: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.street"]',
postcode: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.postcode"]',
city: 'vn-client-fiscal-data vn-textfield[ng-model="$ctrl.client.city"]',
postcode: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.postcode"]',
city: 'vn-client-fiscal-data vn-datalist[ng-model="$ctrl.client.city"]',
province: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.provinceFk"]',
country: 'vn-client-fiscal-data vn-autocomplete[ng-model="$ctrl.client.countryFk"]',
activeCheckbox: 'vn-client-fiscal-data vn-check[label="Active"]',
@ -113,8 +114,8 @@ export default {
defaultCheckbox: 'vn-check[label="Default"]',
consignee: 'vn-textfield[ng-model="$ctrl.address.nickname"]',
streetAddress: 'vn-textfield[ng-model="$ctrl.address.street"]',
postcode: 'vn-textfield[ng-model="$ctrl.address.postalCode"]',
city: 'vn-textfield[ng-model="$ctrl.address.city"]',
postcode: 'vn-datalist[ng-model="$ctrl.address.postalCode"]',
city: 'vn-datalist[ng-model="$ctrl.address.city"]',
province: 'vn-autocomplete[ng-model="$ctrl.address.provinceId"]',
agency: 'vn-autocomplete[ng-model="$ctrl.address.agencyModeId"]',
phone: 'vn-textfield[ng-model="$ctrl.address.phone"]',
@ -192,7 +193,7 @@ export default {
},
dms: {
deleteFileButton: 'vn-client-dms-index vn-tr:nth-child(1) vn-icon-button[icon="delete"]',
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(8) > span',
firstDocWorker: 'vn-client-dms-index vn-td:nth-child(7) > span',
firstDocWorkerDescriptor: '.vn-popover.shown vn-worker-descriptor',
acceptDeleteButton: '.vn-confirm.shown button[response="accept"]'
},
@ -365,7 +366,7 @@ export default {
ticketsIndex: {
openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]',
advancedSearchInvoiceOut: 'vn-ticket-search-panel vn-textfield[ng-model="filter.refFk"]',
newTicketButton: 'vn-ticket-index > a',
newTicketButton: 'vn-ticket-index a',
searchResult: 'vn-ticket-index vn-card > vn-table > div > vn-tbody > a.vn-tr',
searchWeeklyResult: 'vn-ticket-weekly-index vn-table vn-tbody > vn-tr',
searchResultDate: 'vn-ticket-index vn-table vn-tbody > a:nth-child(1) > vn-td:nth-child(5)',
@ -511,17 +512,20 @@ export default {
},
ticketRequests: {
addRequestButton: 'vn-ticket-request-index > a > vn-float-button > button',
request: 'vn-ticket-request-index vn-table vn-tr',
descriptionInput: 'vn-ticket-request-create [ng-model="$ctrl.ticketRequest.description"]',
atender: 'vn-ticket-request-create vn-autocomplete[ng-model="$ctrl.ticketRequest.attenderFk"]',
quantity: 'vn-ticket-request-create vn-input-number[ng-model="$ctrl.ticketRequest.quantity"]',
price: 'vn-ticket-request-create vn-input-number[ng-model="$ctrl.ticketRequest.price"]',
firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)',
firstRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(6) vn-input-number',
secondRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(2) > vn-td:nth-child(6) vn-input-number',
thirdDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(3) > vn-td:nth-child(2) vn-textfield',
thirdRemoveRequestButton: 'vn-ticket-request-index vn-tr:nth-child(3) vn-icon[icon="delete"]',
thirdRequestQuantity: 'vn-ticket-request-index vn-table vn-tr:nth-child(3) > vn-td:nth-child(6) vn-input-number',
saveButton: 'vn-ticket-request-create button[type=submit]',
firstDescription: 'vn-ticket-request-index vn-table vn-tr:nth-child(1) > vn-td:nth-child(2) vn-textfield',
},
ticketLog: {
firstTD: 'vn-ticket-log vn-table vn-td:nth-child(1)',
logButton: 'vn-left-menu a[ui-sref="ticket.card.log"]',
changedBy: 'vn-ticket-log > vn-log vn-tr:nth-child(1) > vn-td:nth-child(2) > span',
actionTaken: 'vn-ticket-log > vn-log vn-td:nth-child(1) > div > div:nth-child(3) > span.value',
@ -628,6 +632,16 @@ export default {
createButton: 'button[type=submit]',
cancelButton: 'vn-button[href="#!/client/index"]'
},
orderSummary: {
header: 'vn-order-summary h5',
id: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(1) span',
alias: 'vn-order-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) span',
consignee: 'vn-order-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) span',
subtotal: 'vn-order-summary vn-one.taxes > p:nth-child(1)',
vat: 'vn-order-summary vn-one.taxes > p:nth-child(2)',
total: 'vn-order-summary vn-one.taxes > p:nth-child(3)',
sale: 'vn-order-summary vn-tbody > vn-tr',
},
orderCatalog: {
plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]',
type: 'vn-autocomplete[data="$ctrl.itemTypes"]',
@ -698,6 +712,17 @@ export default {
firstTicketDeleteButton: 'vn-route-tickets vn-tr:nth-child(1) vn-icon[icon="delete"]',
confirmButton: '.vn-confirm.shown button[response="accept"]'
},
workerSummary: {
header: 'vn-worker-summary h5',
id: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(2) > section > span',
email: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(3) > section > span',
department: 'vn-worker-summary vn-one:nth-child(1) > vn-label-value:nth-child(4) > section > span',
userId: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(2) > section > span',
userName: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(3) > section > span',
role: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(4) > section > span',
extension: 'vn-worker-summary vn-one:nth-child(2) > vn-label-value:nth-child(5) > section > span',
},
workerBasicData: {
name: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.firstName"]',
surname: 'vn-worker-basic-data vn-textfield[ng-model="$ctrl.worker.lastName"]',
@ -781,14 +806,29 @@ export default {
ticketOne: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(1)',
ticketTwo: 'vn-invoice-out-summary > vn-card > vn-horizontal > vn-auto > vn-table > div > vn-tbody > vn-tr:nth-child(2)'
},
travelBasicDada: {
reference: 'vn-travel-basic-data vn-textfield[ng-model="$ctrl.travel.ref"]',
agency: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.agencyModeFk"]',
shippingDate: 'vn-travel-basic-data vn-date-picker[ng-model="$ctrl.travel.shipped"]',
deliveryDate: 'vn-travel-basic-data vn-date-picker[ng-model="$ctrl.travel.landed"]',
outputWarehouse: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.warehouseOutFk"]',
inputWarehouse: 'vn-travel-basic-data vn-autocomplete[ng-model="$ctrl.travel.warehouseInFk"]',
delivered: 'vn-travel-basic-data vn-check[ng-model="$ctrl.travel.isDelivered"]',
received: 'vn-travel-basic-data vn-check[ng-model="$ctrl.travel.isReceived"]',
save: 'vn-travel-basic-data vn-submit[label="Save"]',
undoChanges: 'vn-travel-basic-data vn-button[label="Undo changes"]'
},
travelLog: {
firstLogFirstTD: 'vn-travel-log vn-tbody > vn-tr > vn-td:nth-child(1) > div'
},
travelThermograph: {
add: 'vn-travel-thermograph-index vn-float-button[icon="add"]',
thermographID: 'vn-travel-thermograph-create vn-autocomplete[ng-model="$ctrl.dms.thermographId"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="cloud_upload"]',
uploadIcon: 'vn-travel-thermograph-create vn-icon[icon="icon-attach"]',
createdThermograph: 'vn-travel-thermograph-index vn-tbody > vn-tr',
upload: 'vn-travel-thermograph-create button[type=submit]'
},
agencyBasicData: {
zoneBasicData: {
name: 'vn-zone-basic-data vn-textfield[ng-model="$ctrl.zone.name"]',
agency: 'vn-zone-basic-data vn-autocomplete[ng-model="$ctrl.zone.agencyModeFk"]',
maxVolume: 'vn-zone-basic-data vn-input-number[ng-model="$ctrl.zone.m3Max"]',
@ -799,5 +839,15 @@ export default {
inflation: 'vn-zone-basic-data vn-input-number[ng-model="$ctrl.zone.inflation"]',
volumetric: 'vn-zone-basic-data vn-check[ng-model="$ctrl.zone.isVolumetric"]',
saveButton: 'vn-zone-basic-data vn-submit > button',
},
entrySummary: {
header: 'vn-entry-summary > vn-card > h5',
reference: 'vn-entry-summary vn-label-value[label="Reference"]',
confirmed: 'vn-entry-summary vn-check[label="Confirmed"]',
},
entryDescriptor: {
agency: 'vn-entry-descriptor div.body vn-label-value:nth-child(3) span',
travelsQuicklink: 'vn-entry-descriptor vn-quick-links > a:nth-child(1)',
entriesQuicklink: 'vn-entry-descriptor vn-quick-links > a:nth-child(2)'
}
};

View File

@ -87,7 +87,7 @@ describe('Client create path', async() => {
.waitToGetProperty(selectors.createClientView.country, 'value');
expect(clientCity).toEqual('Valencia');
expect(clientProvince).toEqual('Province one');
expect(clientProvince).toContain('Province one');
expect(clientCountry).toEqual('España');
});
@ -101,7 +101,6 @@ describe('Client create path', async() => {
});
it('should click on the Clients button of the top bar menu', async() => {
await page.waitFor(500);
await page.waitToClick(selectors.globalItems.applicationsMenuButton);
await page.wait(selectors.globalItems.applicationsMenuVisible);
await page.waitToClick(selectors.globalItems.clientsButton);

View File

@ -160,6 +160,7 @@ describe('Client Edit fiscalData path', () => {
});
it('should propagate the Equalization tax changes', async() => {
await page.waitFor(1000);
await page.waitToClick(selectors.clientFiscalData.acceptPropagationButton);
const result = await page.waitForLastSnackbar();
@ -197,11 +198,10 @@ describe('Client Edit fiscalData path', () => {
expect(result).toEqual('Valencia');
});
it(`should confirm the province have been autocompleted`, async() => {
const result = await page.waitToGetProperty(selectors.clientFiscalData.province, 'value');
expect(result).toEqual('Province one');
expect(result).toContain('Province one');
});
it('should confirm the country have been autocompleted', async() => {

View File

@ -25,9 +25,7 @@ describe('Client Add address path', () => {
it('should receive an error after clicking save button as consignee, street and town fields are empty', async() => {
await page.waitToClick(selectors.clientAddresses.defaultCheckbox);
await page.autocompleteSearch(selectors.clientAddresses.province, 'Province five');
await page.write(selectors.clientAddresses.city, 'Valencia');
await page.write(selectors.clientAddresses.postcode, '46000');
await page.write(selectors.clientAddresses.postcode, 'EC170150');
await page.autocompleteSearch(selectors.clientAddresses.agency, 'Entanglement');
await page.write(selectors.clientAddresses.phone, '999887744');
await page.write(selectors.clientAddresses.mobileInput, '999887744');
@ -37,6 +35,16 @@ describe('Client Add address path', () => {
expect(result).toEqual('Some fields are invalid');
});
it('should confirm that the city and province are propertly filled', async() => {
const city = await page
.waitToGetProperty(selectors.clientAddresses.city, 'value');
const province = await page
.waitToGetProperty(selectors.clientAddresses.province, 'value');
expect(city).toEqual('Quito');
expect(province).toContain('Province five');
});
it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => {
await page.write(selectors.clientAddresses.consignee, 'Bruce Bunner');
@ -47,7 +55,7 @@ describe('Client Add address path', () => {
expect(result).toEqual('Incoterms is required for a non UEE member');
});
it(`should receive an error after clicking save button as consignee, incoterms and customsAgent are empty`, async() => {
it(`should receive an error after clicking save button as customsAgent is empty`, async() => {
await page.autocompleteSearch(selectors.clientAddresses.incoterms, 'Free Alongside Ship');
await page.waitToClick(selectors.clientAddresses.saveButton);
const result = await page.waitForLastSnackbar();
@ -63,13 +71,20 @@ describe('Client Add address path', () => {
expect(result).toEqual('Data saved!');
});
it(`should click on the first address button to confirm the new address exists and it's the default one`, async() => {
it(`should navigate back to the addresses index`, async() => {
let url = await page.expectURL('/address/index');
expect(url).toBe(true);
});
it(`should confirm the new address exists and it's the default one`, async() => {
await page.waitFor(2000); // needs more than a single second to load the section
const result = await page.waitToGetProperty(selectors.clientAddresses.defaultAddress, 'innerText');
expect(result).toContain('320 Park Avenue New York');
});
it(`should click on the make default icon of the second address`, async() => {
it('should click on the make default icon of the second address', async() => {
await page.waitToClick(selectors.clientAddresses.secondMakeDefaultStar);
const result = await page.waitForLastSnackbar();
@ -101,6 +116,7 @@ describe('Client Add address path', () => {
});
it(`should go back to the addreses section by clicking the cancel button`, async() => {
await page.waitForSelector('#shapes .shown', {hidden: true});
await page.waitToClick(selectors.clientAddresses.cancelEditAddressButton);
await page.waitToClick('.vn-confirm.shown button[response="accept"]');
let url = await page.expectURL('address/index');

View File

@ -16,6 +16,12 @@ describe('Client Add notes path', () => {
await browser.close();
});
it(`should reach the notes index`, async() => {
let url = await page.expectURL('/note');
expect(url).toBe(true);
});
it(`should click on the add note button`, async() => {
await page.waitToClick(selectors.clientNotes.addNoteFloatButton);
let url = await page.expectURL('/note/create');

View File

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

View File

@ -35,7 +35,7 @@ describe('Client balance path', () => {
await page.clearInput(selectors.globalItems.userConfigThirdAutocomplete);
let result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
expect(result).toContain('Data saved!');
});
it('should click the new payment button', async() => {
@ -63,7 +63,6 @@ describe('Client balance path', () => {
let firstBalanceLine = await page
.waitToGetProperty(selectors.clientBalance.firstBalanceLine, 'innerText');
expect(company).toEqual('VNL');
expect(firstBalanceLine).toContain('0.00');
});

View File

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

View File

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

View File

@ -0,0 +1,71 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Worker summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('employee', 'worker');
await page.accessToSearchResult('agencyNick');
});
afterAll(async() => {
await browser.close();
});
it('should reach the employee summary section', async() => {
const url = await page.expectURL('#!/worker/3/summary');
expect(url).toBe(true);
});
it('should check the summary contains the name and userName on the header', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.header, 'innerText');
expect(result).toEqual('agency agency');
});
it('should check the summary contains the basic data id', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.id, 'innerText');
expect(result).toEqual('3');
});
it('should check the summary contains the basic data email', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.email, 'innerText');
expect(result).toEqual('agency@verdnatura.es');
});
it('should check the summary contains the basic data department', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.department, 'innerText');
expect(result).toEqual('CAMARA');
});
it('should check the summary contains the user data id', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.userId, 'innerText');
expect(result).toEqual('3');
});
it('should check the summary contains the user data name', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.userName, 'innerText');
expect(result).toEqual('agency');
});
it('should check the summary contains the user data role', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.role, 'innerText');
expect(result).toEqual('agency');
});
it('should check the summary contains the user data extension', async() => {
const result = await page.waitToGetProperty(selectors.workerSummary.extension, 'innerText');
expect(result).toEqual('1101');
});
});

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,65 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Ticket log path', () => {
let browser;
let page;
const ticketId = '5';
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
});
afterAll(async() => {
await browser.close();
});
it('should navigate to the target ticket notes section', async() => {
await page.loginAndModule('employee', 'ticket');
await page.accessToSearchResult(ticketId);
await page.accessToSection('ticket.card.observation');
let url = await page.expectURL('/observation');
expect(url).toBe(true);
});
it('should create a new note for the test', async() => {
await page.waitToClick(selectors.ticketNotes.addNoteButton);
await page.autocompleteSearch(selectors.ticketNotes.firstNoteType, 'observation one');
await page.write(selectors.ticketNotes.firstDescription, 'description');
await page.waitToClick(selectors.ticketNotes.submitNotesButton);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should navigate to the log section', async() => {
await page.accessToSection('ticket.card.log');
let url = await page.expectURL('/log');
expect(url).toBe(true);
});
it('should set the viewport width to 1920 to see the table full width', async() => {
await page.setViewport({
width: 1920,
height: 0,
});
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
expect(result.length).not.toBeGreaterThan('20');
});
it('should set the viewport width to 800 to see the table shrink and move data to the 1st column', async() => {
await page.setViewport({
width: 800,
height: 0,
});
const result = await page.waitToGetProperty(selectors.ticketLog.firstTD, 'innerText');
expect(result.length).toBeGreaterThan('20');
});
});

View File

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

View File

@ -0,0 +1,65 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Order summary path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('employee', 'order');
await page.accessToSearchResult('16');
});
afterAll(async() => {
await browser.close();
});
it('should reach the order summary section', async() => {
const url = await page.expectURL('#!/order/16/summary');
expect(url).toBe(true);
});
it('should check the summary contains the order id', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.id, 'innerText');
expect(result).toEqual('16');
});
it('should check the summary contains the order alias', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.alias, 'innerText');
expect(result).toEqual('address 26');
});
it('should check the summary contains the order consignee', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.consignee, 'innerText');
expect(result).toEqual('Many places - Silla (Province one)');
});
it('should check the summary contains the order subtotal', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.subtotal, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order vat', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.vat, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order total', async() => {
const result = await page.waitToGetProperty(selectors.orderSummary.total, 'innerText');
expect(result.length).toBeGreaterThan(1);
});
it('should check the summary contains the order sales', async() => {
const result = await page.countElement(selectors.orderSummary.sale);
expect(result).toBeGreaterThan(0);
});
});

View File

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

View File

@ -0,0 +1,102 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Travel basic data path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'travel');
await page.accessToSearchResult('3');
await page.accessToSection('travel.card.basicData');
});
afterAll(async() => {
await browser.close();
});
it('should reach the thermograph section', async() => {
const result = await page.expectURL('/basic-data');
expect(result).toBe(true);
});
it('should set a wrong delivery date then receive an error on submit', async() => {
await page.datePicker(selectors.travelBasicDada.deliveryDate, -1, null);
await page.waitToClick(selectors.travelBasicDada.save);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Landing cannot be lesser than shipment');
});
it('should undo the changes', async() => {
await page.waitToClick(selectors.travelBasicDada.undoChanges);
await page.waitToClick(selectors.travelBasicDada.save);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('No changes to save');
});
it('should now edit the whole form then save', async() => {
await page.clearInput(selectors.travelBasicDada.reference);
await page.write(selectors.travelBasicDada.reference, 'new reference!');
await page.waitFor(2000);
await page.autocompleteSearch(selectors.travelBasicDada.agency, 'Entanglement');
await page.autocompleteSearch(selectors.travelBasicDada.outputWarehouse, 'Warehouse Three');
await page.autocompleteSearch(selectors.travelBasicDada.inputWarehouse, 'Warehouse Four');
await page.waitToClick(selectors.travelBasicDada.delivered);
await page.waitToClick(selectors.travelBasicDada.received);
await page.waitToClick(selectors.travelBasicDada.save);
const result = await page.waitForLastSnackbar();
expect(result).toEqual('Data saved!');
});
it('should reload the section and check the reference was saved', async() => {
await page.reloadSection('travel.card.basicData');
const result = await page.waitToGetProperty(selectors.travelBasicDada.reference, 'value');
expect(result).toEqual('new reference!');
});
it('should check the agency was saved', async() => {
const result = await page.waitToGetProperty(selectors.travelBasicDada.agency, 'value');
expect(result).toEqual('Entanglement');
});
it('should check the output warehouse date was saved', async() => {
const result = await page.waitToGetProperty(selectors.travelBasicDada.outputWarehouse, 'value');
expect(result).toEqual('Warehouse Three');
});
it('should check the input warehouse date was saved', async() => {
const result = await page.waitToGetProperty(selectors.travelBasicDada.inputWarehouse, 'value');
expect(result).toEqual('Warehouse Four');
});
it(`should check the delivered checkbox was saved even tho it doesn't make sense`, async() => {
await page.waitForClassPresent(selectors.travelBasicDada.delivered, 'checked');
});
it(`should check the received checkbox was saved even tho it doesn't make sense`, async() => {
await page.waitForClassPresent(selectors.travelBasicDada.received, 'checked');
});
it('should navigate to the travel logs', async() => {
await page.accessToSection('travel.card.log');
const result = await page.expectURL('/log');
expect(result).toBe(true);
});
it('should check the 1st log contains details from the changes made', async() => {
const result = await page.waitToGetProperty(selectors.travelLog.firstLogFirstTD, 'innerText');
expect(result).toContain('new reference!');
});
});

View File

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

View File

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

View File

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

View File

@ -0,0 +1,61 @@
import selectors from '../../helpers/selectors.js';
import getBrowser from '../../helpers/puppeteer';
describe('Entry descriptor path', () => {
let browser;
let page;
beforeAll(async() => {
browser = await getBrowser();
page = browser.page;
await page.loginAndModule('buyer', 'entry');
await page.accessToSearchResult('2');
});
afterAll(async() => {
await browser.close();
});
it('should reach the second entry summary section', async() => {
let url = await page.expectURL('#!/entry/2/summary');
expect(url).toBe(true);
});
it('should show some entry information', async() => {
const result = await page.waitToGetProperty(selectors.entryDescriptor.agency, 'innerText');
expect(result).toContain('inhouse pickup');
});
it('should click the travels button to be redirected to the travels index filtered by the current agency', async() => {
await page.waitToClick(selectors.entryDescriptor.travelsQuicklink);
const url = await page.expectURL('/travel/index');
const filter = await page.expectURL('agencyFk');
expect(url).toBe(true);
expect(filter).toBe(true);
});
it('should go back to the entry summary', async() => {
await page.waitToClick(selectors.globalItems.homeButton);
await page.selectModule('entry');
await page.accessToSearchResult('2');
let url = await page.expectURL('#!/entry/2/summary');
expect(url).toBe(true);
});
it('should click the entries button to be redirected to the entries index filtered by the current supplier', async() => {
await page.waitToClick(selectors.entryDescriptor.entriesQuicklink);
const url = await page.expectURL('/entry/index');
const supplierFilter = await page.expectURL('supplierFk');
const toFilter = await page.expectURL('to');
const fromFilter = await page.expectURL('from');
expect(url).toBe(true);
expect(supplierFilter).toBe(true);
expect(toFilter).toBe(true);
expect(fromFilter).toBe(true);
});
});

View File

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

View File

@ -50,6 +50,17 @@
}
}
}
&.message {
color: white;
background-color: $color-bg-dark;
&:not(.disabled) {
&:hover,
&:focus {
background-color: lighten($color-bg-dark, 10%);
}
}
}
&.flat {
color: $color-button;
background-color: transparent;
@ -75,6 +86,22 @@
& > button > span {
display: none;
}
&.xs {
font-size: 0.5em;
}
&.sm {
font-size: 0.7em;
}
&.md {
font-size: 0.9em;
}
&.lg {
font-size: 1.2em;
}
}
&.disabled {
opacity: .7;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ export default class Datalist extends Textfield {
value = value == '' || value == null ? null : value;
oldValue = oldValue == '' || oldValue == null ? null : oldValue;
this.refreshSelection();
if (oldValue === undefined) this.refreshSelection();
if (!value || value === oldValue && this.modelData != null) return;
@ -52,7 +52,14 @@ export default class Datalist extends Textfield {
validSelection(selection) {
return this.modelData && this.modelData.find(item => {
return item[this.valueField] == selection;
let dataValue = item[this.valueField];
if (typeof(dataValue) === 'string')
dataValue = dataValue.toLowerCase();
if (typeof(selection) === 'string')
selection = selection.toLowerCase();
return dataValue == selection;
});
}

View File

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

View File

@ -3,7 +3,8 @@
ng-model="$ctrl.search"
class="dense search"
ng-blur="$ctrl.onFocusOut()"
placeholder="{{::'Search' | translate}}">
placeholder="{{::'Search' | translate}}"
autocomplete="off">
</vn-textfield>
</div>
<div class="list" tabindex="-1">

View File

@ -132,6 +132,17 @@ export default class Field extends FormInput {
return this.error || this.inputError || null;
}
get autocomplete() {
return this._autocomplete;
}
set autocomplete(value) {
this._autocomplete = value;
if (value === 'off')
this.input.setAttribute('autocomplete', 'off');
}
refreshHint() {
let error = this.shownError;
let hint = error || this.hint;
@ -206,6 +217,7 @@ ngModule.vnComponent('vnField', {
controller: Field,
bindings: {
type: '@?',
autocomplete: '@?',
placeholder: '@?',
value: '=?',
info: '@?',

View File

@ -30,7 +30,7 @@
ng-click="$ctrl.onClear($event)">
</vn-icon>
<vn-icon
icon="cloud_upload"
icon="icon-attach"
vn-tooltip="Select a file"
ng-click="$ctrl.openFileSelector()">
</vn-icon>

View File

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

View File

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

View File

@ -22,7 +22,7 @@ describe('Component vnPopover', () => {
describe('show()', () => {
it(`should enable the shown property and emit the open event`, () => {
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.show();
expect(controller.shown).toBeTruthy();
@ -31,13 +31,13 @@ describe('Component vnPopover', () => {
it(`should do nothing if it's already shown`, () => {
controller.shown = true;
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.show();
expect(controller.emit).not.toHaveBeenCalledWith('open');
});
//#1615 migrar karma a jest (this doesn't work anymore, needs fixing)
// #1615 migrar karma a jest (this doesn't work anymore, needs fixing)
xit(`should check that popover is visible into the screen`, () => {
$parent.css({
backgroundColor: 'red',
@ -65,7 +65,7 @@ describe('Component vnPopover', () => {
describe('hide()', () => {
it(`should disable the shown property and emit the close event`, inject($timeout => {
controller.show();
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.hide();
$timeout.flush();
@ -75,7 +75,7 @@ describe('Component vnPopover', () => {
it(`should do nothing if it's already hidden`, () => {
controller.shown = false;
spyOn(controller, 'emit');
jest.spyOn(controller, 'emit');
controller.hide();
expect(controller.emit).not.toHaveBeenCalledWith('close');

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -100,7 +100,9 @@ export default class Watcher extends Component {
*/
submit() {
try {
this.check();
if (this.requestMethod() !== 'post')
this.check();
else this.isInvalid();
} catch (err) {
return this.$q.reject(err);
}
@ -120,12 +122,12 @@ export default class Watcher extends Component {
if (this.form)
this.form.$setSubmitted();
if (!this.dataChanged()) {
const isPost = (this.requestMethod() === 'post');
if (!this.dataChanged() && !isPost) {
this.updateOriginalData();
return this.$q.resolve();
}
let isPost = (this.$attrs.save && this.$attrs.save.toLowerCase() === 'post');
let changedData = isPost
? this.data
: getModifiedData(this.data, this.orgData);
@ -158,7 +160,6 @@ export default class Watcher extends Component {
});
}
return this.$q((resolve, reject) => {
this.$http.post(this.url, changedData).then(
json => this.writeData(json, resolve),
@ -166,6 +167,13 @@ export default class Watcher extends Component {
);
});
}
/**
* return the request method.
*/
requestMethod() {
return this.$attrs.save && this.$attrs.save.toLowerCase();
}
/**
* Checks if data is ready to send.
@ -177,6 +185,14 @@ export default class Watcher extends Component {
throw new UserError('No changes to save');
}
/**
* Checks if the form is valid.
*/
isInvalid() {
if (this.form && this.form.$invalid)
throw new UserError('Some fields are invalid');
}
/**
* Notifies the user that the data has been saved.
*/

View File

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

View File

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

View File

@ -0,0 +1,66 @@
describe('Directive http-click', () => {
let $scope;
let element;
let compile;
beforeEach(ngModule('vnCore'));
compile = (_element, _childElement) => {
inject(($compile, $rootScope) => {
$scope = $rootScope.$new();
element = angular.element(_element);
$compile(element)($scope);
$scope.$digest();
});
};
it('should call click function on the element, disable it and then enable it again', () => {
let html = `<input vn-http-click="myEvent()"/>`;
compile(html);
const myPromise = new Promise(resolve => resolve());
$scope.myEvent = () => {
return myPromise;
};
element[0].$ctrl = {disabled: false};
element[0].click();
expect(element[0].$ctrl.disabled).toEqual(true);
let finalValue;
myPromise.then(() => {
finalValue = 'called!';
expect(element[0].$ctrl.disabled).toEqual(false);
}).finally(() => {
expect(finalValue).toEqual('called!');
});
});
it('should call click function on the element and not disable it', () => {
let html = `<input vn-http-click="myEvent()"/>`;
compile(html);
const myPromise = new Promise(resolve => resolve());
$scope.myEvent = () => {
return myPromise;
};
element[0].$ctrl = {disabled: true};
element[0].click();
expect(element[0].$ctrl.disabled).toEqual(true);
let finalValue;
myPromise.then(() => {
finalValue = 'called!';
expect(element[0].$ctrl.disabled).toEqual(true);
}).finally(() => {
expect(finalValue).toEqual('called!');
}).catch(err => {
throw err;
});
});
});

View File

@ -108,7 +108,10 @@ function runFn(
$filter,
$interpolate,
$window,
vnApp) {
vnApp,
vnToken,
vnConfig,
aclService) {
Object.assign(Component.prototype, {
$translate,
$q,
@ -121,7 +124,10 @@ function runFn(
$filter,
$interpolate,
$window,
vnApp
vnApp,
vnToken,
vnConfig,
aclService
});
}
runFn.$inject = [
@ -136,7 +142,10 @@ runFn.$inject = [
'$filter',
'$interpolate',
'$window',
'vnApp'
'vnApp',
'vnToken',
'vnConfig',
'aclService'
];
ngModule.run(runFn);

View File

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

View File

@ -2,10 +2,11 @@ import ngModule from '../module';
import getMainRoute from '../lib/get-main-route';
export default class Modules {
constructor(aclService, $window) {
constructor(aclService, $window, $translate) {
Object.assign(this, {
aclService,
$window
$window,
$translate
});
}
@ -17,7 +18,7 @@ export default class Modules {
if (this.modules)
return this.modules;
this.modules = [];
const modules = [];
for (let mod of this.$window.routes) {
if (!mod || !mod.routes) continue;
@ -31,7 +32,7 @@ export default class Modules {
if (res) keyBind = res.key.toUpperCase();
}
this.modules.push({
modules.push({
name: mod.name || mod.module,
icon: mod.icon || null,
route,
@ -39,9 +40,16 @@ export default class Modules {
});
}
const sortedModules = modules.sort((a, b) => {
const translatedNameA = this.$translate.instant(a.name);
const translatedNameB = this.$translate.instant(b.name);
return translatedNameA.localeCompare(translatedNameB);
});
this.modules = sortedModules;
return this.modules;
}
}
Modules.$inject = ['aclService', '$window'];
Modules.$inject = ['aclService', '$window', '$translate'];
ngModule.service('vnModules', Modules);

View File

@ -23,6 +23,27 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-zone:before {
content: "\e95d";
}
.icon-inventory:before {
content: "\e95e";
}
.icon-wiki:before {
content: "\e968";
}
.icon-attach:before {
content: "\e96c";
}
.icon-zone2:before {
content: "\e96d";
}
.icon-net:before {
content: "\e95b";
}
.icon-anonymous:before {
content: "\e95c";
}
.icon-buyrequest:before {
content: "\e914";
}
@ -295,4 +316,4 @@
}
.icon-worker:before {
content: "\e943";
}
}

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 108 KiB

View File

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

View File

@ -1,24 +1,8 @@
<a ng-if="$ctrl.links.btnOne"
vn-tooltip="{{::$ctrl.links.btnOne.tooltip}}"
<a ng-repeat="button in $ctrl.links"
vn-tooltip="{{::button.tooltip}}"
class="vn-button colored"
ui-sref="{{::$ctrl.links.btnOne.state}}">
ui-sref="{{::button.state}}">
<vn-icon
icon="{{::$ctrl.links.btnOne.icon}}">
</vn-icon>
</a>
<a ng-if="$ctrl.links.btnTwo"
vn-tooltip="{{::$ctrl.links.btnTwo.tooltip}}"
class="vn-button colored"
ui-sref="{{::$ctrl.links.btnTwo.state}}">
<vn-icon
icon="{{::$ctrl.links.btnTwo.icon}}">
</vn-icon>
</a>
<a ng-if="$ctrl.links.btnThree"
vn-tooltip="{{::$ctrl.links.btnThree.tooltip}}"
class="vn-button colored"
ui-sref="{{::$ctrl.links.btnThree.state}}">
<vn-icon
icon="{{::$ctrl.links.btnThree.icon}}">
icon="{{::button.icon}}">
</vn-icon>
</a>

View File

@ -8,7 +8,7 @@
<div>
<vn-icon icon="{{::mod.icon || 'photo'}}"></vn-icon>
</div>
<h4 ng-bind-html="::$ctrl.getModuleName(mod)"></h4>
<h4 ng-bind-html="$ctrl.getModuleName(mod)"></h4>
<span
ng-show="::mod.keyBind"
vn-tooltip="Ctrl + Alt + {{::mod.keyBind}}">

View File

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

View File

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

View File

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

View File

@ -64,5 +64,6 @@
"Sent units from ticket": "I sent *{{quantity}}* units of [{{concept}} (#{{itemId}})]({{{itemUrl}}}) to *\"{{nickname}}\"* coming from ticket id [#{{ticketId}}]({{{ticketUrl}}})",
"Customs agent is required for a non UEE member": "Customs agent is required for a non UEE member",
"Incoterms is required for a non UEE member": "Incoterms is required for a non UEE member",
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}"
"Client checked as validated despite of duplication": "Client checked as validated despite of duplication from client id {{clientId}}",
"Landing cannot be lesser than shipment": "Landing cannot be lesser than shipment"
}

View File

@ -127,5 +127,7 @@
"Sent units from ticket": "Envio *{{quantity}}* unidades de [{{concept}} (#{{itemId}})]({{{itemUrl}}}) a *\"{{nickname}}\"* provenientes del ticket id [#{{ticketId}}]({{{ticketUrl}}})",
"Client checked as validated despite of duplication": "Cliente comprobado a pesar de que existe el cliente id {{clientId}}",
"ORDER_ROW_UNAVAILABLE": "No hay disponibilidad de este producto",
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000"
"Distance must be lesser than 1000": "La distancia debe ser inferior a 1000",
"This ticket is deleted": "Este ticket está eliminado",
"A travel with this data already exists": "Ya existe un travel con estos datos"
}

View File

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

View File

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

View File

@ -155,7 +155,6 @@ class Controller {
});
}
onUpdateGreugeResponse(response) {
if (response == 'accept') {
const promises = [];

View File

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

View File

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

View File

@ -1,14 +1,11 @@
import ngModule from '../module';
import Component from 'core/lib/component';
class Controller {
constructor($scope, $state, $http, $translate, vnApp, aclService, $httpParamSerializer) {
this.$scope = $scope;
this.$state = $state;
this.$http = $http;
this.$translate = $translate;
this.vnApp = vnApp;
this.aclService = aclService;
class Controller extends Component {
constructor($element, $scope, $httpParamSerializer) {
super($element, $scope);
this.$httpParamSerializer = $httpParamSerializer;
this.moreOptions = [
{callback: this.showPickupOrder, name: 'Show Pickup order'},
{callback: this.confirmPickupOrder, name: 'Send Pickup order'},
@ -22,7 +19,7 @@ class Controller {
return !hasAclProperty || (hasAclProperty && this.aclService.hasAny([option.acl]));
});
this.$scope.moreButton.data = options;
this.$.moreButton.data = options;
}
onMoreChange(callback) {
@ -63,7 +60,8 @@ class Controller {
showPickupOrder() {
const params = {
clientId: this.claim.clientFk,
claimId: this.claim.id
claimId: this.claim.id,
authorization: this.vnToken.token
};
const serializedParams = this.$httpParamSerializer(params);
let url = `api/report/claim-pickup-order?${serializedParams}`;
@ -71,7 +69,7 @@ class Controller {
}
confirmPickupOrder() {
this.$scope.confirmPickupOrder.show();
this.$.confirmPickupOrder.show();
}
sendPickupOrder(response) {
@ -81,16 +79,14 @@ class Controller {
clientId: this.claim.clientFk,
claimId: this.claim.id
};
const serializedParams = this.$httpParamSerializer(params);
const url = `email/claim-pickup-order?${serializedParams}`;
this.$http.get(url).then(
this.$http.get(`email/claim-pickup-order`, {params}).then(
() => this.vnApp.showMessage(this.$translate.instant('Notification sent!'))
);
}
}
confirmDeleteClaim() {
this.$scope.confirmDeleteClaim.show();
this.$.confirmDeleteClaim.show();
}
deleteClaim(response) {
@ -103,7 +99,7 @@ class Controller {
}
}
Controller.$inject = ['$scope', '$state', '$http', '$translate', 'vnApp', 'aclService', '$httpParamSerializer'];
Controller.$inject = ['$element', '$scope', '$httpParamSerializer'];
ngModule.component('vnClaimDescriptor', {
template: require('./index.html'),

View File

@ -3,14 +3,19 @@ import './index.js';
describe('Item Component vnClaimDescriptor', () => {
let $httpParamSerializer;
let $httpBackend;
let $element;
let $scope;
let controller;
beforeEach(ngModule('claim'));
beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$httpParamSerializer_) => {
beforeEach(angular.mock.inject(($componentController, $rootScope, _$httpBackend_, _$httpParamSerializer_) => {
$httpBackend = _$httpBackend_;
$httpParamSerializer = _$httpParamSerializer_;
controller = $componentController('vnClaimDescriptor');
$scope = $rootScope.$new();
$element = angular.element('<vn-claim-descriptor></vn-claim-descriptor>');
controller = $componentController('vnClaimDescriptor', {$element, $scope});
controller.claim = {id: 2, clientFk: 101, client: {email: 'client@email'}};
}));
@ -22,7 +27,7 @@ describe('Item Component vnClaimDescriptor', () => {
};
const serializedParams = $httpParamSerializer(params);
let expectedPath = `api/report/claim-pickup-order?${serializedParams}`;
spyOn(window, 'open');
jest.spyOn(window, 'open').mockReturnThis();
controller.showPickupOrder();
expect(window.open).toHaveBeenCalledWith(expectedPath);
@ -31,19 +36,19 @@ describe('Item Component vnClaimDescriptor', () => {
describe('confirmPickupOrder()', () => {
it('should call confirmPickupOrder.show()', () => {
controller.$scope.confirmPickupOrder = {
controller.$.confirmPickupOrder = {
show: jasmine.createSpy('show')
};
controller.claim = {id: 2};
controller.confirmPickupOrder();
expect(controller.$scope.confirmPickupOrder.show).toHaveBeenCalledWith();
expect(controller.$.confirmPickupOrder.show).toHaveBeenCalledWith();
});
});
describe('sendPickupOrder(response)', () => {
it('should make a query and call vnApp.showMessage() if the response is accept', () => {
spyOn(controller.vnApp, 'showMessage');
jest.spyOn(controller.vnApp, 'showMessage');
const params = {
recipient: 'client@email',
@ -63,13 +68,13 @@ describe('Item Component vnClaimDescriptor', () => {
describe('confirmDeleteClaim()', () => {
it('should call confirmDeleteClaim.show()', () => {
controller.$scope.confirmDeleteClaim = {
controller.$.confirmDeleteClaim = {
show: jasmine.createSpy('show')
};
controller.claim = {id: 2};
controller.confirmDeleteClaim();
expect(controller.$scope.confirmDeleteClaim.show).toHaveBeenCalledWith();
expect(controller.$.confirmDeleteClaim.show).toHaveBeenCalledWith();
});
});
@ -78,8 +83,8 @@ describe('Item Component vnClaimDescriptor', () => {
let response = 'accept';
controller.claim = {id: 2};
spyOn(controller.vnApp, 'showSuccess');
spyOn(controller.$state, 'go');
jest.spyOn(controller.vnApp, 'showSuccess');
jest.spyOn(controller.$state, 'go');
$httpBackend.when('DELETE', `Claims/2`).respond(200);
$httpBackend.expect('DELETE', `Claims/2`);
controller.deleteClaim(response);

View File

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

View File

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

View File

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

View File

@ -10,24 +10,17 @@
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Client Id"]
ng-model="filter.clientFk">
</vn-textfield>
<vn-textfield
vn-one
label="Client"
ng-model="filter.client">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-textfield
vn-one
label="Claim Id"
ng-model="filter.id">
</vn-textfield>
<vn-textfield
vn-one
label="Client Id"
ng-model="filter.clientFk">
</vn-textfield>
</vn-horizontal>
<vn-horizontal>
<vn-autocomplete
vn-one

View File

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

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