WIP: #7220 - Component Unit Cypress Test #296

Draft
jsegarra wants to merge 33 commits from 7220_cypressUnitTest into dev
94 changed files with 3132 additions and 162 deletions
Showing only changes of commit fc50023a0b - Show all commits

View File

@ -1,7 +1,7 @@
const { defineConfig } = require('cypress');
const {
injectQuasarDevServerConfig,
} = require('@quasar/quasar-app-extension-testing-e2e-cypress/cct-dev-server');
// const {
// injectQuasarDevServerConfig,
// } = require('@quasar/quasar-app-extension-testing-e2e-cypress/cct-dev-server');
module.exports = defineConfig({
env: {

View File

@ -44,7 +44,7 @@
"@quasar/quasar-app-extension-qcalendar": "4.0.0-beta.15",
"@quasar/quasar-app-extension-testing-e2e-cypress": "^6.1.0",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0",
"@vitest/ui": "^1.6.0",
"@vitest/ui": "^2.1.4",
"@vue/test-utils": "^2.4.4",
"autoprefixer": "^10.4.14",
"cypress": "^13.6.6",
@ -55,7 +55,7 @@
"husky": "^8.0.0",
"postcss": "^8.4.23",
"prettier": "^2.8.8",
"vitest": "^0.31.1"
"vitest": "^0.31.4"
},
"engines": {
"node": "^20 || ^18 || ^16",

File diff suppressed because it is too large Load Diff

View File

@ -2,13 +2,13 @@
import { reactive, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import FetchData from 'src/components/FetchData.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnSelectProvince from 'src/components/VnSelectProvince.vue';
import VnInput from 'src/components/common/VnInput.vue';
import CreateNewCityForm from './CreateNewCityForm.vue';
import VnSelectDialog from 'components/common/VnSelectDialog.vue';
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import FormModelPopup from './FormModelPopup.vue';
const emit = defineEmits(['onDataSaved']);

View File

@ -7,6 +7,9 @@ import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
import FetchData from 'src/components/FetchData.vue';
import CreateNewProvinceForm from './CreateNewProvinceForm.vue';
const { validate } = useValidator();
const { t } = useI18n();
const emit = defineEmits(['onProvinceCreated']);
const $props = defineProps({
countryFk: {
@ -24,9 +27,6 @@ const $props = defineProps({
});
const provinceFk = defineModel({ type: Number, default: null });
const { validate } = useValidator();
const { t } = useI18n();
const provincesOptions = ref($props.provinces);
provinceFk.value = $props.provinceSelected;
const provincesFetchDataRef = ref();
@ -81,5 +81,5 @@ async function handleProvinces(data) {
<i18n lang="yml">
es:
Province: Provincia
Create province: Crear provincia
Create province: Crear provincia
</i18n>

View File

@ -2,6 +2,8 @@
import { computed, ref } from 'vue';
import { useI18n } from 'vue-i18n';
import { useValidator } from 'src/composables/useValidator';
import { useAttrs } from 'vue';
const $attrs = useAttrs();
const emit = defineEmits([
'update:modelValue',
@ -57,12 +59,6 @@ const focus = () => {
vnInputRef.value.focus();
};
defineExpose({
focus,
});
import { useAttrs } from 'vue';
const $attrs = useAttrs();
const mixinRules = [
requiredFieldRule,
...($attrs.rules ?? []),
@ -76,11 +72,39 @@ const mixinRules = [
}
},
];
defineExpose({
focus,
});
const isInsertMode = ref(false);
const handleKeydown = (event) => {
const qInputEl = vnInputRef.value.$el.querySelector('input');
const cursorPos = qInputEl.selectionStart;
if (event.key === 'Insert') {
isInsertMode.value = !isInsertMode.value;
} else if (isInsertMode.value && !isNaN(event.key) && event.key.length === 1) {
event.preventDefault();
const currentValue = value.value;
if (cursorPos !== null) {
const newValue =
currentValue.slice(0, cursorPos) +
event.key +
currentValue.slice(cursorPos + 1);
value.value = newValue;
setTimeout(() => {
qInputEl.setSelectionRange(cursorPos + 1, cursorPos + 1);
}, 0);
}
}
};
</script>
<template>
<div @mouseover="hover = true" @mouseleave="hover = false">
<QInput
@keydown="handleKeydown"
ref="vnInputRef"
v-model="value"
v-bind="{ ...$attrs, ...styleAttrs }"

View File

@ -14,7 +14,7 @@ const props = defineProps({
});
const locationProperties = [
'postcode',
'posstcode',
(obj) =>
obj.city
? `${obj.city}${obj.province?.name ? `(${obj.province.name})` : ''}`

View File

@ -51,7 +51,8 @@ const val = computed(() => $props.value);
</div>
<div class="info" v-if="info">
<QIcon name="info" class="cursor-pointer" size="xs" color="grey">
<QTooltip class="bg-dark text-white shadow-4" :offset="[10, 10]">
{{ info }}
<QTooltip class="bg-dark text-white shadow-4">
{{ info }}
</QTooltip>
</QIcon>

View File

@ -7,9 +7,9 @@ import { useRoute } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import { useArrayData } from 'composables/useArrayData';
import { toDate, toCurrency, toPercentage } from 'filters/index';
import CrudModel from 'components/CrudModel.vue';
import FetchData from 'components/FetchData.vue';
import VnDiscount from 'components/common/vnDiscount.vue';
import CrudModel from 'src/components/CrudModel.vue';
import FetchData from 'src/components/FetchData.vue';
import VnDiscount from 'src/components/common/vnDiscount.vue';
import ClaimLinesImport from './ClaimLinesImport.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';

View File

@ -85,7 +85,12 @@ function handleLocation(data, location) {
<QCheckbox :label="t('Default')" v-model="data.isDefaultAddress" />
<VnRow>
<VnInput :label="t('Consignee')" clearable v-model="data.nickname" />
<VnInput
:label="t('Consignee')"
clearable
v-model="data.nickname"
required
/>
<VnInput :label="t('Street address')" clearable v-model="data.street" />
</VnRow>

View File

@ -8,7 +8,7 @@ import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import EntryLatestBuysFilter from './EntryLatestBuysFilter.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
import VnImg from 'src/components/ui/VnImg.vue';
const stateStore = useStateStore();

View File

@ -1,6 +1,6 @@
<script setup>
import { ref, computed, watch } from 'vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import useNotify from 'src/composables/useNotify.js';
import axios from 'axios';

View File

@ -9,7 +9,7 @@ import { useArrayData } from 'src/composables/useArrayData';
import CustomerDescriptorProxy from '../Customer/Card/CustomerDescriptorProxy.vue';
import TicketDescriptorProxy from '../Ticket/Card/TicketDescriptorProxy.vue';
import WorkerDescriptorProxy from '../Worker/Card/WorkerDescriptorProxy.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
const { t } = useI18n();
const tableRef = ref();

View File

@ -14,8 +14,8 @@ import RouteSummary from 'pages/Route/Card/RouteSummary.vue';
import RightMenu from 'src/components/common/RightMenu.vue';
import RouteFilter from 'pages/Route/Card/RouteFilter.vue';
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnTable from 'components/VnTable/VnTable.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnTable from 'src/components/VnTable/VnTable.vue';
const { openReport } = usePrintService();
const { t } = useI18n();

View File

@ -104,6 +104,7 @@ function handleLocation(data, location) {
v-model="data.account"
:label="t('supplier.fiscalData.account')"
clearable
:max-length="10"
/>
<VnSelect
:label="t('supplier.fiscalData.sageTaxTypeFk')"

View File

@ -9,9 +9,9 @@ import SendEmailDialog from 'src/components/common/SendEmailDialog.vue';
import VnConfirm from 'src/components/ui/VnConfirm.vue';
import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
import toDate from 'filters/toDate';
import FormPopup from 'components/FormPopup.vue';
import VnSelect from 'components/common/VnSelect.vue';
import FetchData from 'components/FetchData.vue';
import FormPopup from 'src/components/FormPopup.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import FetchData from 'src/components/FetchData.vue';
import VnInputTime from 'src/components/common/VnInputTime.vue';
import { useAcl } from 'src/composables/useAcl';
import VnInputNumber from 'src/components/common/VnInputNumber.vue';

View File

@ -2,11 +2,11 @@
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import FetchData from 'src/components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnSelect from 'components/common/VnSelect.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import VnInputDate from 'components/common/VnInputDate.vue';
import VnInputDate from 'src/components/common/VnInputDate.vue';
import VnInputTime from 'src/components/common/VnInputTime.vue';
const { t } = useI18n();

View File

@ -2,11 +2,11 @@
import { useI18n } from 'vue-i18n';
import { useRoute } from 'vue-router';
import { ref, computed } from 'vue';
import FetchData from 'components/FetchData.vue';
import VnRow from 'components/ui/VnRow.vue';
import FetchData from 'src/components/FetchData.vue';
import VnRow from 'src/components/ui/VnRow.vue';
import VnSelect from 'src/components/common/VnSelect.vue';
import VnInput from 'src/components/common/VnInput.vue';
import CrudModel from 'components/CrudModel.vue';
import CrudModel from 'src/components/CrudModel.vue';
import axios from 'axios';
const { t } = useI18n();

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import { createTestingPinia } from '@pinia/testing';
import axios from 'axios';
import { setActivePinia } from 'pinia';

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import CreateManualInvoiceForm from 'src/components/CreateManualInvoiceForm.vue';
describe.skip('<CreateManualInvoiceForm />', () => {

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import CreateNewCityForm from 'src/components/CreateNewCityForm.vue';
describe.skip('<CreateNewCityForm />', () => {

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import CreateNewExpenseForm from 'src/components/CreateNewExpenseForm.vue';
describe.skip('<CreateNewExpenseForm />', () => {

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import CreateNewPostcodeForm from 'src/components/CreateNewPostcodeForm.vue';
describe.skip('<CreateNewPostcodeForm />', () => {

View File

@ -1,5 +1,6 @@
import CreateNewProvinceForm from 'src/components/CreateNewProvinceForm.vue';
/// <reference types="cypress" />
describe.skip('<CreateNewProvinceForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import CreateThermographForm from 'src/components/CreateThermographForm.vue';
/// <reference types="cypress" />
describe.skip('<CreateThermographForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import FormPopup from 'src/components/FormPopup.vue';
describe.skip('<FormPopup />', () => {

View File

@ -1,3 +1,4 @@
/// <reference types="cypress" />
import ItemsFilterPanel from 'src/components/ItemsFilterPanel.vue';
describe.skip('<ItemsFilterPanel />', () => {

View File

@ -1,5 +1,6 @@
import PinnedModules from 'src/components/PinnedModules.vue';
/// <reference types="cypress" />
describe.skip('<PinnedModules />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import RefundInvoiceForm from 'src/components/RefundInvoiceForm.vue';
/// <reference types="cypress" />
describe.skip('<RefundInvoiceForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import RegularizeStockForm from 'src/components/RegularizeStockForm.vue';
/// <reference types="cypress" />
describe.skip('<RegularizeStockForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import TransferInvoiceForm from 'src/components/TransferInvoiceForm.vue';
/// <reference types="cypress" />
describe.skip('<TransferInvoiceForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import UserPanel from 'src/components/UserPanel.vue';
/// <reference types="cypress" />
describe.skip('<UserPanel />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import RightMenu from 'src/components/common/RightMenu.vue';
/// <reference types="cypress" />
describe.skip('<RightMenu />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SendEmailDialog from 'src/components/common/SendEmailDialog.vue';
/// <reference types="cypress" />
describe('<SendEmailDialog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SendSmsDialog from 'src/components/common/SendSmsDialog.vue';
/// <reference types="cypress" />
describe.skip('<SendSmsDialog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import TableVisibleColumns from 'src/components/common/TableVisibleColumns.vue';
/// <reference types="cypress" />
describe.skip('<TableVisibleColumns />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnAccountNumber from 'src/components/common/VnAccountNumber.vue';
/// <reference types="cypress" />
describe.skip('<VnAccountNumber />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnBreadcrumbs from 'src/components/common/VnBreadcrumbs.vue';
/// <reference types="cypress" />
describe.skip('<VnBreadcrumbs />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnCard from 'src/components/common/VnCard.vue';
/// <reference types="cypress" />
describe.skip('<VnCard />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnComponent from 'src/components/common/VnComponent.vue';
/// <reference types="cypress" />
describe.skip('<VnComponent />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnDms from 'src/components/common/VnDms.vue';
/// <reference types="cypress" />
describe.skip('<VnDms />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnDmsList from 'src/components/common/VnDmsList.vue';
/// <reference types="cypress" />
describe.skip('<VnDmsList />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnInput from 'src/components/common/VnInput.vue';
/// <reference types="cypress" />
describe.skip('<VnInput />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnInputDate from 'src/components/common/VnInputDate.vue';
/// <reference types="cypress" />
describe.skip('<VnInputDate />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnInputNumber from 'src/components/common/VnInputNumber.vue';
/// <reference types="cypress" />
describe.skip('<VnInputNumber />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnInputTime from 'src/components/common/VnInputTime.vue';
/// <reference types="cypress" />
describe.skip('<VnInputTime />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,8 +1,55 @@
/// <reference types="cypress" />
import VnJsonValue from 'src/components/common/VnJsonValue.vue';
describe.skip('<VnJsonValue />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnJsonValue);
describe('<VnJsonValue />', () => {
const mountComponent = (value) => {
cy.createWrapper(VnJsonValue, { props: { value } });
};
it('renders null value correctly', () => {
mountComponent(null);
cy.get('span').should('have.class', 'json-null').and('contain', '∅');
});
it('renders number value correctly', () => {
mountComponent(123.456);
cy.get('span').should('have.class', 'json-number').and('contain', '123.456');
});
it('renders boolean value correctly', () => {
mountComponent(true);
cy.get('span').should('have.class', 'json-true').and('contain', '✓');
mountComponent(false);
cy.get('span').should('have.class', 'json-false').and('contain', '✗');
});
it('renders string value correctly', () => {
mountComponent('Hello, World!');
cy.get('span')
.should('have.class', 'json-string')
.and('contain', 'Hello, World!');
});
it('renders truncated string value correctly', () => {
const longString = 'a'.repeat(513);
mountComponent(longString);
cy.get('span')
.should('have.class', 'json-string')
.and('contain', 'a'.repeat(512) + '...');
});
it('renders date value correctly', () => {
const date = new Date('2023-01-01T00:00:00Z');
mountComponent(date);
cy.get('span').should('have.class', 'json-object').and('contain', '2023-01-01');
});
it('renders object value correctly', () => {
const obj = { key: 'value' };
mountComponent(obj);
cy.get('span')
.should('have.class', 'json-object')
.and('contain', '[object Object]');
});
});

View File

@ -1,17 +1,75 @@
/// <reference types="cypress" />
import VnLocation from 'src/components/common/VnLocation.vue';
describe.skip('<VnLocation />', () => {
it('renders', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnLocation, {
props: {
modelValue: 1234,
location: {
postcode: '46600',
city: ' Alz',
province: { name: 'as' },
country: { name: 'asdq' },
},
const location = {
postcode: '46000',
city: 'Valencia',
province: { name: 'Province one' },
country: { name: 'España' },
};
const defaultComponent = {
props: {
modelValue: 1234,
location,
},
};
const mountComponent = (obj = defaultComponent) => {
cy.createWrapper(VnLocation, obj);
};
it('renders with default props', () => {
mountComponent();
cy.get('.q-field__label').should('contain', 'Location');
});
it('renders with location prop', () => {
mountComponent();
cy.get('.q-field__label').should('contain', 'Location');
cy.get('.q-field__native').should(
'have.value',
'46000, Valencia(Province one), España'
);
});
it('opens select dialog on click', () => {
mountComponent();
cy.get('.q-field__native').click();
cy.get('.q-dialog').should('be.visible');
});
it('renders options correctly', () => {
const options = [
{
code: '46000',
town: 'Valencia',
province: 'Province one',
country: 'España',
},
];
mountComponent();
cy.get('.q-field__native').click();
cy.get('.q-item').should('have.length', options.length);
cy.get('.q-item').first().should('contain', '46000');
cy.get('.q-item').first().should('contain', 'Valencia(Province one)');
cy.get('.q-item').first().should('contain', 'España');
});
it('emits update:model-value on selection', () => {
mountComponent();
cy.get('.q-field__native').click();
cy.get('.q-item').first().click();
cy.wrap(Cypress.vueWrapper.emitted('update:model-value')).should(
'have.length',
1
);
});
it('renders CreateNewPostcode form', () => {
mountComponent();
cy.get('.q-field__native').click();
cy.get('.q-dialog').should('be.visible');
cy.get('.q-dialog').within(() => {
cy.get('form').should('exist');
});
});
});

View File

@ -1,8 +1,82 @@
/// <reference types="cypress" />
import VnLog from 'src/components/common/VnLog.vue';
describe.skip('<VnLog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnLog);
describe('<VnLog />', () => {
const mountComponent = (opt) => {
cy.createWrapper(VnLog, opt);
};
it('renders with default props', () => {
mountComponent({});
cy.get('.q-field__label').should('contain', 'Location');
});
it('renders with model and url props', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('.q-field__label').should('contain', 'Location');
});
it('fetches data and displays logs', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.intercept('GET', `${url}/*`, { fixture: 'logs.json' }).as('getLogs');
cy.wait('@getLogs');
cy.get('.logs').should('exist');
});
it('applies filters correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('input[aria-label="Search"]').type('test search{enter}');
cy.get('.logs').should('exist');
});
it('clears filters correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('input[aria-label="Search"]').type('test search{enter}');
cy.get('.q-btn[icon="filter_alt_off"]').click();
cy.get('input[aria-label="Search"]').should('have.value', '');
});
it('renders date filters correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('input[aria-label="Date from"]').click();
cy.get('.q-date').should('be.visible');
cy.get('input[aria-label="Date to"]').click();
cy.get('.q-date').should('be.visible');
});
it('renders user filters correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('input[aria-label="User"]').click();
cy.get('.q-menu').should('be.visible');
});
it('renders action filters correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.get('input[aria-label="Action"]').click();
cy.get('.q-menu').should('be.visible');
});
it('renders log details correctly', () => {
const model = 'testModel';
const url = 'http://example.com/api/logs';
mountComponent({ model, url });
cy.intercept('GET', `${url}/*`, { fixture: 'logs.json' }).as('getLogs');
cy.wait('@getLogs');
cy.get('.logs .model-log').first().click();
cy.get('.change-detail').should('be.visible');
});
});

View File

@ -1,5 +1,6 @@
import VnLogFilter from 'src/components/common/VnLogFilter.vue';
/// <reference types="cypress" />
describe.skip('<VnLogFilter />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnPopup from 'src/components/common/VnPopup.vue';
/// <reference types="cypress" />
describe.skip('<VnPopup />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnProgressModal from 'src/components/common/VnProgressModal.vue';
/// <reference types="cypress" />
describe.skip('<VnProgressModal />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnRadio from 'src/components/common/VnRadio.vue';
/// <reference types="cypress" />
describe.skip('<VnRadio />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSectionMain from 'src/components/common/VnSectionMain.vue';
/// <reference types="cypress" />
describe.skip('<VnSectionMain />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSelect from 'src/components/common/VnSelect.vue';
/// <reference types="cypress" />
describe.skip('<VnSelect />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSelectCache from 'src/components/common/VnSelectCache.vue';
/// <reference types="cypress" />
describe.skip('<VnSelectCache />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSelectDialog from 'src/components/common/VnSelectDialog.vue';
/// <reference types="cypress" />
describe.skip('<VnSelectDialog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSelectEnum from 'src/components/common/VnSelectEnum.vue';
/// <reference types="cypress" />
describe.skip('<VnSelectEnum />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSmsDialog from 'src/components/common/VnSmsDialog.vue';
/// <reference types="cypress" />
describe.skip('<VnSmsDialog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSummaryDialog from 'src/components/common/VnSummaryDialog.vue';
/// <reference types="cypress" />
describe.skip('<VnSummaryDialog />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,8 +1,12 @@
/// <reference types="cypress" />
import VnTitle from 'src/components/common/VnTitle.vue';
describe('<VnTitle />', () => {
const mountComponent = (opt) => {
cy.createWrapper(VnTitle, opt);
};
it('renders text with link', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
text: 'Example Link',
@ -13,7 +17,7 @@ describe('<VnTitle />', () => {
cy.get('a').should('contain.text', 'Example Link');
});
it('renders text without link', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
text: 'No Link',
},
@ -24,21 +28,21 @@ describe('<VnTitle />', () => {
});
it('applies correct classes based on url prop', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
},
});
cy.get('a').should('have.class', 'link');
cy.createWrapper(VnTitle, {
mountComponent({
props: {},
});
cy.get('a').should('have.class', 'color-vn-text');
});
it('displays icon when url is provided', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
},
@ -47,27 +51,27 @@ describe('<VnTitle />', () => {
});
it('does not display icon when url is not provided', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {},
});
cy.get('.q-icon').should('not.exist');
});
it('applies correct cursor style based on url prop', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
},
});
cy.get('.header-link').should('have.css', 'cursor', 'pointer');
cy.createWrapper(VnTitle, {
mountComponent({
props: {},
});
cy.get('.header-link').should('have.css', 'cursor', 'default');
});
it('renders default icon when no icon prop is provided', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
},
@ -76,7 +80,7 @@ describe('<VnTitle />', () => {
});
it('renders custom icon when icon prop is provided', () => {
cy.createWrapper(VnTitle, {
mountComponent({
props: {
url: 'https://example.com',
icon: 'custom_icon',

View File

@ -1,5 +1,6 @@
import VnWeekdayPicker from 'src/components/common/VnWeekdayPicker.vue';
/// <reference types="cypress" />
describe.skip('<VnWeekdayPicker />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import vnDiscount from 'src/components/common/vnDiscount.vue';
/// <reference types="cypress" />
describe.skip('<vnDiscount />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import CardDescriptor from 'src/components/ui/CardDescriptor.vue';
/// <reference types="cypress" />
describe.skip('<CardDescriptor />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import CardList from 'src/components/ui/CardList.vue';
/// <reference types="cypress" />
describe.skip('<CardList />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import CardSummary from 'src/components/ui/CardSummary.vue';
/// <reference types="cypress" />
describe.skip('<CardSummary />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import CatalogItem from 'src/components/ui/CatalogItem.vue';
/// <reference types="cypress" />
describe.skip('<CatalogItem />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,8 +1,64 @@
import FetchedTags from 'src/components/ui/FetchedTags.vue';
/// <reference types="cypress" />
import FetchedTags from 'src/components/ui/FetchedTags.vue'; // Ajusta la ruta según tu estructura de proyecto
describe.skip('<FetchedTags />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(FetchedTags);
describe('FetchedTags', () => {
const mountComponent = (opt = {}) => {
cy.createWrapper(FetchedTags, {
props: { ...opt },
});
};
it('renders with default props', () => {
const item = {
tag1: 'Tag 1',
value1: 'Value 1',
tag2: 'Tag 2',
value2: 'Value 2',
};
mountComponent({ item });
cy.get('.fetchedTags').should('exist');
cy.get('.inline-tag').should('have.length', 2);
cy.get('.inline-tag').first().should('contain', 'Value 1');
cy.get('.inline-tag').last().should('contain', 'Value 2');
});
it('renders with custom tag and value props', () => {
const item = {
customTag1: 'Custom Tag 1',
customValue1: 'Custom Value 1',
customTag2: 'Custom Tag 2',
customValue2: 'Custom Value 2',
};
mountComponent({ item, tag: 'customTag', value: 'customValue' });
cy.get('.fetchedTags').should('exist');
cy.get('.inline-tag').should('have.length', 2);
cy.get('.inline-tag').first().should('contain', 'Custom Value 1');
cy.get('.inline-tag').last().should('contain', 'Custom Value 2');
});
it('renders empty tags correctly', () => {
const item = {
tag1: 'Tag 1',
value1: '',
tag2: 'Tag 2',
value2: '',
};
mountComponent({ item });
cy.get('.fetchedTags').should('exist');
cy.get('.inline-tag').should('have.length', 2);
cy.get('.inline-tag').first().should('have.class', 'empty');
cy.get('.inline-tag').last().should('have.class', 'empty');
});
it('renders tags with missing values correctly', () => {
const item = {
tag1: 'Tag 1',
tag2: 'Tag 2',
};
mountComponent({ item });
cy.get('.fetchedTags').should('exist');
cy.get('.inline-tag').should('have.length', 2);
cy.get('.inline-tag').first().should('have.class', 'empty');
cy.get('.inline-tag').last().should('have.class', 'empty');
});
});

View File

@ -1,5 +1,6 @@
import QCalendarMonthWrapper from 'src/components/ui/QCalendarMonthWrapper.vue';
/// <reference types="cypress" />
describe.skip('<QCalendarMonthWrapper />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SkeletonDescriptor from 'src/components/ui/SkeletonDescriptor.vue';
/// <reference types="cypress" />
describe.skip('<SkeletonDescriptor />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SkeletonForm from 'src/components/ui/SkeletonForm.vue';
/// <reference types="cypress" />
describe.skip('<SkeletonForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SkeletonSummary from 'src/components/ui/SkeletonSummary.vue';
/// <reference types="cypress" />
describe.skip('<SkeletonSummary />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import SkeletonTable from 'src/components/ui/SkeletonTable.vue';
/// <reference types="cypress" />
describe.skip('<SkeletonTable />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,8 +1,64 @@
import VnAvatar from 'src/components/ui/VnAvatar.vue';
/// <reference types="cypress" />
import VnAvatar from 'src/components/ui/VnAvatar.vue'; // Ajusta la ruta según tu estructura de proyecto
describe.skip('<VnAvatar />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnAvatar);
describe('VnAvatar', () => {
const mountComponent = (opt = {}) => {
cy.createWrapper(VnAvatar, {
props: {
...opt,
},
global: {
mocks: {
useSession: () => ({
getTokenMultimedia: () => 'test-token',
}),
useColor: () => '#535353',
getCssVar: () => '#FFFFFF',
},
},
});
};
it('renders with default props', () => {
mountComponent();
cy.get('.q-avatar').should('exist');
cy.get('.q-img').should('exist');
cy.get('.q-avatar').should('have.attr', 'title', 'System');
});
it('displays uppercase title if provided', () => {
mountComponent({ title: 'Test Title' });
cy.get('.q-avatar').should('have.attr', 'title', 'TEST TITLE');
});
it('uses default title when title prop is not provided', () => {
mountComponent();
cy.get('.q-avatar').should('have.attr', 'title', 'System');
});
it('shows first letter of title when image fails to load', () => {
mountComponent({ title: 'Test' });
cy.get('.q-img').should('exist');
cy.get('.q-img').invoke('trigger', 'error');
cy.get('.q-avatar').contains('T');
});
it('applies background color from color prop', () => {
mountComponent({ color: 'red' });
cy.get('.q-avatar')
.should('have.attr', 'style')
.and('include', 'background-color: red;');
});
it.only('applies background color from useColor when color prop is not provided', () => {
mountComponent({ title: 'Test' });
cy.get('.q-avatar')
.should('have.attr', 'style')
.and('include', 'background-color: #000000;');
});
it('displays description slot if provided', () => {
mountComponent({ description: 'Test Description' });
cy.get('.description').should('exist').and('contain', 'Test Description');
});
});

View File

@ -1,5 +1,6 @@
import VnConfirm from 'src/components/ui/VnConfirm.vue';
/// <reference types="cypress" />
describe.skip('<VnConfirm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
/// <reference types="cypress" />
describe.skip('<VnFilterPanel />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnFilterPanelChip from 'src/components/ui/VnFilterPanelChip.vue';
/// <reference types="cypress" />
describe.skip('<VnFilterPanelChip />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnImg from 'src/components/ui/VnImg.vue';
/// <reference types="cypress" />
describe.skip('<VnImg />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnLinkPhone from 'src/components/ui/VnLinkPhone.vue';
/// <reference types="cypress" />
describe.skip('<VnLinkPhone />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,8 +1,32 @@
import { Dark } from 'quasar';
import VnLogo from 'src/components/ui/VnLogo.vue';
describe.skip('<VnLogo />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnLogo);
/// <reference types="cypress" />
describe('<VnLogo />', () => {
const mountComponent = (opt = {}) => {
cy.createWrapper(VnLogo, { props: { ...opt } });
};
it('renders with default logo', () => {
mountComponent();
cy.get('img').should('have.attr', 'src').and('include', 'salix.svg');
});
it.skip('renders with dark mode logo', () => {
cy.stub(Dark, 'isActive').returns(true);
mountComponent();
// Dark.set(true);
cy.get('img').should('have.attr', 'src').and('include', 'salix_dark.svg');
Dark.set(false); // Reset dark mode
});
it.skip('renders with custom logo', () => {
mountComponent({ logo: 'custom' });
cy.get('img').should('have.attr', 'src').and('include', 'custom.svg');
});
it.skip('renders with custom dark mode logo', () => {
mountComponent({ logo: 'custom' });
cy.get('img').should('have.attr', 'src').and('include', 'custom_dark.svg');
Dark.set(false); // Reset dark mode
});
});

View File

@ -1,8 +1,72 @@
import VnLv from 'src/components/ui/VnLv.vue';
import { useClipboard } from 'src/composables/useClipboard';
describe.skip('<VnLv />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(VnLv);
/// <reference types="cypress" />
describe('<VnLv />', () => {
before('login', () => {
Cypress.on('uncaught:exception', () => false);
});
const mountComponent = (opt = {}) => cy.createWrapper(VnLv, { props: { ...opt } });
it('renders with default props', () => {
mountComponent();
cy.get('.vn-label-value').should('exist');
});
it('renders label and value correctly', () => {
mountComponent({ label: 'Test Label', value: 'Test Value' });
cy.get('.label span').should('contain', 'Test Label');
cy.get('.value span').should('contain', 'Test Value');
});
it('renders boolean value as checkbox', () => {
mountComponent({ label: 'Test Label', value: true });
cy.get('.q-checkbox').should('exist');
cy.get('.q-checkbox').should('have.class', 'disabled');
});
it.only('renders info icon with tooltip', () => {
mountComponent({ info: 'Test Info' });
cy.get('.info .q-icon').should('exist');
cy.get('.info .q-icon').then((el) => {
el.trigger('mouseover');
});
// TODO
// cy.get('.q-tooltip').should('contain', 'Test Info');
});
it.only('renders copy icon and copies value', () => {
mountComponent({ value: 'Test Value', copy: true });
// cy.spy(el, 'copyText').as('copyValueText');
cy.get('.copy .q-icon').should('exist');
cy.get('.copy .q-icon').then((el) => {
el.trigger('click');
});
cy.get('.q-notification__message').should('exist');
// cy.window().focused();
// cy.window().then((win) => {
// win.navigator.clipboard.readText().then((text) => {
// console.log('Helloooo:' + text);
// });
// });
// cy.window()
// .its('navigator.clipboard')
// .invoke('readText')
// .should('equal', 'Test Value');
// cy.window().then((win) => {
// win.focus();
// cy.wrap(win.navigator.clipboard.readText()).should('equal', 'Test Value');
// });
// expect('@copyValueText').to.be.called;
});
it('renders dash if value is empty and dash is true', () => {
mountComponent({ value: '', dash: true });
cy.get('.value span').should('contain', '-');
});
it('renders value as is if dash is false', () => {
mountComponent({ value: '', dash: false });
cy.get('.value span').should('contain', '');
});
});

View File

@ -1,5 +1,6 @@
import VnNotes from 'src/components/ui/VnNotes.vue';
/// <reference types="cypress" />
describe.skip('<VnNotes />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnOutForm from 'src/components/ui/VnOutForm.vue';
/// <reference types="cypress" />
describe.skip('<VnOutForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnPaginate from 'src/components/ui/VnPaginate.vue';
/// <reference types="cypress" />
describe.skip('<VnPaginate />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnRow from 'src/components/ui/VnRow.vue';
/// <reference types="cypress" />
describe.skip('<VnRow />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSearchbar from 'src/components/ui/VnSearchbar.vue';
/// <reference types="cypress" />
describe.skip('<VnSearchbar />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSms from 'src/components/ui/VnSms.vue';
/// <reference types="cypress" />
describe.skip('<VnSms />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnSubToolbar from 'src/components/ui/VnSubToolbar.vue';
/// <reference types="cypress" />
describe.skip('<VnSubToolbar />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -1,5 +1,6 @@
import VnUserLink from 'src/components/ui/VnUserLink.vue';
/// <reference types="cypress" />
describe.skip('<VnUserLink />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue

View File

@ -8,9 +8,9 @@ import 'quasar/dist/quasar.css';
import { createRouter, createMemoryHistory } from 'vue-router';
import { useArrayDataStore } from 'src/stores/useArrayDataStore';
import { createWebHistory } from 'vue-router';
import { Quasar, Dialog, Notify } from 'quasar';
import { Quasar, Dialog, Notify, Dark } from 'quasar';
installQuasarPlugin({ plugins: { Dialog, Notify } });
installQuasarPlugin({ plugins: { Dialog, Notify, Dark } });
setActivePinia(createPinia());
axios.defaults.baseURL = Cypress.env('baseUrl');
@ -100,13 +100,15 @@ function createWrapper(component, options = {}) {
app.use(options.router);
},
});
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;
return wrapper;
}
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false;
});
Cypress.Commands.add('createWrapper', createWrapper);
Cypress.Commands.add('_vnMount', (component, options = {}) => {

View File

@ -15,3 +15,8 @@
import './commands';
Cypress.on('uncaught:exception', (err, runnable) => {
// returning false here prevents Cypress from
// failing the test
return false;
});

View File

@ -27,7 +27,7 @@ import '@quasar/extras/material-icons/material-icons.css';
import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-e2e-cypress';
import { config } from '@vue/test-utils';
import { Dialog } from 'quasar';
import { Dialog, Notify, Dark } from 'quasar';
// Example to import i18n from boot and use as plugin
// import { i18n } from 'src/boot/i18n';
@ -43,4 +43,4 @@ config.global.mocks = {
// We do want transitions to show when doing visual testing :)
config.global.stubs = {};
installQuasarPlugin({ plugins: { Dialog } });
installQuasarPlugin({ plugins: { Dialog, Notify, Dark } });

View File

@ -0,0 +1,132 @@
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import VnLocation from 'src/components/common/VnLocation.vue'; // Ajusta la ruta según tu estructura de proyecto
describe('VnLocation', () => {
let wrapper, vm;
beforeEach(() => {
vi.spyOn(axios, 'get').mockResolvedValue({
data: [
{
townFk: 1,
provinceFk: 1,
countryFk: 1,
code: '46000',
town: 'Valencia',
province: 'Province one',
country: 'España',
},
{
townFk: 1,
provinceFk: 1,
countryFk: 1,
code: '46600',
town: 'Valencia',
province: 'Province one',
country: 'España',
},
{
townFk: 2,
provinceFk: 1,
countryFk: 1,
code: '46460',
town: 'Gotham',
province: 'Province one',
country: 'España',
},
{
townFk: 3,
provinceFk: 1,
countryFk: 1,
code: '46680',
town: 'Algemesi',
province: 'Province one',
country: 'España',
},
{
townFk: 4,
provinceFk: 1,
countryFk: 1,
code: '46600',
town: 'Alzira',
province: 'Province one',
country: 'España',
},
{
townFk: 5,
provinceFk: 5,
countryFk: 13,
code: 'EC170150',
town: 'Quito',
province: 'Province five',
country: 'Ecuador',
},
],
});
const cmp = createWrapper(VnLocation, {
global: {
stubs: [
'vnPaginate',
'useState',
'arrayData',
'useStateStore',
'vue-i18n',
],
},
});
wrapper = cmp.wrapper;
vm = cmp.vm;
});
it.only('should handle click on input', async () => {
// Simula el clic en el input de ubicación
await wrapper.get('input[aria-label="Location"]').trigger('click');
const labelFormatted = vm.showLabel({
townFk: 5,
provinceFk: 5,
countryFk: 13,
code: 'EC170150',
town: 'Quito',
province: 'Province five',
country: 'Ecuador',
});
expect(labelFormatted).toBe('EC170150, Quito(Province five), Ecuador');
// Verifica que los datos se hayan cargado correctamente
await wrapper.vm.$nextTick(); // Espera a que se actualice el DOM
const options = wrapper.findAll('select[name="town"] option');
expect(options).toHaveLength(6); // Verifica que las opciones se hayan cargado
});
it('should filter provinces based on selected country', async () => {
// Simula la selección de un país
const element = await wrapper.get('input[aria-label="Location"]');
element.setValue('Ecuador');
await vm.$nextTick();
// Verifica que las provincias se filtren
const provinces = wrapper.findAll('select[name="province"] option');
expect(provinces).toHaveLength(1);
});
it('should filter towns based on selected province', async () => {
// Simula la selección de una provincia
await wrapper.find('select[name="province"]').setValue('Ecuador');
// Verifica que los pueblos se filtren
const towns = wrapper.findAll('select[name="town"] option');
expect(towns).toHaveLength(1);
});
it('should pass selected country', async () => {
const country = 'Ecuador';
const province = 'Province five';
// Simula la selección de un país y una provincia
await wrapper.find('select[name="country"]').setValue(country);
await wrapper.find('select[name="province"]').setValue(province);
// Verifica que el valor seleccionado se pase correctamente
expect(wrapper.find('select[name="province"]').element.value).toBe(province);
});
});

View File

@ -15,6 +15,7 @@ export default defineConfig({
// Matches all files with extension 'js', 'jsx', 'ts' and 'tsx'
'test/vitest/__tests__/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}',
],
reporters: ['html'],
},
plugins: [
vue({