#8582 - test: e2e monitorTicket #1391

Merged
jsegarra merged 51 commits from e2e_monitor into dev 2025-04-15 21:04:49 +00:00
21 changed files with 218 additions and 120 deletions

View File

@ -69,7 +69,7 @@ const refresh = () => window.location.reload();
'no-visible': !stateQuery.isLoading().value, 'no-visible': !stateQuery.isLoading().value,
}" }"
size="sm" size="sm"
data-cy="loading-spinner" data-cy="navBar-spinner"
/> />
<QSpace /> <QSpace />
<div id="searchbar" class="searchbar"></div> <div id="searchbar" class="searchbar"></div>

View File

@ -741,6 +741,7 @@ const rowCtrlClickFunction = computed(() => {
withFilters withFilters
" "
:column="col" :column="col"
:data-cy="`column-filter-${col.name}`"
:show-title="true" :show-title="true"
:data-key="$attrs['data-key']" :data-key="$attrs['data-key']"
v-model="params[columnName(col)]" v-model="params[columnName(col)]"

View File

@ -212,6 +212,7 @@ const getLocale = (label) => {
color="primary" color="primary"
style="position: fixed; z-index: 1; right: 0; bottom: 0" style="position: fixed; z-index: 1; right: 0; bottom: 0"
icon="search" icon="search"
data-cy="vnFilterPanel_search"
@click="search()" @click="search()"
> >
<QTooltip bottom anchor="bottom right"> <QTooltip bottom anchor="bottom right">
@ -229,6 +230,7 @@ const getLocale = (label) => {
<QItemSection top side> <QItemSection top side>
<QBtn <QBtn
@click="clearFilters" @click="clearFilters"
data-cy="clearFilters"
color="primary" color="primary"
dense dense
flat flat
@ -292,6 +294,7 @@ const getLocale = (label) => {
</QList> </QList>
</QForm> </QForm>
<QInnerLoading <QInnerLoading
data-cy="filterPanel-spinner"
:label="t('globals.pleaseWait')" :label="t('globals.pleaseWait')"
:showing="isLoading" :showing="isLoading"
color="primary" color="primary"

View File

@ -11,7 +11,7 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy data-cy="CustomerDescriptor">
<CustomerDescriptor v-if="$props.id" :id="$props.id" :summary="CustomerSummary" /> <CustomerDescriptor v-if="$props.id" :id="$props.id" :summary="CustomerSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -228,11 +228,15 @@ async function handleTicketConfig(data) {
url="TicketConfigs" url="TicketConfigs"
:filter="{ fields: ['lackAlertPrice'] }" :filter="{ fields: ['lackAlertPrice'] }"
@on-fetch="handleTicketConfig" @on-fetch="handleTicketConfig"
auto-load ></FetchData>
<QInnerLoading
:showing="isLoading"
:label="t && t('globals.pleaseWait')"
color="primary"
/> />
<VnTable <VnTable
v-if="ticketConfig" v-if="!isLoading"
auto-load auto-load
data-cy="proposalTable" data-cy="proposalTable"
ref="proposalTableRef" ref="proposalTableRef"

View File

@ -8,14 +8,14 @@ import VnRow from 'src/components/ui/VnRow.vue';
class="q-pa-md" class="q-pa-md"
:style="{ 'flex-direction': $q.screen.lt.lg ? 'column' : 'row', gap: '0px' }" :style="{ 'flex-direction': $q.screen.lt.lg ? 'column' : 'row', gap: '0px' }"
> >
<div style="flex: 0.3"> <div style="flex: 0.3" data-cy="clientsOnWebsite">
<span <span
class="q-ml-md text-body1" class="q-ml-md text-body1"
v-text="$t('salesMonitor.clientsOnWebsite')" v-text="$t('salesMonitor.clientsOnWebsite')"
/> />
<SalesClientTable /> <SalesClientTable />
</div> </div>
<div style="flex: 0.7"> <div style="flex: 0.7" data-cy="recentOrderActions">
<span <span
class="q-ml-md text-body1" class="q-ml-md text-body1"
v-text="$t('salesMonitor.recentOrderActions')" v-text="$t('salesMonitor.recentOrderActions')"

View File

@ -9,6 +9,7 @@ import { toDateFormat, toDateTimeFormat } from 'src/filters/date.js';
import { toCurrency } from 'src/filters'; import { toCurrency } from 'src/filters';
import { useVnConfirm } from 'composables/useVnConfirm'; import { useVnConfirm } from 'composables/useVnConfirm';
import axios from 'axios'; import axios from 'axios';
import VnDateBadge from 'src/components/common/VnDateBadge.vue';
import useOpenURL from 'src/composables/useOpenURL'; import useOpenURL from 'src/composables/useOpenURL';
const { t } = useI18n(); const { t } = useI18n();
@ -165,16 +166,7 @@ const openTab = (id) => useOpenURL(`#/order/${id}/summary`);
</div> </div>
</template> </template>
<template #column-dateSend="{ row }"> <template #column-dateSend="{ row }">
<QTd> <VnDateBadge :date="row.date_send" />
<QBadge
:color="getBadgeColor(row.date_send)"
text-color="black"
class="q-pa-sm"
style="font-size: 14px"
>
{{ toDateFormat(row.date_send) }}
</QBadge>
</QTd>
</template> </template>
<template #column-clientFk="{ row }"> <template #column-clientFk="{ row }">

View File

@ -9,6 +9,7 @@ import VnInput from 'src/components/common/VnInput.vue';
import VnInputNumber from 'src/components/common/VnInputNumber.vue'; import VnInputNumber from 'src/components/common/VnInputNumber.vue';
import FetchData from 'src/components/FetchData.vue'; import FetchData from 'src/components/FetchData.vue';
import { dateRange } from 'src/filters'; import { dateRange } from 'src/filters';
import VnCheckbox from 'src/components/common/VnCheckbox.vue';
defineProps({ dataKey: { type: String, required: true } }); defineProps({ dataKey: { type: String, required: true } });
const { t, te } = useI18n(); const { t, te } = useI18n();
@ -209,7 +210,7 @@ const getLocale = (label) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<QCheckbox <VnCheckbox
:label="t('params.myTeam')" :label="t('params.myTeam')"
v-model="params.myTeam" v-model="params.myTeam"
toggle-indeterminate toggle-indeterminate
@ -218,7 +219,7 @@ const getLocale = (label) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<QCheckbox <VnCheckbox
:label="t('params.problems')" :label="t('params.problems')"
v-model="params.problems" v-model="params.problems"
toggle-indeterminate toggle-indeterminate
@ -227,7 +228,7 @@ const getLocale = (label) => {
</QItem> </QItem>
<QItem> <QItem>
<QItemSection> <QItemSection>
<QCheckbox <VnCheckbox
:label="t('params.pending')" :label="t('params.pending')"
v-model="params.pending" v-model="params.pending"
toggle-indeterminate toggle-indeterminate

View File

@ -1,7 +1,6 @@
<script setup> <script setup>
import { ref, computed, onMounted } from 'vue'; import { ref, computed, onMounted } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue'; import DepartmentDescriptorProxy from 'src/pages/Worker/Department/Card/DepartmentDescriptorProxy.vue';
import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue'; import CustomerDescriptorProxy from 'src/pages/Customer/Card/CustomerDescriptorProxy.vue';
import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue'; import TicketDescriptorProxy from 'src/pages/Ticket/Card/TicketDescriptorProxy.vue';
@ -168,9 +167,11 @@ const columns = computed(() => [
component: 'select', component: 'select',
name: 'provinceFk', name: 'provinceFk',
attrs: { attrs: {
options: provinceOpts.value, url: 'Provinces',
'option-value': 'id', fields: ['id', 'name'],
'option-label': 'name', sortBy: ['name ASC'],
optionValue: 'id',
optionLabel: 'name',
dense: true, dense: true,
}, },
}, },
@ -183,9 +184,11 @@ const columns = computed(() => [
component: 'select', component: 'select',
name: 'stateFk', name: 'stateFk',
attrs: { attrs: {
options: stateOpts.value, sortBy: ['name ASC'],
'option-value': 'id', url: 'States',
'option-label': 'name', fields: ['id', 'name'],
optionValue: 'id',
optionLabel: 'name',
dense: true, dense: true,
}, },
}, },
@ -212,9 +215,12 @@ const columns = computed(() => [
component: 'select', component: 'select',
name: 'zoneFk', name: 'zoneFk',
attrs: { attrs: {
options: zoneOpts.value, url: 'Zones',
'option-value': 'id', fields: ['id', 'name'],
'option-label': 'name', sortBy: ['name ASC'],
optionValue: 'id',
optionLabel: 'name',
dense: true, dense: true,
}, },
}, },
@ -225,11 +231,12 @@ const columns = computed(() => [
align: 'left', align: 'left',
columnFilter: { columnFilter: {
component: 'select', component: 'select',
url: 'PayMethods',
attrs: { attrs: {
options: PayMethodOpts.value, url: 'PayMethods',
optionValue: 'id', fields: ['id', 'name'],
sortBy: ['id ASC'],
optionLabel: 'name', optionLabel: 'name',
optionValue: 'id',
dense: true, dense: true,
}, },
}, },
@ -254,7 +261,9 @@ const columns = computed(() => [
columnFilter: { columnFilter: {
component: 'select', component: 'select',
attrs: { attrs: {
options: DepartmentOpts.value, url: 'Departments',
fields: ['id', 'name'],
sortBy: ['id ASC'],
dense: true, dense: true,
}, },
}, },
@ -265,11 +274,12 @@ const columns = computed(() => [
align: 'left', align: 'left',
columnFilter: { columnFilter: {
component: 'select', component: 'select',
url: 'ItemPackingTypes',
attrs: { attrs: {
options: ItemPackingTypeOpts.value, url: 'ItemPackingTypes',
'option-value': 'code', fields: ['code'],
'option-label': 'code', sortBy: ['code ASC'],
optionValue: 'code',
optionCode: 'code',
dense: true, dense: true,
}, },
}, },
@ -324,60 +334,6 @@ const totalPriceColor = (ticket) => {
const openTab = (id) => useOpenURL(`#/ticket/${id}/sale`); const openTab = (id) => useOpenURL(`#/ticket/${id}/sale`);
</script> </script>
<template> <template>
<FetchData
url="Provinces"
:filter="{
fields: ['id', 'name'],
order: 'name ASC',
}"
auto-load
@on-fetch="(data) => (provinceOpts = data)"
/>
<FetchData
url="States"
:filter="{
fields: ['id', 'name'],
order: 'name ASC',
}"
auto-load
@on-fetch="(data) => (stateOpts = data)"
/>
<FetchData
url="Zones"
:filter="{
fields: ['id', 'name'],
order: 'name ASC',
}"
auto-load
@on-fetch="(data) => (zoneOpts = data)"
/>
<FetchData
url="ItemPackingTypes"
:filter="{
fields: ['code'],
order: 'code ASC',
}"
auto-load
@on-fetch="(data) => (ItemPackingTypeOpts = data)"
/>
<FetchData
url="Departments"
:filter="{
fields: ['id', 'name'],
order: 'id ASC',
}"
auto-load
@on-fetch="(data) => (DepartmentOpts = data)"
/>
<FetchData
url="PayMethods"
:filter="{
fields: ['id', 'name'],
order: 'id ASC',
}"
auto-load
@on-fetch="(data) => (PayMethodOpts = data)"
/>
<MonitorTicketSearchbar /> <MonitorTicketSearchbar />
<RightMenu> <RightMenu>
<template #right-panel> <template #right-panel>

View File

@ -10,7 +10,7 @@ const $props = defineProps({
}); });
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy data-cy="TicketDescriptor">
<TicketDescriptor v-if="$props.id" :id="$props.id" :summary="TicketSummary" /> <TicketDescriptor v-if="$props.id" :id="$props.id" :summary="TicketSummary" />
</QPopupProxy> </QPopupProxy>
</template> </template>

View File

@ -11,7 +11,7 @@ const $props = defineProps({
</script> </script>
<template> <template>
<QPopupProxy> <QPopupProxy data-cy="DepartmentDescriptor">
<DepartmentDescriptor <DepartmentDescriptor
v-if="$props.id" v-if="$props.id"
:id="$props.id" :id="$props.id"

View File

@ -53,7 +53,7 @@ describe('invoiceInCorrective', () => {
it('should show/hide the section if it is a corrective invoice', () => { it('should show/hide the section if it is a corrective invoice', () => {
cy.visit('/#/invoice-in/1/summary'); cy.visit('/#/invoice-in/1/summary');
cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('not.exist'); cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('not.exist');
cy.clicDescriptorAction(4); cy.clickDescriptorAction(4);
cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('exist'); cy.get('[data-cy="InvoiceInCorrective-menu-item"]').should('exist');
}); });
}); });

View File

@ -64,17 +64,17 @@ describe('InvoiceInDescriptor', () => {
beforeEach(() => cy.visit('/#/invoice-in/1/summary')); beforeEach(() => cy.visit('/#/invoice-in/1/summary'));
it('should navigate to the supplier summary', () => { it('should navigate to the supplier summary', () => {
cy.clicDescriptorAction(1); cy.clickDescriptorAction(1);
cy.url().should('to.match', /supplier\/\d+\/summary/); cy.url().should('to.match', /supplier\/\d+\/summary/);
}); });
it('should navigate to the entry summary', () => { it('should navigate to the entry summary', () => {
cy.clicDescriptorAction(2); cy.clickDescriptorAction(2);
cy.url().should('to.match', /entry\/\d+\/summary/); cy.url().should('to.match', /entry\/\d+\/summary/);
}); });
it('should navigate to the invoiceIn list', () => { it('should navigate to the invoiceIn list', () => {
cy.clicDescriptorAction(3); cy.clickDescriptorAction(3);
cy.url().should('to.match', /invoice-in\/list\?table=\{.*supplierFk.+\}/); cy.url().should('to.match', /invoice-in\/list\?table=\{.*supplierFk.+\}/);
}); });
}); });
@ -93,7 +93,7 @@ describe('InvoiceInDescriptor', () => {
createCorrective(); createCorrective();
redirect(originalId); redirect(originalId);
cy.clicDescriptorAction(4); cy.clickDescriptorAction(4);
cy.validateVnTableRows({ cy.validateVnTableRows({
cols: [ cols: [
{ {
@ -141,7 +141,7 @@ function createCorrective() {
function redirect(subtitle) { function redirect(subtitle) {
const regex = new RegExp(`InvoiceIns/${subtitle}\\?filter=.*`); const regex = new RegExp(`InvoiceIns/${subtitle}\\?filter=.*`);
cy.intercept('GET', regex).as('getOriginal'); cy.intercept('GET', regex).as('getOriginal');
cy.clicDescriptorAction(4); cy.clickDescriptorAction(4);
cy.wait('@getOriginal'); cy.wait('@getOriginal');
cy.validateDescriptor({ subtitle }); cy.validateDescriptor({ subtitle });
} }

View File

@ -0,0 +1,47 @@
/// <reference types="cypress" />
describe('Monitor Clients actions', () => {
beforeEach(() => {
cy.login('salesPerson');
cy.intercept('GET', '**/Departments**').as('departments');
cy.visit('/#/monitor/clients-actions');
cy.waitForElement('.q-page');
cy.wait('@departments').then((xhr) => {
cy.window().then((win) => {
const user = JSON.parse(win.sessionStorage.getItem('user'));
const { where } = JSON.parse(xhr.request.query.filter);
expect(where.id.like).to.include(user.departmentFk.toString());
});
});
cy.intercept('GET', '**/SalesMonitors/ordersFilter*').as('ordersFilter');
cy.intercept('GET', '**/SalesMonitors/clientsFilter*').as('clientsFilter');
});
it('Should filter by field', () => {
cy.get('.q-page').should('be.visible');
cy.dataCy('clientsOnWebsite')
.find('[data-cy="column-filter-departmentFk"] [data-cy="_select"]')
.click();
cy.dataCy('recentOrderActions').within(() => {
cy.getRowCol('clientFk').find('span').should('have.class', 'link').click();
});
cy.checkVisibleDescriptor('Customer');
cy.dataCy('recentOrderActions').within(() => {
cy.getRowCol('departmentFk', 2)
.find('span')
.should('have.class', 'link')
.click();
});
cy.checkVisibleDescriptor('Department');
cy.dataCy('clientsOnWebsite')
Review

Estos dos tests que comprueban el título no le veo sentido.

Estos dos tests que comprueban el título no le veo sentido.
Review

Validan que las tablas tiene titulo de cabecera.
Me pareció interesante y es una validación que no ralentiza los tests.
Es cierto que no lo validamos pero creo que no hay mas casos como este.
Por darle más valor al test

Validan que las tablas tiene titulo de cabecera. Me pareció interesante y es una validación que no ralentiza los tests. Es cierto que no lo validamos pero creo que no hay mas casos como este. Por darle más valor al test
.find('.q-ml-md')
.should('have.text', 'Clients on website');
cy.dataCy('recentOrderActions')
.find('.q-ml-md')
.should('have.text', 'Recent order actions');
cy.dataCy('From_inputDate').should('have.value', '01/01/2001');
cy.dataCy('To_inputDate').should('have.value', '01/01/2001');
});
});

View File

@ -0,0 +1,69 @@
/// <reference types="cypress" />
describe('Monitor Tickets Table', () => {
beforeEach(() => {
cy.viewport(1920, 1080);
cy.login('salesPerson');
cy.visit('/#/monitor/tickets');
cy.waitForElement('.q-page');
cy.intercept('GET', '**/SalesMonitors/salesFilter*').as('filterRequest');
cy.openRightMenu();
});
it('should open new tab when ctrl+click on client link', () => {
cy.intercept('GET', '**/SalesMonitors/salesFilter*').as('filterRequest');
cy.window().then((win) => {
cy.stub(win, 'open').as('windowOpen');
});
cy.getRowCol('provinceFk').click({ ctrlKey: true });
cy.get('@windowOpen').should('be.calledWithMatch', /\/ticket\/\d+\/sale/);
});
it('should open the descriptorProxy and SummaryPopup', () => {
cy.getRowCol('totalProblems');
cy.getRowCol('id').find('span').should('have.class', 'link').click();
cy.checkVisibleDescriptor('Ticket');
cy.getRowCol('zoneFk').find('span').should('have.class', 'link').click();
cy.checkVisibleDescriptor('Zone');
cy.getRowCol('clientFk').find('span').should('have.class', 'link').click();
cy.checkVisibleDescriptor('Customer');
cy.getRowCol('departmentFk').find('span').should('have.class', 'link').click();
cy.checkVisibleDescriptor('Department');
cy.getRowCol('shippedDate').find('.q-badge');
cy.tableActions().click({ ctrlKey: true });
cy.tableActions(1).click();
cy.get('.summaryHeader').should('exist');
});
it('clear scopeDays', () => {
cy.get('[data-cy="Days onward_input"]').clear().type('2');
cy.searchInFilterPanel();
cy.get('.q-chip__content > span').should('have.text', '"2"');
cy.waitSpinner();
checkScopeDays(2);
cy.get('[data-cy="Days onward_input"]').clear();
cy.searchInFilterPanel();
cy.get('.q-chip__content > span').should('have.text', '"0"');
cy.waitSpinner();
checkScopeDays(0);
});
});
function checkScopeDays(scopeDays) {
cy.url().then((url) => {
const urlParams = new URLSearchParams(url.split('?')[1]);
const saleMonitorTickets = JSON.parse(
decodeURIComponent(urlParams.get('saleMonitorTickets')),
);
expect(saleMonitorTickets.scopeDays).to.equal(scopeDays);
const fromDate = new Date(saleMonitorTickets.from);
const toDate = new Date(saleMonitorTickets.to);
expect(toDate.getDate() - fromDate.getDate()).to.equal(
saleMonitorTickets.scopeDays,
);
});
}

View File

@ -2,7 +2,7 @@
describe('OrderCatalog', () => { describe('OrderCatalog', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.viewport(1920, 720); cy.viewport(1920, 1080);
cy.visit('/#/order/8/catalog'); cy.visit('/#/order/8/catalog');
}); });

View File

@ -6,9 +6,7 @@ describe('ParkingBasicData', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.visit(`/#/shelving/parking/1/basic-data`); cy.visit(`/#/shelving/parking/1/basic-data`);
cy.get('[data-cy="loading-spinner"]', { timeout: 10000 }).should( cy.get('[data-cy="navBar-spinner"]', { timeout: 10000 }).should('not.be.visible');
'not.be.visible',
);
}); });
it('should give an error if the code aldready exists', () => { it('should give an error if the code aldready exists', () => {

View File

@ -0,0 +1,6 @@
Cypress.Commands.add('checkVisibleDescriptor', (alias) =>
cy
.get(`[data-cy="${alias}Descriptor"] [data-cy="vnDescriptor"] > .header`)
jorgep marked this conversation as resolved
Review

[data-cy="${alias}Descriptor"] [data-cy="vnDescriptor"] no vale así?

[data-cy="${alias}Descriptor"] [data-cy="vnDescriptor"] no vale así?
Review

Si y no.
Poniendo .header valido que se está renderizando , porque quitándolo, se puede dar el caso que exista en el DOM pero no se visualice

Si y no. Poniendo .header valido que se está renderizando , porque quitándolo, se puede dar el caso que exista en el DOM pero no se visualice
.should('exist')
.and('be.visible'),
);

View File

@ -2,9 +2,7 @@ Cypress.Commands.add('getRow', (index = 1) =>
cy.get(`.vnTable .q-virtual-scroll__content tr:nth-child(${index})`), cy.get(`.vnTable .q-virtual-scroll__content tr:nth-child(${index})`),
); );
Cypress.Commands.add('getRowCol', (field, index = 1) => Cypress.Commands.add('getRowCol', (field, index = 1) =>
cy.get( cy.getRow(index).find(`[data-col-field="${field}"]`),
`.vnTable .q-virtual-scroll__content > :nth-child(${index}) > [data-col-field="${field}"]`,
),
); );
Cypress.Commands.add('vnTableCreateBtn', () => Cypress.Commands.add('vnTableCreateBtn', () =>
@ -14,3 +12,9 @@ Cypress.Commands.add('vnTableCreateBtn', () =>
Cypress.Commands.add('waitTableScrollLoad', () => Cypress.Commands.add('waitTableScrollLoad', () =>
cy.waitForElement('[data-q-vs-anchor]'), cy.waitForElement('[data-q-vs-anchor]'),
); );
Cypress.Commands.add('tableActions', (n = 0, child = 1) =>
cy.get(
`:nth-child(${child}) > .q-table--col-auto-width > [data-cy="tableAction-${n}"] > .q-btn__content > .q-icon`,
),
);

View File

@ -78,20 +78,21 @@ Cypress.Commands.add('waitForElement', (element) => {
Cypress.Commands.add('getValue', (selector) => { Cypress.Commands.add('getValue', (selector) => {
cy.get(selector).then(($el) => { cy.get(selector).then(($el) => {
if ($el.find('.q-checkbox__inner').length > 0) { if ($el.find('.q-checkbox__inner').length > 0) {
return cy.get(selector + '.q-checkbox__inner'); return cy.get(`${selector}.q-checkbox__inner`);
} }
// Si es un QSelect // Si es un QSelect
if ($el.find('.q-select__dropdown-icon').length) { if ($el.find('.q-select__dropdown-icon').length) {
return cy return cy
.get( .get(
selector + `${
'> .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > input', selector
}> .q-field > .q-field__inner > .q-field__control > .q-field__control-container > .q-field__native > input`,
) )
.invoke('val'); .invoke('val');
} }
// Si es un QSelect // Si es un QSelect
if ($el.find('span').length) { if ($el.find('span').length) {
return cy.get(selector + ' span').then(($span) => { return cy.get(`${selector} span`).then(($span) => {
return $span[0].innerText; return $span[0].innerText;
}); });
} }
@ -100,10 +101,15 @@ Cypress.Commands.add('getValue', (selector) => {
}); });
}); });
Cypress.Commands.add('waitSpinner', () => { Cypress.Commands.add('waitSpinner', (_spinner = 'navBar') => {
const spinners = {
navBar: '[data-cy="navBar-spinner"]',
filterPanel: '[data-cy="filterPanel-spinner"]',
};
const spinner = spinners[_spinner];
cy.get('body').then(($body) => { cy.get('body').then(($body) => {
if ($body.find('[data-cy="loading-spinner"]').length) { if ($body.find(spinner).length) {
cy.get('[data-cy="loading-spinner"]').should('not.be.visible'); cy.get(spinner).should('not.be.visible');
} }
}); });
}); });
@ -142,7 +148,7 @@ function selectItem(selector, option, ariaControl, hasWrite = true) {
function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) { function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) {
// Se intenta obtener la lista de opciones del desplegable de manera recursiva // Se intenta obtener la lista de opciones del desplegable de manera recursiva
return cy return cy
.get('#' + ariaControl, { timeout }) .get(`#${ariaControl}`, { timeout })
.should('exist') .should('exist')
.find('.q-item') .find('.q-item')
.should('exist') .should('exist')
@ -352,11 +358,21 @@ Cypress.Commands.add('openListSummary', (row) => {
cy.get('.card-list-body .actions .q-btn:nth-child(2)').eq(row).click(); cy.get('.card-list-body .actions .q-btn:nth-child(2)').eq(row).click();
}); });
Cypress.Commands.add('openRightMenu', (element) => { Cypress.Commands.add('openRightMenu', (element = 'toggle-right-drawer') => {
if (element) cy.waitForElement(element); if (element) cy.waitForElement(`[data-cy="${element}"]`);
cy.get('[data-cy="toggle-right-drawer"]').click(); cy.dataCy(element).click();
}); });
Cypress.Commands.add('cleanFilterPanel', (element = 'clearFilters') => {
cy.get('#filterPanelForm').scrollIntoView();
if (element) cy.waitForElement(`[data-cy="${element}"]`);
cy.dataCy(element).click();
});
Cypress.Commands.add('searchInFilterPanel', (element = 'vnFilterPanel_search') => {
if (element) cy.waitForElement(`[data-cy="${element}"]`);
cy.dataCy(element).click();
});
Cypress.Commands.add('openLeftMenu', (element) => { Cypress.Commands.add('openLeftMenu', (element) => {
if (element) cy.waitForElement(element); if (element) cy.waitForElement(element);
cy.get('.q-toolbar > .q-btn--round.q-btn--dense > .q-btn__content > .q-icon').click(); cy.get('.q-toolbar > .q-btn--round.q-btn--dense > .q-btn__content > .q-icon').click();
@ -454,9 +470,9 @@ Cypress.Commands.add('clickButtonWith', (type, value) => {
Cypress.Commands.add('clickButtonWithIcon', (iconClass) => { Cypress.Commands.add('clickButtonWithIcon', (iconClass) => {
cy.waitForElement('[data-cy="descriptor_actions"]'); cy.waitForElement('[data-cy="descriptor_actions"]');
cy.get('[data-cy="loading-spinner"]', { timeout: 10000 }).should('not.be.visible'); cy.waitSpinner();
cy.get('.q-btn') cy.get('.q-btn')
.filter((index, el) => Cypress.$(el).find('.q-icon.' + iconClass).length > 0) .filter((index, el) => Cypress.$(el).find(`.q-icon.${iconClass}`).length > 0)
.then(($btn) => { .then(($btn) => {
cy.wrap($btn).click(); cy.wrap($btn).click();
}); });
@ -591,7 +607,7 @@ Cypress.Commands.add('validatePdfDownload', (match, trigger) => {
}); });
}); });
Cypress.Commands.add('clicDescriptorAction', (index = 1) => { Cypress.Commands.add('clickDescriptorAction', (index = 1) => {
cy.get(`[data-cy="descriptor_actions"] .q-btn:nth-of-type(${index})`).click(); cy.get(`[data-cy="descriptor_actions"] .q-btn:nth-of-type(${index})`).click();
}); });

View File

@ -68,6 +68,7 @@ const waitForApiReady = (url, maxRetries = 20, delay = 1000) => {
}; };
before(() => { before(() => {
cy.viewport(1920, 1080);
waitForApiReady('/api/Applications/status'); waitForApiReady('/api/Applications/status');
}); });