import { useI18n } from 'vue-i18n';
-import { useRoute } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import LeftMenu from 'src/components/LeftMenu.vue';
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
-import ZoneFilterPanel from './ZoneFilterPanel.vue';
const { t } = useI18n();
const stateStore = useStateStore();
-const route = useRoute();
const exprBuilder = (param, value) => {
switch (param) {
@@ -41,32 +38,17 @@ const exprBuilder = (param, value) => {
-
-
-
-
-
-
-
-
-
-
+
diff --git a/src/pages/Zone/locale/en.yml b/src/pages/Zone/locale/en.yml
index bae89fda9..31eeb2b7f 100644
--- a/src/pages/Zone/locale/en.yml
+++ b/src/pages/Zone/locale/en.yml
@@ -7,6 +7,7 @@ zone:
deliveryDays: Delivery days
upcomingDeliveries: Upcoming deliveries
warehouses: Warehouses
+ calendar: Calendar
list:
clone: Clone
id: Id
@@ -42,6 +43,8 @@ summary:
filterPanel:
name: Name
agencyModeFk: Agency
+zoneLocations:
+ locations: Locations
deliveryPanel:
pickup: Pick up
delivery: Delivery
@@ -64,6 +67,41 @@ warehouses:
deleteSubtitle: Are you sure you want to continue?
warehouse: Warehouse
add: Add
+eventsPanel:
+ editMode: Edit mode
+ include: Include
+ exclude: Exclude
+ events: Events
+ closing: Closing
+ travelingDays: Traveling days
+ price: Price
+ bonus: Bonus
+ m3Max: Max m³
+ everyday: Everyday
+ delete: Delete
+ deleteTitle: This item will be deleted
+ deleteSubtitle: Are you sure you want to continue?
+eventsExclusionForm:
+ addExclusion: Add exclusion
+ editExclusion: Edit exclusion
+ day: Day
+ all: All
+ specificLocations: Specific locations
+ rootTreeLabel: Locations where it is not distributed
+eventsInclusionForm:
+ addEvent: Add event
+ editEvent: Edit event
+ oneDay: One day
+ indefinitely: Indefinitely
+ rangeOfDates: Range of dates
+ day: Day
+ closing: Closing
+ travelingDays: Traveling days
+ price: Price
+ bonus: Bonus
+ m3Max: Max m³
+ from: From
+ to: To
upcomingDeliveries:
province: Province
closing: Closing
diff --git a/src/pages/Zone/locale/es.yml b/src/pages/Zone/locale/es.yml
index d74238a6e..c670c2c08 100644
--- a/src/pages/Zone/locale/es.yml
+++ b/src/pages/Zone/locale/es.yml
@@ -7,6 +7,7 @@ zone:
deliveryDays: Días de entrega
upcomingDeliveries: Próximos repartos
warehouses: Almacenes
+ calendar: Calendario
list:
clone: Clonar
id: Id
@@ -42,6 +43,8 @@ summary:
filterPanel:
name: Nombre
agencyModeFk: Agencia
+zoneLocations:
+ locations: Localizaciones
deliveryPanel:
pickup: Recogida
delivery: Entrega
@@ -66,6 +69,41 @@ warehouses:
deleteSubtitle: ¿Seguro que quieres continuar?
warehouse: Almacén
add: Añadir
+eventsPanel:
+ editMode: Modo edición
+ include: Incluir
+ exclude: Excluir
+ events: Eventos
+ closing: Cierre
+ travelingDays: Días de viaje
+ price: Precio
+ bonus: Bonificación
+ m3Max: Meidida máxima
+ everyday: Todos los días
+ delete: Eliminar
+ deleteTitle: Este elemento será eliminado
+ deleteSubtitle: ¿Seguro que quieres continuar?
+eventsExclusionForm:
+ addExclusion: Añadir exclusión
+ editExclusion: Editar exclusión
+ day: Día
+ all: Todo
+ specificLocations: Localizaciones concretas
+ rootTreeLabel: Localizaciones en las que no se reparte
+eventsInclusionForm:
+ addEvent: Añadir evento
+ editEvent: Editar evento
+ oneDay: Un día
+ indefinitely: Indefinido
+ rangeOfDates: Rango de fechas
+ day: Día
+ closing: Cierre
+ travelingDays: Días de viaje
+ price: Precio
+ bonus: Bonificación
+ m3Max: Medida máxima
+ from: Desde
+ to: Hasta
upcomingDeliveries:
province: Provincia
closing: Cierre
diff --git a/src/router/index.js b/src/router/index.js
index 7a0aedcae..41ff4c1da 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -13,6 +13,7 @@ import { useRole } from 'src/composables/useRole';
import { useUserConfig } from 'src/composables/useUserConfig';
import { toLowerCamel } from 'src/filters';
import { useTokenConfig } from 'src/composables/useTokenConfig';
+import { useAcl } from 'src/composables/useAcl';
const state = useState();
const session = useSession();
@@ -55,6 +56,7 @@ export default route(function (/* { store, ssrContext } */) {
const stateRoles = state.getRoles().value;
if (stateRoles.length === 0) {
await useRole().fetch();
+ await useAcl().fetch();
await useUserConfig().fetch();
await useTokenConfig().fetch();
}
diff --git a/src/router/modules/account.js b/src/router/modules/account.js
new file mode 100644
index 000000000..019c91f4d
--- /dev/null
+++ b/src/router/modules/account.js
@@ -0,0 +1,83 @@
+import { RouterView } from 'vue-router';
+
+export default {
+ path: '/account',
+ name: 'Account',
+ meta: {
+ title: 'users',
+ icon: 'face',
+ moduleName: 'Account',
+ },
+ component: RouterView,
+ redirect: { name: 'AccountMain' },
+ menus: {
+ main: [
+ 'AccountList',
+ 'AccountAliasList',
+ 'AccountRoles',
+ 'AccountAcls',
+ 'AccountConnections',
+ ],
+ card: [],
+ },
+ children: [
+ {
+ path: '',
+ name: 'AccountMain',
+ component: () => import('src/pages/Account/AccountMain.vue'),
+ redirect: { name: 'AccountList' },
+ children: [
+ {
+ path: 'list',
+ name: 'AccountList',
+ meta: {
+ title: 'list',
+ icon: 'view_list',
+ },
+ component: () => import('src/pages/Account/AccountList.vue'),
+ },
+ {
+ path: 'alias-list',
+ name: 'AccountAliasList',
+ meta: {
+ title: 'alias',
+ icon: 'email',
+ },
+ component: () => import('src/pages/Account/AccountAliasList.vue'),
+ },
+ {
+ path: 'connections',
+ name: 'AccountConnections',
+ meta: {
+ title: 'connections',
+ icon: 'check',
+ },
+ component: () => import('src/pages/Account/AccountConnections.vue'),
+ },
+ {
+ path: 'acls',
+ name: 'AccountAcls',
+ meta: {
+ title: 'acls',
+ icon: 'check',
+ },
+ component: () => import('src/pages/Account/AccountAcls.vue'),
+ },
+ {
+ path: 'acl-form',
+ name: 'AccountAclForm',
+ component: () => import('src/pages/Account/Acls/AclFormView.vue'),
+ },
+ {
+ path: 'role-list',
+ name: 'AccountRoles',
+ meta: {
+ title: 'roles',
+ icon: 'group',
+ },
+ component: () => import('src/pages/Account/Role/AccountRoles.vue'),
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/router/modules/index.js b/src/router/modules/index.js
index 38bcd54d5..bf7e46b00 100644
--- a/src/router/modules/index.js
+++ b/src/router/modules/index.js
@@ -18,7 +18,10 @@ import Parking from './parking';
import Agency from './agency';
import ItemType from './itemType';
import Zone from './zone';
+import Account from './account';
import Monitor from './monitor';
+import MailAlias from './mailAlias';
+import Role from './role';
export default [
Item,
@@ -41,5 +44,8 @@ export default [
Agency,
ItemType,
Zone,
+ Account,
+ MailAlias,
Monitor,
+ Role,
];
diff --git a/src/router/modules/invoiceIn.js b/src/router/modules/invoiceIn.js
index 869a3555a..75d0612aa 100644
--- a/src/router/modules/invoiceIn.js
+++ b/src/router/modules/invoiceIn.js
@@ -37,6 +37,15 @@ export default {
},
component: () => import('src/pages/InvoiceIn/InvoiceInList.vue'),
},
+ {
+ path: 'create',
+ name: 'InvoiceInCreare',
+ meta: {
+ title: 'invoiceInCreate',
+ icon: 'create',
+ },
+ component: () => import('src/pages/InvoiceIn/InvoiceInCreate.vue'),
+ },
],
},
{
diff --git a/src/router/modules/mailAlias.js b/src/router/modules/mailAlias.js
new file mode 100644
index 000000000..8e0f8abdc
--- /dev/null
+++ b/src/router/modules/mailAlias.js
@@ -0,0 +1,57 @@
+import { RouterView } from 'vue-router';
+
+export default {
+ path: 'account/alias',
+ name: 'Alias',
+ meta: {
+ title: 'alias',
+ icon: 'email',
+ moduleName: 'Alias',
+ },
+ component: RouterView,
+ redirect: { name: 'AccountAliasList' },
+ menus: {
+ main: [],
+ card: ['AliasBasicData', 'AliasUsers'],
+ },
+ children: [
+ {
+ name: 'AliasCard',
+ path: ':id',
+ component: () => import('src/pages/Account/Alias/Card/AliasCard.vue'),
+ redirect: { name: 'AliasSummary' },
+ children: [
+ {
+ name: 'AliasSummary',
+ path: 'summary',
+ meta: {
+ title: 'summary',
+ icon: 'launch',
+ },
+ component: () =>
+ import('src/pages/Account/Alias/Card/AliasSummary.vue'),
+ },
+ {
+ name: 'AliasBasicData',
+ path: 'basic-data',
+ meta: {
+ title: 'basicData',
+ icon: 'vn:settings',
+ },
+ component: () =>
+ import('src/pages/Account/Alias/Card/AliasBasicData.vue'),
+ },
+ {
+ name: 'AliasUsers',
+ path: 'users',
+ meta: {
+ title: 'aliasUsers',
+ icon: 'group',
+ },
+ component: () =>
+ import('src/pages/Account/Alias/Card/AliasUsers.vue'),
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/router/modules/role.js b/src/router/modules/role.js
new file mode 100644
index 000000000..47cd10b18
--- /dev/null
+++ b/src/router/modules/role.js
@@ -0,0 +1,76 @@
+import { RouterView } from 'vue-router';
+
+export default {
+ path: 'account/role',
+ name: 'Role',
+ meta: {
+ title: 'role',
+ icon: 'vn:greuge',
+ moduleName: 'Role',
+ },
+ component: RouterView,
+ redirect: { name: 'AccountRoles' },
+ menus: {
+ main: [],
+ card: ['RoleBasicData', 'SubRoles', 'InheritedRoles', 'RoleLog'],
+ },
+ children: [
+ {
+ name: 'RoleCard',
+ path: ':id',
+ component: () => import('src/pages/Account/Role/Card/RoleCard.vue'),
+ redirect: { name: 'RoleSummary' },
+ children: [
+ {
+ name: 'RoleSummary',
+ path: 'summary',
+ meta: {
+ title: 'summary',
+ icon: 'launch',
+ },
+ component: () =>
+ import('src/pages/Account/Role/Card/RoleSummary.vue'),
+ },
+ {
+ name: 'RoleBasicData',
+ path: 'basic-data',
+ meta: {
+ title: 'basicData',
+ icon: 'vn:settings',
+ },
+ component: () =>
+ import('src/pages/Account/Role/Card/RoleBasicData.vue'),
+ },
+ {
+ name: 'SubRoles',
+ path: 'sub-roles',
+ meta: {
+ title: 'subRoles',
+ icon: 'group',
+ },
+ component: () => import('src/pages/Account/Role/Card/SubRoles.vue'),
+ },
+
+ {
+ name: 'InheritedRoles',
+ path: 'inherited-roles',
+ meta: {
+ title: 'inheritedRoles',
+ icon: 'account_tree',
+ },
+ component: () =>
+ import('src/pages/Account/Role/Card/InheritedRoles.vue'),
+ },
+ {
+ name: 'RoleLog',
+ path: 'log',
+ meta: {
+ title: 'log',
+ icon: 'history',
+ },
+ component: () => import('src/pages/Account/Role/Card/RoleLog.vue'),
+ },
+ ],
+ },
+ ],
+};
diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js
index 384978d13..927d11802 100644
--- a/src/router/modules/worker.js
+++ b/src/router/modules/worker.js
@@ -24,7 +24,6 @@ export default {
'WorkerTimeControl',
'WorkerLocker',
],
- departmentCard: ['BasicData'],
},
children: [
{
diff --git a/src/router/modules/zone.js b/src/router/modules/zone.js
index c355856b1..fd6fa959b 100644
--- a/src/router/modules/zone.js
+++ b/src/router/modules/zone.js
@@ -11,8 +11,19 @@ export default {
component: RouterView,
redirect: { name: 'ZoneMain' },
menus: {
- main: ['ZoneList', 'ZoneDeliveryDays', 'ZoneUpcomingDeliveries'],
- card: ['ZoneBasicData', 'ZoneWarehouses', 'ZoneHistory', 'ZoneLocations'],
+ main: [
+ 'ZoneList',
+ 'ZoneDeliveryDays',
+ 'ZoneUpcomingList',
+ 'ZoneUpcomingDeliveries',
+ ],
+ card: [
+ 'ZoneBasicData',
+ 'ZoneWarehouses',
+ 'ZoneHistory',
+ 'ZoneLocations',
+ 'ZoneEvents',
+ ],
},
children: [
{
@@ -106,7 +117,7 @@ export default {
path: 'location',
meta: {
title: 'locations',
- icon: 'vn:greuge',
+ icon: 'my_location',
},
component: () => import('src/pages/Zone/Card/ZoneLocations.vue'),
},
@@ -128,6 +139,15 @@ export default {
},
component: () => import('src/pages/Zone/Card/ZoneLog.vue'),
},
+ {
+ name: 'ZoneEvents',
+ path: 'events',
+ meta: {
+ title: 'calendar',
+ icon: 'vn:calendar',
+ },
+ component: () => import('src/pages/Zone/Card/ZoneEvents.vue'),
+ },
],
},
],
diff --git a/src/router/routes.js b/src/router/routes.js
index 6a0430d51..805eefb8c 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -2,14 +2,15 @@ import item from './modules/item';
import customer from './modules/customer';
import ticket from './modules/ticket';
import claim from './modules/claim';
+import route from './modules/route';
import worker from './modules/worker';
import invoiceOut from './modules/invoiceOut';
import invoiceIn from './modules/invoiceIn';
import wagon from './modules/wagon';
import supplier from './modules/Supplier';
-import route from './modules/route';
import travel from './modules/travel';
import department from './modules/department';
+import role from './modules/role';
import ItemType from './modules/itemType';
import shelving from 'src/router/modules/shelving';
import order from 'src/router/modules/order';
@@ -18,7 +19,9 @@ import roadmap from 'src/router/modules/roadmap';
import parking from 'src/router/modules/parking';
import agency from 'src/router/modules/agency';
import zone from 'src/router/modules/zone';
+import account from './modules/account';
import monitor from 'src/router/modules/monitor';
+import mailAlias from './modules/mailAlias';
const routes = [
{
@@ -79,6 +82,9 @@ const routes = [
agency,
ItemType,
zone,
+ account,
+ role,
+ mailAlias,
{
path: '/:catchAll(.*)*',
name: 'NotFound',
diff --git a/src/stores/useNavigationStore.js b/src/stores/useNavigationStore.js
index 263a9dec8..4dd5ed2ae 100644
--- a/src/stores/useNavigationStore.js
+++ b/src/stores/useNavigationStore.js
@@ -23,6 +23,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
'worker',
'wagon',
'zone',
+ 'account',
];
const pinnedModules = ref([]);
const role = useRole();
diff --git a/src/stores/useWeekdayStore.js b/src/stores/useWeekdayStore.js
index ac17356ae..57a302dc1 100644
--- a/src/stores/useWeekdayStore.js
+++ b/src/stores/useWeekdayStore.js
@@ -73,6 +73,22 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
return locales;
});
+ const getLocalesMap = computed(() => {
+ const locales = {};
+ for (let code of localeOrder.es) {
+ const weekDay = weekdaysMap[code];
+ const locale = t(`weekdays.${weekdaysMap[code].code}`);
+ const obj = {
+ ...weekDay,
+ locale,
+ localeChar: locale.substr(0, 1),
+ localeAbr: locale.substr(0, 3),
+ };
+ locales[weekDay.code] = obj;
+ }
+ return locales;
+ });
+
const getLocaleMonths = computed(() => {
const locales = [];
for (let code of monthCodes) {
@@ -106,6 +122,28 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
return wdays;
};
+ /**
+ * Perform the inverse operation of fromSet() method. Transforms an
+ * array whose indexes are weekday index with selected days set to %true to
+ * weekday codes separated by commas.
+ *
+ * @param {Array} _weekDays Array with selected days set to %true
+ * @return {String} weekDays Weekday codes separated by commas
+ */
+ const toSet = (_weekDays) => {
+ let wdays = [];
+
+ if (_weekDays) {
+ for (let i = 0; i < _weekDays.length; i++) {
+ if (!_weekDays[i]) continue;
+ let data = weekdays[i];
+ if (data) wdays.push(data.code);
+ }
+ }
+
+ return wdays.join(',');
+ };
+
return {
initStore,
weekdaysMap,
@@ -115,5 +153,7 @@ export const useWeekdayStore = defineStore('weekdayStore', () => {
monthCodes,
getLocaleMonths,
fromSet,
+ toSet,
+ getLocalesMap,
};
});
diff --git a/test/cypress/integration/agency/agencyWorkCenter.spec.js b/test/cypress/integration/agency/agencyWorkCenter.spec.js
index ff3c53214..8349260ee 100644
--- a/test/cypress/integration/agency/agencyWorkCenter.spec.js
+++ b/test/cypress/integration/agency/agencyWorkCenter.spec.js
@@ -13,7 +13,6 @@ describe('AgencyWorkCenter', () => {
cy.get(
'.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'
).type('workCenterOne{enter}');
- cy.get('.q-btn--standard > .q-btn__content > .block').click();
cy.get('.q-notification__message').should('have.text', 'Data created');
});
@@ -35,13 +34,11 @@ describe('AgencyWorkCenter', () => {
cy.get(
'.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'
).type('workCenterOne{enter}');
- cy.get('.q-btn--standard > .q-btn__content > .block').click();
cy.get('.q-notification__message').should('have.text', 'Data created');
cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click();
cy.get(
'.vn-row > .q-field > .q-field__inner > .q-field__control > .q-field__control-container'
).type('workCenterOne{enter}');
- cy.get('.q-btn--standard > .q-btn__content > .block').click();
cy.get(
':nth-child(2) > .q-notification__wrapper > .q-notification__content > .q-notification__message'
diff --git a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
index 963dda3e2..77a11969b 100644
--- a/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInBasicData.spec.js
@@ -2,8 +2,7 @@
describe('InvoiceInBasicData', () => {
const formInputs = '.q-form > .q-card input';
const firstFormSelect = '.q-card > .vn-row:nth-child(1) > .q-select';
- const appendBtns = '.q-form label button';
- const dialogAppendBtns = '.q-dialog label button';
+ const documentBtns = '.q-form .q-field button';
const dialogInputs = '.q-dialog input';
const dialogActionBtns = '.q-card__actions button';
@@ -15,8 +14,7 @@ describe('InvoiceInBasicData', () => {
it('should edit the provideer and supplier ref', () => {
cy.selectOption(firstFormSelect, 'Bros');
cy.get('[title="Reset"]').click();
- cy.get(appendBtns).eq(0).click();
- cy.get(formInputs).eq(1).type(4739);
+ cy.get(formInputs).eq(1).type('{selectall}4739');
cy.saveCard();
cy.get(`${firstFormSelect} input`).invoke('val').should('eq', 'Plants nick');
@@ -27,22 +25,20 @@ describe('InvoiceInBasicData', () => {
const firtsInput = 'Ticket:65';
const secondInput = "I don't know what posting here!";
- cy.get(appendBtns).eq(3).click();
- cy.get(dialogAppendBtns).eq(0).click();
- cy.get(dialogInputs).eq(0).type(firtsInput);
- cy.get(dialogAppendBtns).eq(1).click();
- cy.get('textarea').type(secondInput);
+ cy.get(documentBtns).eq(1).click();
+ cy.get(dialogInputs).eq(0).type(`{selectall}${firtsInput}`);
+ cy.get('textarea').type(`{selectall}${secondInput}`);
cy.get(dialogActionBtns).eq(1).click();
- cy.get(appendBtns).eq(3).click();
-
+ cy.get(documentBtns).eq(1).click();
cy.get(dialogInputs).eq(0).invoke('val').should('eq', firtsInput);
cy.get('textarea').invoke('val').should('eq', secondInput);
});
it('should throw an error creating a new dms if a file is not attached', () => {
- cy.get(appendBtns).eq(2).click();
- cy.get(appendBtns).eq(1).click();
+ cy.get(formInputs).eq(5).click();
+ cy.get(formInputs).eq(5).type('{selectall}{backspace}');
+ cy.get(documentBtns).eq(0).click();
cy.get(dialogActionBtns).eq(1).click();
cy.get('.q-notification__message').should(
'have.text',
diff --git a/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js
new file mode 100644
index 000000000..f2d9a3497
--- /dev/null
+++ b/test/cypress/integration/invoiceIn/invoiceInDescriptor.spec.js
@@ -0,0 +1,24 @@
+describe('InvoiceInDescriptor', () => {
+ const dialogBtns = '.q-card__actions button';
+ const firstDescritorOpt = '.q-menu > .q-list > :nth-child(1) > .q-item__section';
+ const isBookedField =
+ '.q-card:nth-child(3) .vn-label-value:nth-child(5) > .value > span';
+
+ it('should booking and unbooking the invoice properly', () => {
+ cy.login('developer');
+ cy.visit(`/#/invoice-in/1/summary?limit=10`);
+
+ cy.openLeftMenu();
+ cy.openActionsDescriptor();
+ cy.get(firstDescritorOpt).click();
+ cy.get(dialogBtns).eq(1).click();
+ cy.get('.fullscreen').first().click();
+ cy.get(isBookedField).should('have.attr', 'title', 'true');
+
+ cy.openLeftMenu();
+ cy.openActionsDescriptor();
+ cy.get(firstDescritorOpt).click();
+ cy.get(dialogBtns).eq(1).click();
+ cy.get(isBookedField).should('have.attr', 'title', 'false');
+ });
+});
diff --git a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
index 389be671c..63e99eac1 100644
--- a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
+++ b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js
@@ -18,7 +18,7 @@ describe('InvoiceInVat', () => {
cy.saveCard();
cy.visit(`/#/invoice-in/1/vat`);
- cy.getValue(firstLineVat).should('equal', 'H.P. IVA 21% CEE');
+ cy.getValue(firstLineVat).should('equal', '8');
});
it('should add a new row', () => {
diff --git a/test/cypress/integration/vnLog.spec.js b/test/cypress/integration/vnLog.spec.js
index 80b9d07df..4db724e99 100644
--- a/test/cypress/integration/vnLog.spec.js
+++ b/test/cypress/integration/vnLog.spec.js
@@ -9,15 +9,15 @@ describe('VnLog', () => {
cy.visit(`/#/claim/${1}/log`);
cy.openRightMenu();
});
-
- it('should filter by insert actions', () => {
+ // Se tiene que cambiar el Accept-Language a 'en', ya hay una tarea para eso #7189.
+ xit('should filter by insert actions', () => {
cy.checkOption(':nth-child(7) > .q-checkbox');
cy.get('.q-page').click();
cy.validateContent(chips[0], 'Document');
cy.validateContent(chips[1], 'Beginning');
});
- it('should filter by entity', () => {
+ xit('should filter by entity', () => {
cy.selectOption('.q-drawer--right .q-item > .q-select', 'Claim');
cy.get('.q-page').click();
cy.validateContent(chips[0], 'Claim');
diff --git a/test/cypress/integration/worker/workerCreate.spec.js b/test/cypress/integration/worker/workerCreate.spec.js
new file mode 100644
index 000000000..26ce899c8
--- /dev/null
+++ b/test/cypress/integration/worker/workerCreate.spec.js
@@ -0,0 +1,59 @@
+describe('WorkerCreate', () => {
+ const externalRadio = '.q-toolbar .q-radio:nth-child(2)';
+ const notification = '.q-notification__message';
+ const developerBossId = 120;
+
+ const internal = {
+ Fi: { val: '78457139E' },
+ 'Web user': { val: 'manolo' },
+ Name: { val: 'Manolo' },
+ 'Last name': { val: 'Hurtado' },
+ 'Personal email': { val: 'manolo@mydomain.com' },
+ Street: { val: 'S/ DEFAULTWORKERSTREET' },
+ Location: { val: 1, type: 'select' },
+ Phone: { val: '123456789' },
+ 'Worker code': { val: 'DWW' },
+ Boss: { val: developerBossId, type: 'select' },
+ Birth: { val: '2022-12-11T23:00:00.000Z', type: 'date', day: 11 },
+ };
+ const external = {
+ Fi: { val: 'Z4531219V' },
+ 'Web user': { val: 'pepe' },
+ Name: { val: 'PEPE' },
+ 'Last name': { val: 'GARCIA' },
+ 'Personal email': { val: 'pepe@gmail.com' },
+ 'Worker code': { val: 'PG' },
+ Boss: { val: developerBossId, type: 'select' },
+ };
+
+ beforeEach(() => {
+ cy.viewport(1280, 720);
+ cy.login('hr');
+ cy.visit('/#/worker/create');
+ });
+
+ it('should throw an error if a pay method has not been selected', () => {
+ cy.fillInForm(internal);
+ cy.saveCard();
+ cy.get(notification).should(
+ 'contains.text',
+ 'That payment method requires an IBAN'
+ );
+ });
+
+ it('should create an internal', () => {
+ cy.fillInForm({
+ ...internal,
+ 'Pay method': { val: 'PayMethod one', type: 'select' },
+ });
+ cy.saveCard();
+ cy.get(notification).should('contains.text', 'Data created');
+ });
+
+ it('should create an external', () => {
+ cy.get(externalRadio).click();
+ cy.fillInForm(external);
+ cy.saveCard();
+ cy.get(notification).should('contains.text', 'Data created');
+ });
+});
diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js
index 1e9292626..9808fd157 100644
--- a/test/cypress/integration/worker/workerList.spec.js
+++ b/test/cypress/integration/worker/workerList.spec.js
@@ -8,13 +8,13 @@ describe('WorkerList', () => {
});
it('should load workers', () => {
- cy.get(workerFieldNames).eq(0).should('have.text', 'jessicajones');
- cy.get(workerFieldNames).eq(1).should('have.text', 'brucebanner');
- cy.get(workerFieldNames).eq(2).should('have.text', 'charlesxavier');
+ cy.get(workerFieldNames).eq(2).should('have.text', 'jessicajones');
+ cy.get(workerFieldNames).eq(3).should('have.text', 'brucebanner');
+ cy.get(workerFieldNames).eq(4).should('have.text', 'charlesxavier');
});
it('should open the worker summary', () => {
- cy.openListSummary(0);
+ cy.openListSummary(2);
cy.get('.summaryHeader div').should('have.text', '1110 - Jessica Jones');
cy.get('.summary .header-link')
.eq(0)
diff --git a/test/cypress/integration/worker/workerLocker.spec.js b/test/cypress/integration/worker/workerLocker.spec.js
index 01e74760b..ef2f88300 100644
--- a/test/cypress/integration/worker/workerLocker.spec.js
+++ b/test/cypress/integration/worker/workerLocker.spec.js
@@ -1,6 +1,6 @@
-describe('WorkerList', () => {
+describe('WorkerLocker', () => {
const workerId = 1109;
- const lockerCode = '201A';
+ const lockerCode = '2F';
const input = '.q-card input';
const firstOpt = '[role="listbox"] .q-item:nth-child(1)';
beforeEach(() => {
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index e7f8cb9d9..055cb8021 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -86,14 +86,49 @@ Cypress.Commands.add('selectOption', (selector, option) => {
cy.get('.q-menu .q-item').contains(option).click();
});
+Cypress.Commands.add('fillInForm', (obj, form = '.q-form > .q-card') => {
+ const days = '.q-date__calendar-days .q-date__calendar-item--in';
+ cy.waitForElement('.q-form > .q-card');
+ cy.get(`${form} input`).each(([el]) => {
+ cy.wrap(el)
+ .invoke('attr', 'aria-label')
+ .then((ariaLabel) => {
+ const field = obj[ariaLabel];
+ if (!field) return;
+
+ const { type, val, day } = field;
+ switch (type) {
+ case 'select':
+ cy.wrap(el).type(val);
+ cy.get('.q-menu .q-item').contains(val).click();
+ break;
+ case 'date':
+ cy.wrap(el).click();
+ cy.get(days)
+ .eq(day ? day - 1 : 0)
+ .click();
+ break;
+ default:
+ cy.wrap(el).type(val);
+ break;
+ }
+ });
+ });
+});
+
Cypress.Commands.add('checkOption', (selector) => {
cy.get(selector).find('.q-checkbox__inner').click();
});
// Global buttons
Cypress.Commands.add('saveCard', () => {
+ const dropdownArrow = '.q-btn-dropdown__arrow-container > .q-btn__content > .q-icon';
+ cy.get('#st-actions').then(($el) => {
+ if ($el.find(dropdownArrow).length) cy.get(dropdownArrow).click();
+ });
cy.get('[title="Save"]').click();
});
+
Cypress.Commands.add('resetCard', () => {
cy.get('[title="Reset"]').click();
});
@@ -193,11 +228,15 @@ Cypress.Commands.add('closeSideMenu', (element) => {
Cypress.Commands.add('clearSearchbar', (element) => {
if (element) cy.waitForElement(element);
- cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').clear();
+ cy.get(
+ '#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input'
+ ).clear();
});
Cypress.Commands.add('writeSearchbar', (value) => {
- cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').type(value);
+ cy.get('#searchbar > form > div:nth-child(1) > label > div:nth-child(1) input').type(
+ value
+ );
});
Cypress.Commands.add('validateContent', (selector, expectedValue) => {
cy.get(selector).should('have.text', expectedValue);
diff --git a/test/vitest/__tests__/composables/useAcl.spec.js b/test/vitest/__tests__/composables/useAcl.spec.js
new file mode 100644
index 000000000..a2b44b5e7
--- /dev/null
+++ b/test/vitest/__tests__/composables/useAcl.spec.js
@@ -0,0 +1,88 @@
+import { vi, describe, expect, it, beforeAll, afterAll } from 'vitest';
+import { axios, flushPromises } from 'app/test/vitest/helper';
+import { useAcl } from 'src/composables/useAcl';
+
+describe('useAcl', () => {
+ const acl = useAcl();
+ const mockAcls = [
+ {
+ model: 'Address',
+ property: '*',
+ accessType: '*',
+ permission: 'ALLOW',
+ principalType: 'ROLE',
+ principalId: 'employee',
+ },
+ {
+ model: 'Worker',
+ property: 'holidays',
+ accessType: 'READ',
+ permission: 'ALLOW',
+ principalType: 'ROLE',
+ principalId: 'employee',
+ },
+ {
+ model: 'Url',
+ property: 'getByUser',
+ accessType: 'READ',
+ permission: 'ALLOW',
+ principalType: 'ROLE',
+ principalId: '$everyone',
+ },
+ {
+ model: 'TpvTransaction',
+ property: 'start',
+ accessType: 'WRITE',
+ permission: 'ALLOW',
+ principalType: 'ROLE',
+ principalId: '$authenticated',
+ },
+ ];
+
+ beforeAll(async () => {
+ vi.spyOn(axios, 'get').mockResolvedValue({ data: mockAcls });
+ await acl.fetch();
+ });
+
+ afterAll(async () => await flushPromises());
+
+ describe('hasAny', () => {
+ it('should return false if no roles matched', async () => {
+ expect(acl.hasAny('Worker', 'updateAttributes', 'WRITE')).toBeFalsy();
+ });
+
+ it('should return false if no roles matched', async () => {
+ expect(acl.hasAny('Worker', 'holidays', 'READ')).toBeTruthy();
+ });
+
+ describe('*', () => {
+ it('should return true if an acl matched', async () => {
+ expect(acl.hasAny('Address', '*', 'WRITE')).toBeTruthy();
+ });
+
+ it('should return false if no acls matched', async () => {
+ expect(acl.hasAny('Worker', '*', 'READ')).toBeFalsy();
+ });
+ });
+
+ describe('$authenticated', () => {
+ it('should return false if no acls matched', async () => {
+ expect(acl.hasAny('Url', 'getByUser', '*')).toBeFalsy();
+ });
+
+ it('should return true if an acl matched', async () => {
+ expect(acl.hasAny('Url', 'getByUser', 'READ')).toBeTruthy();
+ });
+ });
+
+ describe('$everyone', () => {
+ it('should return false if no acls matched', async () => {
+ expect(acl.hasAny('TpvTransaction', 'start', 'READ')).toBeFalsy();
+ });
+
+ it('should return false if an acl matched', async () => {
+ expect(acl.hasAny('TpvTransaction', 'start', 'WRITE')).toBeTruthy();
+ });
+ });
+ });
+});
diff --git a/test/vitest/__tests__/composables/useSession.spec.js b/test/vitest/__tests__/composables/useSession.spec.js
index 2292859a9..831acbf18 100644
--- a/test/vitest/__tests__/composables/useSession.spec.js
+++ b/test/vitest/__tests__/composables/useSession.spec.js
@@ -1,5 +1,5 @@
import { vi, describe, expect, it, beforeAll, beforeEach } from 'vitest';
-import { axios, flushPromises } from 'app/test/vitest/helper';
+import { axios } from 'app/test/vitest/helper';
import { useSession } from 'composables/useSession';
import { useState } from 'composables/useState';
@@ -87,13 +87,17 @@ describe('session', () => {
},
},
];
+ beforeEach(() => {
+ vi.spyOn(axios, 'get').mockImplementation((url) => {
+ if (url === 'VnUsers/acls') return Promise.resolve({ data: [] });
+ return Promise.resolve({
+ data: { roles: rolesData, user: expectedUser },
+ });
+ });
+ });
it('should fetch the user roles and then set token in the sessionStorage', async () => {
const expectedRoles = ['salesPerson', 'admin'];
- vi.spyOn(axios, 'get').mockResolvedValue({
- data: { roles: rolesData, user: expectedUser },
- });
-
const expectedToken = 'mySessionToken';
const expectedTokenMultimedia = 'mySessionTokenMultimedia';
const keepLogin = false;
@@ -117,10 +121,6 @@ describe('session', () => {
it('should fetch the user roles and then set token in the localStorage', async () => {
const expectedRoles = ['salesPerson', 'admin'];
- vi.spyOn(axios, 'get').mockResolvedValue({
- data: { roles: rolesData, user: expectedUser },
- });
-
const expectedToken = 'myLocalToken';
const expectedTokenMultimedia = 'myLocalTokenMultimedia';
const keepLogin = true;
diff --git a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInBasicData.spec.js b/test/vitest/__tests__/pages/InvoiceIn/InvoiceInBasicData.spec.js
deleted file mode 100644
index a3c383f74..000000000
--- a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInBasicData.spec.js
+++ /dev/null
@@ -1,34 +0,0 @@
-import { vi, describe, expect, it, beforeAll } from 'vitest';
-import { createWrapper, axios } from 'app/test/vitest/helper';
-import InvoiceInBasicData from 'src/pages/InvoiceIn/Card/InvoiceInBasicData.vue';
-
-describe('InvoiceInBasicData', () => {
- let vm;
-
- beforeAll(() => {
- vm = createWrapper(InvoiceInBasicData, {
- global: {
- stubs: [],
- mocks: {
- fetch: vi.fn(),
- },
- },
- }).vm;
- });
-
- describe('upsert()', () => {
- it('should throw an error when data is empty', async () => {
- vi.spyOn(axios, 'post').mockResolvedValue({ data: [] });
- vi.spyOn(vm.quasar, 'notify');
-
- await vm.upsert();
-
- expect(vm.quasar.notify).toHaveBeenCalledWith(
- expect.objectContaining({
- message: `The company can't be empty`,
- type: 'negative',
- })
- );
- });
- });
-});
diff --git a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInIntrastat.spec.js b/test/vitest/__tests__/pages/InvoiceIn/InvoiceInIntrastat.spec.js
index 55ca19d71..adfb054c6 100644
--- a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInIntrastat.spec.js
+++ b/test/vitest/__tests__/pages/InvoiceIn/InvoiceInIntrastat.spec.js
@@ -19,13 +19,13 @@ describe('InvoiceInIntrastat', () => {
describe('getTotal()', () => {
it('should correctly handle the sum', () => {
- vm.invoceInIntrastat = [
+ const invoceInIntrastat = [
{ amount: 10, stems: 162 },
{ amount: 20, stems: 21 },
];
- const totalAmount = vm.getTotal('amount');
- const totalStems = vm.getTotal('stems');
+ const totalAmount = vm.getTotal(invoceInIntrastat, 'amount');
+ const totalStems = vm.getTotal(invoceInIntrastat, 'stems');
expect(totalAmount).toBe(10 + 20);
expect(totalStems).toBe(162 + 21);
diff --git a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInVat.spec.js b/test/vitest/__tests__/pages/InvoiceIn/InvoiceInVat.spec.js
index 6cc082a35..76453f65a 100644
--- a/test/vitest/__tests__/pages/InvoiceIn/InvoiceInVat.spec.js
+++ b/test/vitest/__tests__/pages/InvoiceIn/InvoiceInVat.spec.js
@@ -1,5 +1,5 @@
import { vi, describe, expect, it, beforeAll } from 'vitest';
-import { createWrapper, axios } from 'app/test/vitest/helper';
+import { createWrapper } from 'app/test/vitest/helper';
import InvoiceInVat from 'src/pages/InvoiceIn/Card/InvoiceInVat.vue';
describe('InvoiceInVat', () => {
@@ -16,41 +16,6 @@ describe('InvoiceInVat', () => {
}).vm;
});
- describe('addExpense()', () => {
- beforeAll(() => {
- vi.spyOn(axios, 'post').mockResolvedValue({ data: [] });
- vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
- vi.spyOn(vm.quasar, 'notify');
- });
-
- it('should throw an error when the code property is undefined', async () => {
- await vm.addExpense();
-
- expect(vm.quasar.notify).toHaveBeenCalledWith(
- expect.objectContaining({
- message: `The code can't be empty`,
- type: 'negative',
- })
- );
- });
-
- it('should correctly handle expense addition', async () => {
- vm.newExpense = {
- code: 123,
- isWithheld: false,
- description: 'Descripción del gasto',
- };
-
- await vm.addExpense();
- expect(vm.quasar.notify).toHaveBeenCalledWith(
- expect.objectContaining({
- message: 'Data saved',
- type: 'positive',
- })
- );
- });
- });
-
describe('taxRate()', () => {
it('should correctly compute the tax rate', () => {
const invoiceInTax = { taxableBase: 100, taxTypeSageFk: 1 };
diff --git a/test/vitest/__tests__/pages/Login/Login.spec.js b/test/vitest/__tests__/pages/Login/Login.spec.js
index 6e2de9870..9b9968736 100644
--- a/test/vitest/__tests__/pages/Login/Login.spec.js
+++ b/test/vitest/__tests__/pages/Login/Login.spec.js
@@ -23,8 +23,9 @@ describe('Login', () => {
},
};
vi.spyOn(axios, 'post').mockResolvedValueOnce({ data: { token: 'token' } });
- vi.spyOn(axios, 'get').mockResolvedValue({
- data: { roles: [], user: expectedUser , multimediaToken: {id:'multimediaToken' }},
+ vi.spyOn(axios, 'get').mockImplementation((url) => {
+ if (url === 'VnUsers/acls') return Promise.resolve({ data: [] });
+ return Promise.resolve({data: { roles: [], user: expectedUser , multimediaToken: {id:'multimediaToken' }}});
});
vi.spyOn(vm.quasar, 'notify');
diff --git a/test/vitest/helper.js b/test/vitest/helper.js
index 89cc640fd..4eeea25a8 100644
--- a/test/vitest/helper.js
+++ b/test/vitest/helper.js
@@ -24,6 +24,7 @@ vi.mock('vue-router', () => ({
params: {
id: 1,
},
+ meta: { moduleName: 'mockName' },
},
},
}),
@@ -31,6 +32,7 @@ vi.mock('vue-router', () => ({
matched: [],
query: {},
params: {},
+ meta: { moduleName: 'mockName' },
}),
}));