diff --git a/src/components/CrudModel.vue b/src/components/CrudModel.vue
index 0de5d3aa2..5eba97dc8 100644
--- a/src/components/CrudModel.vue
+++ b/src/components/CrudModel.vue
@@ -394,6 +394,7 @@ watch(formUrl, async () => {
@click="onSubmit"
:disable="!hasChanges"
:title="t('globals.save')"
+ data-cy="crudModelDefaultSaveBtn"
/>
diff --git a/src/components/VnTable/VnTable.vue b/src/components/VnTable/VnTable.vue
index 4fa9268d4..ea7cf1dda 100644
--- a/src/components/VnTable/VnTable.vue
+++ b/src/components/VnTable/VnTable.vue
@@ -737,6 +737,7 @@ function handleSelection({ evt, added, rows: selectedRows }, rows) {
fab
icon="add"
shortcut="+"
+ data-cy="vnTableCreateBtn"
/>
{{ createForm?.title }}
diff --git a/src/components/common/VnSmsDialog.vue b/src/components/common/VnSmsDialog.vue
index 064394445..8851a33b2 100644
--- a/src/components/common/VnSmsDialog.vue
+++ b/src/components/common/VnSmsDialog.vue
@@ -86,7 +86,7 @@ async function send() {
-
+
@@ -161,6 +161,7 @@ async function send() {
:loading="isLoading"
color="primary"
unelevated
+ data-cy="sendSmsBtn"
/>
diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index da2d370fe..ccf87c6d6 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -130,6 +130,7 @@ async function search() {
dense
standout
autofocus
+ data-cy="vnSearchBar"
>
-
+
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index f8ffb43ed..4e77b633f 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -130,6 +130,7 @@ function ticketFilter(ticket) {
{{ entity.ticketState.state.name }}
@@ -174,7 +175,7 @@ function ticketFilter(ticket) {
{{ t('Client Frozen') }}
{
dense
style="width: 50%"
@click="save()"
+ data-cy="saveManaBtn"
>
{{ t('globals.save') }}
diff --git a/src/pages/Ticket/Card/TicketNotes.vue b/src/pages/Ticket/Card/TicketNotes.vue
index 12f7ba2c6..55a6188d9 100644
--- a/src/pages/Ticket/Card/TicketNotes.vue
+++ b/src/pages/Ticket/Card/TicketNotes.vue
@@ -86,12 +86,14 @@ async function handleSave() {
option-value="id"
v-model="row.observationTypeFk"
:disable="!!row.id"
+ data-cy="ticketNotesObservationType"
/>
{{ t('ticketNotes.removeNote') }}
@@ -113,6 +116,7 @@ async function handleSave() {
class="fill-icon-on-hover q-ml-md"
color="primary"
@click="ticketNotesCrudRef.insert()"
+ data-cy="ticketNotesAddNoteBtn"
>
{{ t('ticketNotes.addNote') }}
diff --git a/src/pages/Ticket/Card/TicketSale.vue b/src/pages/Ticket/Card/TicketSale.vue
index 1575762ce..55ffffbb0 100644
--- a/src/pages/Ticket/Card/TicketSale.vue
+++ b/src/pages/Ticket/Card/TicketSale.vue
@@ -584,6 +584,7 @@ watch(
color="primary"
:disable="!isTicketEditable || ticketState === 'OK'"
@click="changeTicketState('OK')"
+ data-cy="ticketSaleOkStateBtn"
>
{{ t(`Change ticket state to 'Ok'`) }}
@@ -592,6 +593,7 @@ watch(
color="primary"
:label="t('ticketList.state')"
:disable="!isTicketEditable"
+ data-cy="ticketSaleStateDropdown"
>
{{ t('Transfer lines') }}
-
+
{{ t('ticketSale.reserved') }}
@@ -865,7 +875,14 @@ watch(
-
+
{{ t('Add item to basket') }}
diff --git a/src/pages/Ticket/Card/TicketSaleMoreActions.vue b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
index 16b84ab5e..2a8e0237f 100644
--- a/src/pages/Ticket/Card/TicketSaleMoreActions.vue
+++ b/src/pages/Ticket/Card/TicketSaleMoreActions.vue
@@ -179,6 +179,7 @@ const createRefund = async (withWarehouse) => {
color="primary"
:label="t('ticketSale.more')"
:disable="disable"
+ data-cy="ticketSaleMoreActionsDropdown"
>
{{ t('Select lines to see the options') }}
@@ -190,6 +191,7 @@ const createRefund = async (withWarehouse) => {
v-close-popup
v-ripple
@click="showSmsDialog('productNotAvailable')"
+ data-cy="sendShortageSMSItem"
>
{{ t('Send shortage SMS') }}
@@ -201,12 +203,18 @@ const createRefund = async (withWarehouse) => {
v-close-popup
v-ripple
@click="calculateSalePrice()"
+ data-cy="recalculatePriceItem"
>
{{ t('Recalculate price') }}
-
+
{{ t('Update discount') }}
@@ -215,6 +223,7 @@ const createRefund = async (withWarehouse) => {
v-model.number="newDiscount"
:label="t('ticketSale.discount')"
type="number"
+ data-cy="ticketSaleDiscountInput"
/>
@@ -224,6 +233,7 @@ const createRefund = async (withWarehouse) => {
v-close-popup
v-ripple
@click="createClaim()"
+ data-cy="createClaimItem"
>
{{ t('Add claim') }}
@@ -235,6 +245,7 @@ const createRefund = async (withWarehouse) => {
v-close-popup
v-ripple
@click="setReserved(true)"
+ data-cy="markAsReservedItem"
>
{{ t('Mark as reserved') }}
@@ -246,12 +257,13 @@ const createRefund = async (withWarehouse) => {
v-close-popup
v-ripple
@click="setReserved(false)"
+ data-cy="unmarkAsReservedItem"
>
{{ t('Unmark as reserved') }}
-
+
{{ t('Refund') }}
@@ -260,12 +272,22 @@ const createRefund = async (withWarehouse) => {
-
+
{{ t('with warehouse') }}
-
+
{{ t('without warehouse') }}
diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue
index b55043b17..650e28e8f 100644
--- a/src/pages/Ticket/Card/TicketSummary.vue
+++ b/src/pages/Ticket/Card/TicketSummary.vue
@@ -100,6 +100,7 @@ function toTicketUrl(section) {
ref="summaryRef"
:url="`Tickets/${entityId}/summary`"
data-key="TicketSummary"
+ data-cy="ticketSummary"
>
(_transfer.value = $props.transfer));
-
+
@@ -72,6 +74,7 @@ defineExpose({ transferSales });
color="primary"
class="full-width q-my-lg"
@click="transferSales()"
+ data-cy="ticketTransferNewTicketBtn"
/>
diff --git a/src/pages/Ticket/TicketList.vue b/src/pages/Ticket/TicketList.vue
index 7e95f3a1d..b25b1765a 100644
--- a/src/pages/Ticket/TicketList.vue
+++ b/src/pages/Ticket/TicketList.vue
@@ -462,6 +462,7 @@ function setReference(data) {
data-key="TicketList"
:label="t('Search ticket')"
:info="t('You can search by ticket id or alias')"
+ data-cy="ticketListSearchBar"
/>
@@ -489,6 +490,7 @@ function setReference(data) {
'row-key': 'id',
selection: 'multiple',
}"
+ data-cy="ticketListTable"
>
diff --git a/test/cypress/integration/ticket/ticketList.spec.js b/test/cypress/integration/ticket/ticketList.spec.js
new file mode 100644
index 000000000..bbdbcea92
--- /dev/null
+++ b/test/cypress/integration/ticket/ticketList.spec.js
@@ -0,0 +1,54 @@
+///
+describe('TicketList', () => {
+ const firstRow = 'tbody > :nth-child(1)';
+
+ beforeEach(() => {
+ cy.login('developer');
+ cy.viewport(1920, 1080);
+ cy.visit('/#/ticket/list');
+ });
+
+ const searchResults = (search) => {
+ cy.dataCy('vnSearchBar').find('input').focus();
+ if (search) cy.dataCy('vnSearchBar').find('input').type(search);
+ cy.dataCy('vnSearchBar').find('input').type('{enter}');
+ cy.dataCy('ticketListTable').should('exist');
+ cy.get(firstRow).should('exist');
+ };
+
+ it('should search results', () => {
+ cy.dataCy('ticketListTable').should('not.exist');
+ cy.get('.q-field__control').should('exist');
+ searchResults();
+ });
+
+ it('should open ticket sales', () => {
+ searchResults();
+ cy.window().then((win) => {
+ cy.stub(win, 'open').as('windowOpen');
+ });
+ cy.get(firstRow).find('.q-btn:first').click();
+ cy.get('@windowOpen').should('be.calledWithMatch', /\/ticket\/\d+\/sale/);
+ });
+
+ it('should open ticket summary', () => {
+ searchResults();
+ cy.get(firstRow).find('.q-btn:last').click();
+ cy.dataCy('ticketSummary').should('exist');
+ });
+
+ it('Client list create new client', () => {
+ cy.dataCy('vnTableCreateBtn').should('exist');
+ cy.dataCy('vnTableCreateBtn').click();
+ const data = {
+ Customer: { val: 1, type: 'select' },
+ Warehouse: { val: 'Warehouse One', type: 'select' },
+ Address: { val: 'employee', type: 'select' },
+ Landed: { val: '01-01-2024', type: 'date' },
+ };
+ cy.fillInForm(data);
+ cy.get('.q-mt-lg > .q-btn--standard').click();
+ cy.checkNotification('Data created');
+ cy.url().should('match', /\/ticket\/\d+\/summary/);
+ });
+});
diff --git a/test/cypress/integration/ticket/ticketNotes.spec.js b/test/cypress/integration/ticket/ticketNotes.spec.js
new file mode 100644
index 000000000..ef196c783
--- /dev/null
+++ b/test/cypress/integration/ticket/ticketNotes.spec.js
@@ -0,0 +1,25 @@
+///
+describe('TicketRequest', () => {
+ beforeEach(() => {
+ cy.login('developer');
+ cy.viewport(1920, 1080);
+ cy.visit('/#/ticket/31/observation');
+ });
+
+ it('Creates and deletes a note', () => {
+ cy.dataCy('ticketNotesAddNoteBtn').should('exist');
+ cy.dataCy('ticketNotesAddNoteBtn').click();
+ cy.dataCy('ticketNotesObservationType').should('exist');
+ cy.selectOption('[data-cy="ticketNotesObservationType"]:last', 'Weight');
+ cy.dataCy('ticketNotesDescription').should('exist');
+ cy.get('[data-cy="ticketNotesDescription"]:last').type(
+ 'This is a note description'
+ );
+ cy.dataCy('crudModelDefaultSaveBtn').click();
+ cy.checkNotification('Data saved');
+ cy.dataCy('ticketNotesRemoveNoteBtn').should('exist');
+ cy.dataCy('ticketNotesRemoveNoteBtn').click();
+ cy.dataCy('VnConfirm_confirm').click();
+ cy.checkNotification('Data saved');
+ });
+});
diff --git a/test/cypress/integration/ticket/ticketRequest.spec.js b/test/cypress/integration/ticket/ticketRequest.spec.js
new file mode 100644
index 000000000..b9dc509ef
--- /dev/null
+++ b/test/cypress/integration/ticket/ticketRequest.spec.js
@@ -0,0 +1,22 @@
+///
+describe('TicketRequest', () => {
+ beforeEach(() => {
+ cy.login('developer');
+ cy.viewport(1920, 1080);
+ cy.visit('/#/ticket/31/request');
+ });
+
+ it('Creates a new request', () => {
+ cy.dataCy('vnTableCreateBtn').should('exist');
+ cy.dataCy('vnTableCreateBtn').click();
+ const data = {
+ Description: { val: 'Purchase description' },
+ Atender: { val: 'buyerNick', type: 'select' },
+ Quantity: { val: 2 },
+ Price: { val: 123 },
+ };
+ cy.fillInForm(data);
+ cy.get('.q-mt-lg > .q-btn--standard').click();
+ cy.checkNotification('Data created');
+ });
+});
diff --git a/test/cypress/integration/ticket/ticketSale.spec.js b/test/cypress/integration/ticket/ticketSale.spec.js
new file mode 100644
index 000000000..60f31dbf6
--- /dev/null
+++ b/test/cypress/integration/ticket/ticketSale.spec.js
@@ -0,0 +1,131 @@
+///
+
+const c = require('croppie');
+
+describe('TicketSale', () => {
+ beforeEach(() => {
+ cy.login('developer');
+ cy.viewport(1920, 1080);
+ cy.visit('/#/ticket/31/sale');
+ });
+
+ const firstRow = 'tbody > :nth-child(1)';
+
+ const selectFirstRow = () => {
+ cy.waitForElement(firstRow);
+ cy.get(firstRow).find('.q-checkbox__inner').click();
+ };
+
+ it('it should add item to basket', () => {
+ cy.window().then((win) => {
+ cy.stub(win, 'open').as('windowOpen');
+ });
+ cy.dataCy('ticketSaleAddToBasketBtn').should('exist');
+ cy.dataCy('ticketSaleAddToBasketBtn').click();
+ cy.get('@windowOpen').should('be.calledWithMatch', /\/order\/\d+\/catalog/);
+ });
+
+ it('should send SMS', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.waitForElement('[data-cy="sendShortageSMSItem"]');
+ cy.dataCy('sendShortageSMSItem').should('exist');
+ cy.dataCy('sendShortageSMSItem').click();
+ cy.dataCy('vnSmsDialog').should('exist');
+ cy.dataCy('sendSmsBtn').click();
+ cy.checkNotification('SMS sent');
+ });
+
+ it('should recalculate price when "Recalculate price" is clicked', () => {
+ cy.intercept('POST', '**/recalculatePrice').as('recalculatePrice');
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.waitForElement('[data-cy="recalculatePriceItem"]');
+ cy.dataCy('recalculatePriceItem').should('exist');
+ cy.dataCy('recalculatePriceItem').click();
+ cy.wait('@recalculatePrice').its('response.statusCode').should('eq', 200);
+ cy.checkNotification('Data saved');
+ });
+
+ it('should update discount when "Update discount" is clicked', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.waitForElement('[data-cy="updateDiscountItem"]');
+ cy.dataCy('updateDiscountItem').should('exist');
+ cy.dataCy('updateDiscountItem').click();
+ cy.waitForElement('[data-cy="ticketSaleDiscountInput"]');
+ cy.dataCy('ticketSaleDiscountInput').find('input').focus();
+ cy.dataCy('ticketSaleDiscountInput').find('input').type('10');
+ cy.dataCy('saveManaBtn').click();
+ cy.waitForElement('.q-notification__message');
+ cy.checkNotification('Data saved');
+ });
+
+ it('adds claim', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.dataCy('createClaimItem').click();
+ cy.dataCy('VnConfirm_confirm').click();
+ cy.url().should('match', /\/claim\/\d+\/basic-data/);
+ // Delete created claim to avoid cluttering the database
+ cy.dataCy('descriptor-more-opts').click();
+ cy.dataCy('deleteClaim').click();
+ cy.dataCy('VnConfirm_confirm').click();
+ cy.checkNotification('Data deleted');
+ });
+
+ it('marks row as reserved', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.waitForElement('[data-cy="markAsReservedItem"]');
+ cy.dataCy('markAsReservedItem').click();
+ cy.dataCy('ticketSaleReservedIcon').should('exist');
+ });
+
+ it('unmarks row as reserved', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.waitForElement('[data-cy="unmarkAsReservedItem"]');
+ cy.dataCy('unmarkAsReservedItem').click();
+ cy.dataCy('ticketSaleReservedIcon').should('not.exist');
+ });
+
+ it('refunds row with warehouse', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.dataCy('ticketSaleRefundItem').click();
+ cy.dataCy('ticketSaleRefundWithWarehouse').click();
+ cy.checkNotification('The following refund ticket have been created');
+ });
+
+ it('refunds row without warehouse', () => {
+ selectFirstRow();
+ cy.dataCy('ticketSaleMoreActionsDropdown').click();
+ cy.dataCy('ticketSaleRefundItem').click();
+ cy.dataCy('ticketSaleRefundWithoutWarehouse').click();
+ cy.checkNotification('The following refund ticket have been created');
+ });
+
+ it('transfers ticket', () => {
+ cy.visit('/#/ticket/32/sale');
+ selectFirstRow();
+ cy.dataCy('ticketSaleTransferBtn').click();
+ cy.dataCy('ticketTransferPopup').should('exist');
+ cy.dataCy('ticketTransferNewTicketBtn').click();
+ // existen 3 elementos "tbody" necesito checkear que el segundo elemento tbody tenga una row sola
+ cy.get('tbody').eq(1).find('tr').should('have.length', 1);
+ selectFirstRow();
+ cy.dataCy('ticketSaleTransferBtn').click();
+ cy.dataCy('ticketTransferPopup').should('exist');
+ cy.dataCy('ticketTransferDestinationTicketInput').find('input').focus();
+ cy.dataCy('ticketTransferDestinationTicketInput').find('input').type('32');
+ cy.dataCy('ticketTransferTransferBtn').click();
+ // checkear que la url contenga /ticket/1000002/sale
+ cy.url().should('match', /\/ticket\/32\/sale/);
+ });
+
+ it('should redirect to ticket logs', () => {
+ cy.get(firstRow).find('.q-btn:last').click();
+ cy.url().should('match', /\/ticket\/31\/log/);
+ });
+});
diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js
index afe3561a0..b8c1d3988 100755
--- a/test/cypress/support/commands.js
+++ b/test/cypress/support/commands.js
@@ -310,3 +310,7 @@ Cypress.Commands.add('checkValueSelectForm', (id, search) => {
Cypress.Commands.add('searchByLabel', (label, value) => {
cy.get(`[label="${label}"] > .q-field > .q-field__inner`).type(`${value}{enter}`);
});
+
+Cypress.Commands.add('dataCy', (dataTestId, attr = 'data-cy') => {
+ return cy.get(`[${attr}="${dataTestId}"]`);
+});