diff --git a/package.json b/package.json index eaaa0b812..a61c8f21a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.42.0", + "version": "24.44.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", diff --git a/src/boot/axios.js b/src/boot/axios.js index 99a163cca..3bd80f487 100644 --- a/src/boot/axios.js +++ b/src/boot/axios.js @@ -2,9 +2,11 @@ import axios from 'axios'; import { useSession } from 'src/composables/useSession'; import { Router } from 'src/router'; import useNotify from 'src/composables/useNotify.js'; +import { useStateQueryStore } from 'src/stores/useStateQueryStore'; const session = useSession(); const { notify } = useNotify(); +const stateQuery = useStateQueryStore(); const baseUrl = '/api/'; axios.defaults.baseURL = baseUrl; @@ -15,7 +17,7 @@ const onRequest = (config) => { if (token.length && !config.headers.Authorization) { config.headers.Authorization = token; } - + stateQuery.add(config); return config; }; @@ -24,10 +26,10 @@ const onRequestError = (error) => { }; const onResponse = (response) => { - const { method } = response.config; + const config = response.config; + stateQuery.remove(config); - const isSaveRequest = method === 'patch'; - if (isSaveRequest) { + if (config.method === 'patch') { notify('globals.dataSaved', 'positive'); } @@ -35,6 +37,8 @@ const onResponse = (response) => { }; const onResponseError = (error) => { + stateQuery.remove(error.config); + let message = ''; const response = error.response; diff --git a/src/boot/defaults/qInput.js b/src/boot/defaults/qInput.js new file mode 100644 index 000000000..299b98718 --- /dev/null +++ b/src/boot/defaults/qInput.js @@ -0,0 +1,4 @@ +import { QInput } from 'quasar'; +import setDefault from './setDefault'; + +setDefault(QInput, 'dense', true); diff --git a/src/boot/defaults/qSelect.js b/src/boot/defaults/qSelect.js new file mode 100644 index 000000000..be0ba048a --- /dev/null +++ b/src/boot/defaults/qSelect.js @@ -0,0 +1,4 @@ +import { QSelect } from 'quasar'; +import setDefault from './setDefault'; + +setDefault(QSelect, 'dense', true); diff --git a/src/boot/quasar.defaults.js b/src/boot/quasar.defaults.js index c792100d7..9638e2057 100644 --- a/src/boot/quasar.defaults.js +++ b/src/boot/quasar.defaults.js @@ -1 +1,3 @@ export * from './defaults/qTable'; +export * from './defaults/qInput'; +export * from './defaults/qSelect'; diff --git a/src/components/CreateBankEntityForm.vue b/src/components/CreateBankEntityForm.vue index 0a3c10f57..a42be6ef8 100644 --- a/src/components/CreateBankEntityForm.vue +++ b/src/components/CreateBankEntityForm.vue @@ -31,8 +31,8 @@ const countriesFilter = { const countriesOptions = ref([]); -const onDataSaved = (formData, requestResponse) => { - emit('onDataSaved', formData, requestResponse); +const onDataSaved = (...args) => { + emit('onDataSaved', ...args); }; onMounted(async () => { diff --git a/src/components/CreateNewPostcodeForm.vue b/src/components/CreateNewPostcodeForm.vue index 99cba5360..030ca1388 100644 --- a/src/components/CreateNewPostcodeForm.vue +++ b/src/components/CreateNewPostcodeForm.vue @@ -79,14 +79,20 @@ async function onProvinceCreated(data) { watch( () => [postcodeFormData.countryFk], async (newCountryFk, oldValueFk) => { - if (!!oldValueFk[0] && newCountryFk[0] !== oldValueFk[0]) { + if (Array.isArray(newCountryFk)) { + newCountryFk = newCountryFk[0]; + } + if (Array.isArray(oldValueFk)) { + oldValueFk = oldValueFk[0]; + } + if (!!oldValueFk && newCountryFk !== oldValueFk) { postcodeFormData.provinceFk = null; postcodeFormData.townFk = null; } - if ((newCountryFk, newCountryFk !== postcodeFormData.countryFk)) { + if (oldValueFk !== newCountryFk) { await provincesFetchDataRef.value.fetch({ where: { - countryFk: newCountryFk[0], + countryFk: newCountryFk, }, }); await townsFetchDataRef.value.fetch({ @@ -103,9 +109,12 @@ watch( watch( () => postcodeFormData.provinceFk, async (newProvinceFk) => { - if (newProvinceFk[0] && newProvinceFk[0] !== postcodeFormData.provinceFk) { + if (Array.isArray(newProvinceFk)) { + newProvinceFk = newProvinceFk[0]; + } + if (newProvinceFk !== postcodeFormData.provinceFk) { await townsFetchDataRef.value.fetch({ - where: { provinceFk: newProvinceFk[0] }, + where: { provinceFk: newProvinceFk }, }); } } @@ -125,16 +134,26 @@ async function handleCountries(data) { - + { }, }" url="Autonomies/location" + :sort-by="['name ASC']" + :limit="30" /> + diff --git a/src/components/VnSelectProvince.vue b/src/components/VnSelectProvince.vue index 606799e50..9fcbef11e 100644 --- a/src/components/VnSelectProvince.vue +++ b/src/components/VnSelectProvince.vue @@ -1,5 +1,5 @@ - event.index > rows.length - 2 && - ($props.crudModel?.paginate ?? true) && - CrudModelRef.vnPaginateRef.paginate() - " + @virtual-scroll="handleScroll" @row-click="(_, row) => rowClickFunction && rowClickFunction(row)" @update:selected="emit('update:selected', $event)" > @@ -811,6 +817,7 @@ es: top: 0; } } + .vnTable { thead tr th { position: sticky; @@ -849,6 +856,9 @@ es: table tbody th { position: relative; } +} + +.last-row-sticky { tbody:nth-last-child(1) { @extend .bg-header; position: sticky; diff --git a/src/components/common/VnBtnSelect.vue b/src/components/common/VnBtnSelect.vue new file mode 100644 index 000000000..b0616a6b2 --- /dev/null +++ b/src/components/common/VnBtnSelect.vue @@ -0,0 +1,19 @@ + + + + + + diff --git a/src/components/common/VnDate.vue b/src/components/common/VnDate.vue new file mode 100644 index 000000000..761ac995e --- /dev/null +++ b/src/components/common/VnDate.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/src/components/common/VnInput.vue b/src/components/common/VnInput.vue index d93ad7465..1246eedcd 100644 --- a/src/components/common/VnInput.vue +++ b/src/components/common/VnInput.vue @@ -130,24 +130,4 @@ const mixinRules = [ .q-field__append { padding-inline: 0; } - -.q-field__append.q-field__marginal.row.no-wrap.items-center.row { - height: 20px; -} -.q-field--outlined .q-field__append.q-field__marginal.row.no-wrap.items-center.row { - height: auto; -} -.q-field__control { - height: unset; -} - -.q-field--labeled { - .q-field__native, - .q-field__prefix, - .q-field__suffix, - .q-field__input { - padding-bottom: 0; - min-height: 15px; - } -} diff --git a/src/components/common/VnInputDate.vue b/src/components/common/VnInputDate.vue index 3d5afaf80..1aa797ab7 100644 --- a/src/components/common/VnInputDate.vue +++ b/src/components/common/VnInputDate.vue @@ -3,6 +3,7 @@ import { onMounted, watch, computed, ref } from 'vue'; import { date } from 'quasar'; import { useI18n } from 'vue-i18n'; import { useAttrs } from 'vue'; +import VnDate from './VnDate.vue'; const model = defineModel({ type: [String, Date] }); const $props = defineProps({ @@ -87,6 +88,11 @@ const styleAttrs = computed(() => { } : {}; }); + +const manageDate = (date) => { + formattedDate.value = date; + isPopupOpen.value = false; +}; @@ -129,6 +135,7 @@ const styleAttrs = computed(() => { /> { :no-focus="true" :no-parent-event="true" > - { - formattedDate = date; - isPopupOpen = false; - } - " - /> + + + + diff --git a/src/components/common/VnInputTime.vue b/src/components/common/VnInputTime.vue index a5e7d3002..6d69bc4a5 100644 --- a/src/components/common/VnInputTime.vue +++ b/src/components/common/VnInputTime.vue @@ -3,6 +3,8 @@ import { computed, ref, useAttrs } from 'vue'; import { useI18n } from 'vue-i18n'; import { date } from 'quasar'; import { useValidator } from 'src/composables/useValidator'; +import VnTime from './VnTime.vue'; + const { validations } = useValidator(); const $attrs = useAttrs(); const model = defineModel({ type: String }); @@ -107,6 +109,7 @@ function dateToTime(newDate) { /> - + + + + diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue index 84ab4b4b6..b0aa648c1 100644 --- a/src/components/common/VnSelect.vue +++ b/src/components/common/VnSelect.vue @@ -141,6 +141,7 @@ function findKeyInOptions() { function setOptions(data) { myOptions.value = JSON.parse(JSON.stringify(data)); myOptionsOriginal.value = JSON.parse(JSON.stringify(data)); + emit('update:options', data); } function filter(val, options) { @@ -227,6 +228,8 @@ function nullishToTrue(value) { } const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val); + +defineExpose({ opts: myOptions }); @@ -283,15 +286,4 @@ const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val); .q-field--outlined { max-width: 100%; } -.q-field__inner { - .q-field__control { - min-height: auto !important; - - display: flex; - align-items: flex-end; - .q-field__native.row { - min-height: auto !important; - } - } -} diff --git a/src/components/common/VnTime.vue b/src/components/common/VnTime.vue new file mode 100644 index 000000000..369f80432 --- /dev/null +++ b/src/components/common/VnTime.vue @@ -0,0 +1,16 @@ + + + + + diff --git a/src/components/ui/CatalogItem.vue b/src/components/ui/CatalogItem.vue index 545bfbbb4..7dca19770 100644 --- a/src/components/ui/CatalogItem.vue +++ b/src/components/ui/CatalogItem.vue @@ -31,7 +31,7 @@ const dialog = ref(null); - + diff --git a/src/components/ui/VnNotes.vue b/src/components/ui/VnNotes.vue index bf5e86a16..b395b3934 100644 --- a/src/components/ui/VnNotes.vue +++ b/src/components/ui/VnNotes.vue @@ -1,6 +1,6 @@ + (observationTypes = data)" + /> @@ -62,29 +73,42 @@ onBeforeRouteLeave((to, from, next) => { {{ t('globals.now') }} - - - - - - + + + + + + + + + { class="show" v-bind="$attrs" search-url="notes" + @on-fetch=" + newNote.text = ''; + newNote.observationTypeFk = null; + " > @@ -111,13 +139,28 @@ onBeforeRouteLeave((to, from, next) => { :descriptor="false" :worker-id="note.workerFk" size="md" + :title="note.worker?.user.nickname" /> - - {{ toDateHourMin(note.created) }} + + + + {{ + observationTypes.find( + (ot) => ot.id === note.observationTypeFk + )?.description + }} + + + @@ -131,12 +174,6 @@ onBeforeRouteLeave((to, from, next) => { es: Add note here...: Añadir nota aquí... New note: Nueva nota Save (Enter): Guardar (Intro) - + Observation type: Tipo de observación diff --git a/src/components/ui/VnPaginate.vue b/src/components/ui/VnPaginate.vue index c6f57b479..80c607214 100644 --- a/src/components/ui/VnPaginate.vue +++ b/src/components/ui/VnPaginate.vue @@ -56,7 +56,7 @@ const props = defineProps({ }, offset: { type: Number, - default: 0, + default: undefined, }, skeleton: { type: Boolean, diff --git a/src/components/ui/VnRow.vue b/src/components/ui/VnRow.vue index 0df1fb7d4..16bcfab7d 100644 --- a/src/components/ui/VnRow.vue +++ b/src/components/ui/VnRow.vue @@ -9,7 +9,6 @@ defineProps({ wrap: { type: Boolean, default: false } }); + +es: + Model: Modelo + Serial number: Número de serie + Current SIM: SIM actual + Add new device: Añadir nuevo dispositivo + PDA deallocated: PDA desasignada + Remove PDA: Eliminar PDA + Do you want to remove this PDA?: ¿Desea eliminar este PDA? + You can only have one PDA: Solo puedes tener un PDA si no eres autonomo + This PDA is already assigned to another user: Este PDA ya está asignado a otro usuario + diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue index 8fee52dd3..ed34e771d 100644 --- a/src/pages/Worker/Card/WorkerSummary.vue +++ b/src/pages/Worker/Card/WorkerSummary.vue @@ -139,6 +139,7 @@ onBeforeMount(async () => { + diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue index 9795cbed0..7a3f760bc 100644 --- a/src/pages/Worker/WorkerList.vue +++ b/src/pages/Worker/WorkerList.vue @@ -29,6 +29,7 @@ const postcodesOptions = ref([]); const user = useState().getUser(); const defaultPayMethod = ref(); +const bankEntitiesRef = ref(); const columns = computed(() => [ { align: 'left', @@ -118,6 +119,12 @@ onBeforeMount(async () => { ).data?.payMethodFk; }); +async function handleNewBankEntity(data, resp) { + await bankEntitiesRef.value.fetch(); + data.bankEntityFk = resp.id; + bankEntitiesOptions.value.push(resp); +} + function handleLocation(data, location) { const { town, code, provinceFk, countryFk } = location ?? {}; data.postcode = code; @@ -177,6 +184,7 @@ async function autofillBic(worker) { auto-load /> (bankEntitiesOptions = data)" auto-load @@ -344,7 +352,9 @@ async function autofillBic(worker) { > bankEntitiesOptions.push(data)" + @on-data-saved=" + (_, resp) => handleNewBankEntity(data, resp) + " /> diff --git a/src/pages/Worker/locale/en.yml b/src/pages/Worker/locale/en.yml index 865e86e7e..8276977fd 100644 --- a/src/pages/Worker/locale/en.yml +++ b/src/pages/Worker/locale/en.yml @@ -9,3 +9,4 @@ tableColumns: fi: FI SSN: SSN extension: Extension +queue: Queue diff --git a/src/pages/Worker/locale/es.yml b/src/pages/Worker/locale/es.yml index b3c093ec5..9c7618bc3 100644 --- a/src/pages/Worker/locale/es.yml +++ b/src/pages/Worker/locale/es.yml @@ -14,3 +14,4 @@ tableColumns: fi: NIF SSN: NSS extension: Extensión +queue: Cola diff --git a/src/pages/Zone/ZoneDeliveryPanel.vue b/src/pages/Zone/ZoneDeliveryPanel.vue index 088811b01..423095d6e 100644 --- a/src/pages/Zone/ZoneDeliveryPanel.vue +++ b/src/pages/Zone/ZoneDeliveryPanel.vue @@ -94,9 +94,9 @@ watch( url="Postcodes/location" :fields="['geoFk', 'code', 'townFk', 'countryFk']" sort-by="code, townFk" - option-value="code" + option-value="geoFk" option-label="code" - option-filter="code" + :filter-options="['code', 'geoFk']" hide-selected dense outlined diff --git a/src/router/modules/entry.js b/src/router/modules/entry.js index 4750a4301..3add239df 100644 --- a/src/router/modules/entry.js +++ b/src/router/modules/entry.js @@ -12,7 +12,13 @@ export default { component: RouterView, redirect: { name: 'EntryMain' }, menus: { - main: ['EntryList', 'MyEntries', 'EntryLatestBuys', 'EntryStockBought'], + main: [ + 'EntryList', + 'MyEntries', + 'EntryLatestBuys', + 'EntryStockBought', + 'EntryWasteRecalc', + ], card: ['EntryBasicData', 'EntryBuys', 'EntryNotes', 'EntryDms', 'EntryLog'], }, children: [ @@ -67,6 +73,15 @@ export default { }, component: () => import('src/pages/Entry/EntryStockBought.vue'), }, + { + path: 'waste-recalc', + name: 'EntryWasteRecalc', + meta: { + title: 'wasteRecalc', + icon: 'compost', + }, + component: () => import('src/pages/Entry/EntryWasteRecalc.vue'), + }, ], }, { diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js index 7258881be..c2a9e668f 100644 --- a/src/router/modules/worker.js +++ b/src/router/modules/worker.js @@ -27,6 +27,7 @@ export default { 'WorkerBalance', 'WorkerFormation', 'WorkerMedical', + 'WorkerOperator', ], }, children: [ @@ -208,6 +209,15 @@ export default { }, component: () => import('src/pages/Worker/Card/WorkerMedical.vue'), }, + { + name: 'WorkerOperator', + path: 'operator', + meta: { + title: 'operator', + icon: 'person', + }, + component: () => import('src/pages/Worker/Card/WorkerOperator.vue'), + }, ], }, ], diff --git a/src/stores/useStateQueryStore.js b/src/stores/useStateQueryStore.js new file mode 100644 index 000000000..d25dbb921 --- /dev/null +++ b/src/stores/useStateQueryStore.js @@ -0,0 +1,31 @@ +import { ref, computed } from 'vue'; +import { defineStore } from 'pinia'; + +export const useStateQueryStore = defineStore('stateQueryStore', () => { + const queries = ref(new Set()); + + function add(query) { + queries.value.add(query); + return query; + } + + function isLoading() { + return computed(() => queries.value.size); + } + + function remove(query) { + queries.value.delete(query); + } + + function reset() { + queries.value = new Set(); + } + + return { + add, + isLoading, + remove, + queries, + reset, + }; +}); diff --git a/test/cypress/integration/claim/claimDevelopment.spec.js b/test/cypress/integration/claim/claimDevelopment.spec.js index 81fc33ecd..eb39f340a 100755 --- a/test/cypress/integration/claim/claimDevelopment.spec.js +++ b/test/cypress/integration/claim/claimDevelopment.spec.js @@ -33,7 +33,8 @@ describe('ClaimDevelopment', () => { cy.saveCard(); }); - it('should add and remove new line', () => { + // TODO: #8112 + xit('should add and remove new line', () => { cy.wait(['@workers', '@workers']); cy.addCard(); diff --git a/test/cypress/integration/claim/claimNotes.spec.js b/test/cypress/integration/claim/claimNotes.spec.js index a4a493cda..d7a918db1 100644 --- a/test/cypress/integration/claim/claimNotes.spec.js +++ b/test/cypress/integration/claim/claimNotes.spec.js @@ -1,4 +1,6 @@ describe('ClaimNotes', () => { + const saveBtn = '.q-field__append > .q-btn > .q-btn__content > .q-icon'; + const firstNote = '.q-infinite-scroll :nth-child(1) > .q-card__section--vert'; beforeEach(() => { cy.login('developer'); cy.visit(`/#/claim/${2}/notes`); @@ -7,7 +9,7 @@ describe('ClaimNotes', () => { it('should add a new note', () => { const message = 'This is a new message.'; cy.get('.q-textarea').type(message); - cy.get('.q-field__append > .q-btn > .q-btn__content > .q-icon').click(); //save - cy.get(':nth-child(1) > .q-card__section--vert').should('have.text', message); + cy.get(saveBtn).click(); + cy.get(firstNote).should('have.text', message); }); }); diff --git a/test/cypress/integration/client/clientAddress.spec.js b/test/cypress/integration/client/clientAddress.spec.js new file mode 100644 index 000000000..db876b64b --- /dev/null +++ b/test/cypress/integration/client/clientAddress.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client consignee', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/address', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientBalance.spec.js b/test/cypress/integration/client/clientBalance.spec.js new file mode 100644 index 000000000..4a666bdb1 --- /dev/null +++ b/test/cypress/integration/client/clientBalance.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client balance', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/balance', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientBasicData.spec.js b/test/cypress/integration/client/clientBasicData.spec.js new file mode 100644 index 000000000..7b0a19828 --- /dev/null +++ b/test/cypress/integration/client/clientBasicData.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client basic data', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/basic-data', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientBillingData.spec.js b/test/cypress/integration/client/clientBillingData.spec.js new file mode 100644 index 000000000..00af82e39 --- /dev/null +++ b/test/cypress/integration/client/clientBillingData.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client billing data', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/billing-data', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientCredits.spec.js b/test/cypress/integration/client/clientCredits.spec.js new file mode 100644 index 000000000..f81bf987d --- /dev/null +++ b/test/cypress/integration/client/clientCredits.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client credits', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/credits', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientFiscalData.spec.js b/test/cypress/integration/client/clientFiscalData.spec.js new file mode 100644 index 000000000..e337c26f8 --- /dev/null +++ b/test/cypress/integration/client/clientFiscalData.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client fiscal data', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/fiscal-data', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientGreuges.spec.js b/test/cypress/integration/client/clientGreuges.spec.js new file mode 100644 index 000000000..23f8b3182 --- /dev/null +++ b/test/cypress/integration/client/clientGreuges.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client greuges', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/greuges', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientList.spec.js b/test/cypress/integration/client/clientList.spec.js new file mode 100644 index 000000000..93e53b9f6 --- /dev/null +++ b/test/cypress/integration/client/clientList.spec.js @@ -0,0 +1,63 @@ +/// +describe('Client list', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('/#/customer/list', { + timeout: 5000, + onBeforeLoad(win) { + cy.stub(win, 'open'); + }, + }); + }); + + it('Client list create new client', () => { + cy.get('.q-page-sticky > div > .q-btn > .q-btn__content > .q-icon').click(); + const data = { + Name: { val: 'Name 1' }, + 'Social name': { val: 'TEST 1' }, + 'Tax number': { val: '20852113Z' }, + 'Web user': { val: 'user_test_1' }, + Street: { val: 'C/ STREET 1' }, + Email: { val: 'user.test@1.com' }, + 'Business type': { val: 'Otros', type: 'select' }, + 'Sales person': { val: 'salesboss', type: 'select' }, + Location: { val: '46000, Valencia(Province one), España', type: 'select' }, + }; + cy.fillInForm(data); + + cy.get('.q-mt-lg > .q-btn--standard').click(); + + cy.checkNotification('created'); + cy.url().should('include', '/summary'); + }); + it('Client list search client', () => { + const search = 'Jessica Jones'; + cy.searchByLabel('Name', search); + + cy.get('.title > span').should('have.text', search); + let id = null; + cy.get('.q-item > .q-item__label').then((text) => { + id = text.text().trim().split('#')[1]; + cy.get('.q-item > .q-item__label').should('have.text', ` #${id}`); + cy.url().should('include', `/customer/${id}/summary`); + }); + }); + + it('Client founded create ticket', () => { + const search = 'Jessica Jones'; + cy.searchByLabel('Name', search); + cy.clickButtonsDescriptor(2); + cy.waitForElement('#formModel'); + cy.waitForElement('.q-form'); + cy.checkValueForm(1, search); + }); + it('Client founded create order', () => { + const search = 'Jessica Jones'; + cy.searchByLabel('Name', search); + cy.clickButtonsDescriptor(4); + cy.waitForElement('#formModel'); + cy.waitForElement('.q-form'); + cy.checkValueForm(2, search); + }); +}); diff --git a/test/cypress/integration/client/clientNotes.spec.js b/test/cypress/integration/client/clientNotes.spec.js new file mode 100644 index 000000000..99a7c66c5 --- /dev/null +++ b/test/cypress/integration/client/clientNotes.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client notes', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/notes', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientRecoveries.spec.js b/test/cypress/integration/client/clientRecoveries.spec.js new file mode 100644 index 000000000..a4e220008 --- /dev/null +++ b/test/cypress/integration/client/clientRecoveries.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client recoveries', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/recoveries', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/clientWebAccess.spec.js b/test/cypress/integration/client/clientWebAccess.spec.js new file mode 100644 index 000000000..47f9efa4c --- /dev/null +++ b/test/cypress/integration/client/clientWebAccess.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client web-access', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/web-access', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js b/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js new file mode 100644 index 000000000..3c35d5ed0 --- /dev/null +++ b/test/cypress/integration/client/credit-management/clientCreditContracts.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client credit opinion', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/credit-management/credit-contracts', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js new file mode 100644 index 000000000..7d9c0fa77 --- /dev/null +++ b/test/cypress/integration/client/credit-management/clientCreditOpinion.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client credit opinion', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/credit-management/credit-opinion', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientConsumption.spec.js b/test/cypress/integration/client/others/clientConsumption.spec.js new file mode 100644 index 000000000..179a37707 --- /dev/null +++ b/test/cypress/integration/client/others/clientConsumption.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client consumption', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/others/consumption', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientContacts.spec.js b/test/cypress/integration/client/others/clientContacts.spec.js new file mode 100644 index 000000000..66a86801a --- /dev/null +++ b/test/cypress/integration/client/others/clientContacts.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client contacts', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/others/contacts', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientMandates.spec.js b/test/cypress/integration/client/others/clientMandates.spec.js new file mode 100644 index 000000000..aaeb7f930 --- /dev/null +++ b/test/cypress/integration/client/others/clientMandates.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client mandates', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/others/mandates', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientSamples.spec.js b/test/cypress/integration/client/others/clientSamples.spec.js new file mode 100644 index 000000000..03b7238f4 --- /dev/null +++ b/test/cypress/integration/client/others/clientSamples.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client samples', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/others/samples', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientUnpaid.spec.js b/test/cypress/integration/client/others/clientUnpaid.spec.js new file mode 100644 index 000000000..9972ba0e9 --- /dev/null +++ b/test/cypress/integration/client/others/clientUnpaid.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client unpaid', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1110/others/unpaid', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/client/others/clientWebPayments.spec.js b/test/cypress/integration/client/others/clientWebPayments.spec.js new file mode 100644 index 000000000..5f7087d21 --- /dev/null +++ b/test/cypress/integration/client/others/clientWebPayments.spec.js @@ -0,0 +1,13 @@ +/// +describe('Client web payments', () => { + beforeEach(() => { + cy.viewport(1280, 720); + cy.login('developer'); + cy.visit('#/customer/1101/others/web-payments', { + timeout: 5000, + }); + }); + it('Should load layout', () => { + cy.get('.q-card').should('be.visible'); + }); +}); diff --git a/test/cypress/integration/entry/myEntry.spec.js b/test/cypress/integration/entry/myEntry.spec.js index dca74dec2..4addec1c4 100644 --- a/test/cypress/integration/entry/myEntry.spec.js +++ b/test/cypress/integration/entry/myEntry.spec.js @@ -11,7 +11,7 @@ describe('EntryMy when is supplier', () => { it('should open buyLabel when is supplier', () => { cy.get( - '[to="/null/2"] > .q-card > .column > .q-btn > .q-btn__content > .q-icon' + '[to="/null/3"] > .q-card > .column > .q-btn > .q-btn__content > .q-icon' ).click(); cy.get('.q-card__actions > .q-btn').click(); cy.window().its('open').should('be.called'); diff --git a/test/cypress/integration/ticket/ticketDescriptor.spec.js b/test/cypress/integration/ticket/ticketDescriptor.spec.js index 8192b7c7c..0ba2723a2 100644 --- a/test/cypress/integration/ticket/ticketDescriptor.spec.js +++ b/test/cypress/integration/ticket/ticketDescriptor.spec.js @@ -1,7 +1,8 @@ /// describe('Ticket descriptor', () => { - const toCloneOpt = '[role="menu"] .q-list > :nth-child(5)'; - const setWeightOpt = '[role="menu"] .q-list > :nth-child(6)'; + const listItem = '[role="menu"] .q-list .q-item'; + const toCloneOpt = 'To clone ticket'; + const setWeightOpt = 'Set weight'; const warehouseValue = ':nth-child(1) > :nth-child(6) > .value > span'; const summaryHeader = '.summaryHeader > div'; const weight = 25; @@ -14,7 +15,7 @@ describe('Ticket descriptor', () => { it('should clone the ticket without warehouse', () => { cy.visit('/#/ticket/1/summary'); cy.openActionsDescriptor(); - cy.get(toCloneOpt).click(); + cy.contains(listItem, toCloneOpt).click(); cy.clickConfirm(); cy.get(warehouseValue).contains('Warehouse One'); cy.get(summaryHeader) @@ -28,7 +29,7 @@ describe('Ticket descriptor', () => { it('should set the weight of the ticket', () => { cy.visit('/#/ticket/10/summary'); cy.openActionsDescriptor(); - cy.get(setWeightOpt).click(); + cy.contains(listItem, setWeightOpt).click(); cy.intercept('POST', /\/api\/Tickets\/\d+\/setWeight/).as('weight'); cy.get('.q-dialog input').type(weight); cy.clickConfirm(); diff --git a/test/cypress/integration/ticket/ticketExpedition.spec.js b/test/cypress/integration/ticket/ticketExpedition.spec.js new file mode 100644 index 000000000..5eb2c1a2a --- /dev/null +++ b/test/cypress/integration/ticket/ticketExpedition.spec.js @@ -0,0 +1,28 @@ +/// + +describe('Ticket expedtion', () => { + const tableContent = '.q-table .q-virtual-scroll__content'; + const stateTd = 'td:nth-child(9)'; + + beforeEach(() => { + cy.login('developer'); + cy.viewport(1920, 1080); + }); + + it('should change the state', () => { + cy.visit('#/ticket/1/expedition'); + cy.intercept('GET', /\/api\/Expeditions\/filter/).as('expeditions'); + cy.intercept('POST', /\/api\/Expeditions\/crud/).as('crud'); + + cy.wait('@expeditions'); + + cy.selectRows([1, 2]); + cy.get('#subToolbar [aria-controls]:nth-child(1)').click(); + cy.get('.q-menu .q-item').contains('Perdida').click(); + cy.wait('@crud'); + + cy.get(`${tableContent} tr:nth-child(-n+2) ${stateTd}`).each(($el) => { + cy.wrap($el).contains('Perdida'); + }); + }); +}); diff --git a/test/cypress/integration/vnComponent/vnLocation.spec.js b/test/cypress/integration/vnComponent/vnLocation.spec.js index 78dc38899..c1b0cf929 100644 --- a/test/cypress/integration/vnComponent/vnLocation.spec.js +++ b/test/cypress/integration/vnComponent/vnLocation.spec.js @@ -64,7 +64,7 @@ describe('VnLocation', () => { `${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix} > :nth-child(3) > .q-icon` ).click(); cy.get( - `#q-portal--dialog--4 > .q-dialog > ${createForm.prefix} > .vn-row > .q-select > ${createForm.sufix} > :nth-child(1) input` + `#q-portal--dialog--5 > .q-dialog > ${createForm.prefix} > .vn-row > .q-select > ${createForm.sufix} > :nth-child(1) input` ).should('have.value', province); }); }); @@ -133,6 +133,8 @@ describe('VnLocation', () => { ); cy.get('.q-mt-lg > .q-btn--standard').click(); cy.get(`${createForm.prefix}`).should('not.exist'); + cy.waitForElement('.q-form'); + checkVnLocation(postCode, province); }); it('Create city', () => { @@ -144,10 +146,12 @@ describe('VnLocation', () => { cy.get( `${createForm.prefix} > :nth-child(4) > .q-select > ${createForm.sufix} > :nth-child(2) > .q-icon` ).click(); - cy.selectOption('#q-portal--dialog--2 .q-select', 'one'); - cy.get('#q-portal--dialog--2 .q-input').type(province); - cy.get('#q-portal--dialog--2 .q-btn--standard').click(); + cy.selectOption('#q-portal--dialog--3 .q-select', 'one'); + cy.get('#q-portal--dialog--3 .q-input').type(province); + cy.get('#q-portal--dialog--3 .q-btn--standard').click(); cy.get('#q-portal--dialog--1 .q-btn--standard').click(); + cy.waitForElement('.q-form'); + checkVnLocation(postCode, province); }); diff --git a/test/cypress/support/commands.js b/test/cypress/support/commands.js index 83f45b721..8d48dc71a 100755 --- a/test/cypress/support/commands.js +++ b/test/cypress/support/commands.js @@ -152,6 +152,14 @@ Cypress.Commands.add('notificationHas', (selector, text) => { cy.get(selector).should('have.text', text); }); +Cypress.Commands.add('selectRows', (rows) => { + rows.forEach((row) => { + cy.get('.q-table .q-virtual-scroll__content tr .q-checkbox__inner') + .eq(row - 1) + .click(); + }); +}); + Cypress.Commands.add('fillRow', (rowSelector, data) => { // Usar el selector proporcionado para obtener la fila deseada cy.waitForElement('tbody'); diff --git a/test/vitest/__tests__/boot/axios.spec.js b/test/vitest/__tests__/boot/axios.spec.js index feb0d93ea..7a802b4d2 100644 --- a/test/vitest/__tests__/boot/axios.spec.js +++ b/test/vitest/__tests__/boot/axios.spec.js @@ -7,41 +7,46 @@ vi.mock('src/composables/useSession', () => ({ getToken: () => 'DEFAULT_TOKEN', isLoggedIn: () => vi.fn(), destroy: () => vi.fn(), - }) + }), +})); + +vi.mock('src/stores/useStateQueryStore', () => ({ + useStateQueryStore: () => ({ + add: () => vi.fn(), + remove: () => vi.fn(), + }), })); describe('Axios boot', () => { - describe('onRequest()', async () => { it('should set the "Authorization" property on the headers', async () => { const config = { headers: {} }; const resultConfig = onRequest(config); - expect(resultConfig).toEqual(expect.objectContaining({ - headers: { - Authorization: 'DEFAULT_TOKEN' - } - })); + expect(resultConfig).toEqual( + expect.objectContaining({ + headers: { + Authorization: 'DEFAULT_TOKEN', + }, + }) + ); }); - }) + }); describe('onResponseError()', async () => { it('should call to the Notify plugin with a message error for an status code "500"', async () => { - Notify.create = vi.fn() + Notify.create = vi.fn(); const error = { response: { - status: 500 - } + status: 500, + }, }; const result = onResponseError(error); - - expect(result).rejects.toEqual( - expect.objectContaining(error) - ); + expect(result).rejects.toEqual(expect.objectContaining(error)); expect(Notify.create).toHaveBeenCalledWith( expect.objectContaining({ message: 'An internal server error has ocurred', @@ -51,25 +56,22 @@ describe('Axios boot', () => { }); it('should call to the Notify plugin with a message from the response property', async () => { - Notify.create = vi.fn() + Notify.create = vi.fn(); const error = { response: { status: 401, data: { error: { - message: 'Invalid user or password' - } - } - } + message: 'Invalid user or password', + }, + }, + }, }; const result = onResponseError(error); - - expect(result).rejects.toEqual( - expect.objectContaining(error) - ); + expect(result).rejects.toEqual(expect.objectContaining(error)); expect(Notify.create).toHaveBeenCalledWith( expect.objectContaining({ message: 'Invalid user or password', @@ -77,5 +79,5 @@ describe('Axios boot', () => { }) ); }); - }) + }); }); diff --git a/test/vitest/__tests__/stores/useStateQueryStore.spec.js b/test/vitest/__tests__/stores/useStateQueryStore.spec.js new file mode 100644 index 000000000..ab3afb007 --- /dev/null +++ b/test/vitest/__tests__/stores/useStateQueryStore.spec.js @@ -0,0 +1,58 @@ +import { describe, expect, it, beforeEach, beforeAll } from 'vitest'; +import { createWrapper } from 'app/test/vitest/helper'; + +import { useStateQueryStore } from 'src/stores/useStateQueryStore'; + +describe('useStateQueryStore', () => { + beforeAll(() => { + createWrapper({}, {}); + }); + + const stateQueryStore = useStateQueryStore(); + const { add, isLoading, remove, reset } = useStateQueryStore(); + const firstQuery = { url: 'myQuery' }; + + function getQueries() { + return stateQueryStore.queries; + } + + beforeEach(() => { + reset(); + expect(getQueries().size).toBeFalsy(); + }); + + it('should add two queries', async () => { + expect(getQueries().size).toBeFalsy(); + add(firstQuery); + + expect(getQueries().size).toBeTruthy(); + expect(getQueries().has(firstQuery)).toBeTruthy(); + + add(); + expect(getQueries().size).toBe(2); + }); + + it('should add and remove loading state', async () => { + expect(isLoading().value).toBeFalsy(); + add(firstQuery); + expect(isLoading().value).toBeTruthy(); + remove(firstQuery); + expect(isLoading().value).toBeFalsy(); + }); + + it('should add and remove query', async () => { + const secondQuery = { ...firstQuery }; + const thirdQuery = { ...firstQuery }; + + add(firstQuery); + add(secondQuery); + + const beforeCount = getQueries().size; + add(thirdQuery); + expect(getQueries().has(thirdQuery)).toBeTruthy(); + + remove(thirdQuery); + expect(getQueries().has(thirdQuery)).toBeFalsy(); + expect(getQueries().size).toBe(beforeCount); + }); +});