diff --git a/cypress.config.js b/cypress.config.js
index b30df2b3d..f629c5b28 100644
--- a/cypress.config.js
+++ b/cypress.config.js
@@ -4,6 +4,9 @@ const {
} = require('@quasar/quasar-app-extension-testing-e2e-cypress/cct-dev-server');
module.exports = defineConfig({
+ env: {
+ baseUrl: 'http://localhost:9000/',
+ },
e2e: {
baseUrl: 'http://localhost:9000/',
experimentalStudio: true,
@@ -33,7 +36,10 @@ module.exports = defineConfig({
indexHtmlFile: 'test/cypress/support/component-index.html',
supportFile: 'test/cypress/support/component.js',
specPattern: 'test/cypress/components/**/*.spec.js',
- devServer: injectQuasarDevServerConfig(),
+ devServer: {
+ framework: 'quasar',
+ bundler: 'vite',
+ },
setupNodeEvents(on, config) {
// implement node event listeners here
on('after:spec', (results) => {
diff --git a/src/stores/useArrayDataStore.js b/src/stores/useArrayDataStore.js
index ea029bc12..7efda1430 100644
--- a/src/stores/useArrayDataStore.js
+++ b/src/stores/useArrayDataStore.js
@@ -1,8 +1,9 @@
-import { ref } from 'vue';
import { defineStore } from 'pinia';
+import { ref } from 'vue';
export const useArrayDataStore = defineStore('arrayDataStore', () => {
const state = ref({});
+
const defaultOpts = {
filter: {},
userFilter: {},
@@ -24,7 +25,7 @@ export const useArrayDataStore = defineStore('arrayDataStore', () => {
}
function set(key) {
- state.value[key] = getDefaultState();
+ state.value[key] = getDefaultState(); // Ahora asigna el estado a la clave 'key'
}
function clear(key) {
diff --git a/src/stores/useArrayDataStore.test.js b/src/stores/useArrayDataStore.test.js
new file mode 100644
index 000000000..2543f030f
--- /dev/null
+++ b/src/stores/useArrayDataStore.test.js
@@ -0,0 +1,22 @@
+import { setActivePinia, createPinia } from 'pinia';
+import { useArrayDataStore } from './useArrayDataStore';
+
+describe('useArrayDataStore', () => {
+ beforeEach(() => {
+ setActivePinia(createPinia());
+ });
+
+ it('should initialize isLoading to false', () => {
+ const store = useArrayDataStore();
+ store.set('testKey');
+ expect(store.get('testKey').isLoading).toBe(false);
+ });
+
+ it('should reset isLoading to false', () => {
+ const store = useArrayDataStore();
+ store.set('testKey');
+ store.get('testKey').isLoading = true;
+ store.reset('testKey', ['isLoading']);
+ expect(store.get('testKey').isLoading).toBe(false);
+ });
+});
diff --git a/test/cypress/components/CreateBankEntityForm.spec.js b/test/cypress/components/CreateBankEntityForm.spec.js
index c4adc76dc..0739c0e1c 100644
--- a/test/cypress/components/CreateBankEntityForm.spec.js
+++ b/test/cypress/components/CreateBankEntityForm.spec.js
@@ -1,31 +1,34 @@
+import { createTestingPinia } from '@pinia/testing';
import axios from 'axios';
+import { setActivePinia } from 'pinia';
+import { createPinia } from 'pinia';
import CreateBankEntityForm from 'src/components/CreateBankEntityForm.vue';
import { useArrayData } from 'src/composables/useArrayData';
import { useArrayDataStore } from 'src/stores/useArrayDataStore';
-// import { useRouter } from 'vue-router';
+import { useRouter } from 'vue-router';
// import vueRouter from 'vue-router';
describe('', () => {
const mockApiResponse = { results: [{ id: 1, name: 'Test' }] };
- const arrayDataStore = useArrayDataStore();
+ // const arrayDataStore = useArrayDataStore();
const mockStoreData = { filter: {}, userFilter: {}, userParams: {}, url: 'mockUrl' };
-
+ let store, arrayData;
before(() => {
cy.login('developer');
// cy.stub(arrayDataStore, 'get').callsFake(() => 'asd');
- cy.stub(arrayDataStore, 'get')
- .callsFake((e, fn) => (e = fn))
- .as('update');
- const arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
+ // cy.stub(arrayDataStore, 'get')
+ // .callsFake((e, fn) => (e = fn))
+ // .as('update');
+ // const arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
- cy.stub(arrayData).callsFake(() => ({
- userParams: {},
- userFilter: {},
- order: {},
- searchUrl: 'searchUrl',
- }));
- // cy.stub(vueRouter, 'useRouter').callsFake(() => ({
+ // cy.stub(arrayData).callsFake(() => ({
+ // userParams: {},
+ // userFilter: {},
+ // order: {},
+ // searchUrl: 'searchUrl',
+ // }));
+ // cy.stub(vueRouter).callsFake(() => ({
// push: () => {},
// replace: () => {},
// currentRoute: {
@@ -38,14 +41,69 @@ describe('', () => {
// },
// },
// }));
+ Cypress.config('defaultCommandTimeout', 500);
+
+ // const spy = cy.spy();
+ // createTestingPinia({
+ // createSpy: () => spy,
+ // });
+
+ // // one way:
+ // store = useArrayDataStore();
+
+ // // another way with the same error:
+ // useArrayDataStore(
+ // createTestingPinia({
+ // createSpy: () => spy,
+ // initialState: {
+ // state: { ArrayData: cy.spy() },
+ // },
+ // })
+ // );
+
+ // cy.stub(useArrayDataStore, 'get').callsFake(() => cy.spy());
+ // cy.stub(useArrayData, 'get').callsFake(() => store);
+ // arrayData = useArrayData('ArrayData', { url: 'mockUrl' });
});
beforeEach(() => {
+ // cy._mount(CreateBankEntityForm, {
+ // global: {
+ // plugins: [store],
+ // },
+ // });
// Stub del método get del store
// cy.spy(useRouter(), 'replace');
// cy.spy(useRouter(), 'push');
});
it('should intercept axios.get for a specific route', () => {
+ // Configura Pinia y la store
+ const pinia = createPinia();
+ setActivePinia(pinia);
+ const arrayDataStore = useArrayDataStore();
+ cy.stub(arrayDataStore, 'get').returns(mockStoreData).as('getStub');
+
+ cy.stub(arrayData, 'arrayDataStore').callsFake(() => store);
+ cy.createWrapper(CreateBankEntityForm);
+ // Obtén la instancia de la store de Pinia
+ // const store = useArrayDataStore();
+ // Asegúrate de que el método `set` esté disponible
+ // Usar cy.stub() para espiar la función set y personalizar su comportamiento
+ // cy.stub(store, 'set').callsFake(() => {
+ // console.log('store.set fue llamado');
+ // // Simular que set se ejecuta correctamente
+ // store.get('key').data = 'Fake Data';
+ // });
+ // expect(store.set).to.be.a('function');
+ // store.set('key'); // Inicializar el estado con `set`
+ // store.get('key').data = 'Test Data'; // Simular que tenemos datos
+ // // Simula que agregamos usuarios a la store
+ // store.setUsers([
+ // { id: 1, name: 'John Doe' },
+ // { id: 2, name: 'Jane Doe' },
+ // ]);
+ });
+ xit('should intercept axios.get for a specific route', () => {
// Intercepta la llamada a axios.get para una ruta específica
cy.stub(axios, 'get')
.callsFake((url, params) => {
@@ -58,7 +116,11 @@ describe('', () => {
.as('axiosStub');
const onFetchSpy = cy.spy().as('onFetchSpy');
-
+ // Configura Pinia y la store
+ const pinia = createPinia();
+ setActivePinia(pinia);
+ const arrayDataStore = useArrayDataStore();
+ cy.stub(arrayDataStore, 'get').returns(mockStoreData).as('getStub');
cy.createWrapper(CreateBankEntityForm, {
props: {
showEntityField: true,
diff --git a/test/cypress/components/FormModel.spec.js b/test/cypress/components/FormModel.spec.js
index 859c1f9a1..22cf8ab82 100644
--- a/test/cypress/components/FormModel.spec.js
+++ b/test/cypress/components/FormModel.spec.js
@@ -1,8 +1,142 @@
+import { Notify } from 'quasar';
import FormModel from 'src/components/FormModel.vue';
+// import useNotify from 'src/composables/useNotify';
+import { useState } from 'src/composables/useState';
+import { useStateStore } from 'src/stores/useStateStore';
-describe.skip('', () => {
- it('TODO: boilerplate', () => {
- // see: https://on.cypress.io/mounting-vue
- cy.createWrapper(FormModel, { props: {} });
+describe('', () => {
+ let piniaOptions = null;
+ let saveSpy, notifySpy, component, wrapper;
+ beforeEach(() => {
+ piniaOptions = {
+ stubActions: false,
+ createSpy: cy.spy, // Use Cypress spy function
+ };
+ const state = useState();
+ const stateStore = useStateStore();
+ cy.stub(stateStore, 'isSubToolbarShown').returns(true).as('isSubToolbarShown');
+ state.set('testModel', { name: 'Test', age: 30 });
+ const props = {
+ url: '',
+ model: 'testModel',
+ filter: {},
+ urlUpdate: '',
+ urlCreate: '/api/test/create',
+ defaultActions: true,
+ defaultButtons: {},
+ autoLoad: false,
+ formInitialData: {},
+ observeFormChanges: true,
+ mapper: null,
+ clearStoreOnUnmount: true,
+ saveFn: null,
+ goTo: '',
+ reload: false,
+ defaultTrim: true,
+ };
+ cy.mount(FormModel, {
+ piniaOptions,
+ props,
+ slots: {
+ form: `
+
+
+
+ `,
+ moreActions: `
+
+ `,
+ },
+ }).then(({ component: cmp, wrapper: wpr }) => {
+ component = cmp;
+ wrapper = wpr;
+ saveSpy = cy.spy(component, 'save').as('saveSpy');
+ notifySpy = cy.spy(Notify, 'create').as('notifySpy');
+ });
});
+ it('should mount the component', () => {
+ cy.get('#formModel').should('exist');
+ });
+
+ it('should call the save method when the save button is clicked without changes', () => {
+ cy.get('#formModel').should('exist');
+ cy.get('button').contains('Save').click();
+ cy.get('@saveSpy').should('not.have.been.called');
+ cy.get('@notifySpy').should((spy) => {
+ expect(spy).to.have.been.calledWith({
+ message: 'No changes to save',
+ type: 'negative',
+ icon: 'error',
+ });
+ });
+ });
+ it('should call the save method when the save button is clicked with changes', () => {
+ cy.get('#formModel').should('exist');
+ cy.get('[data-cy="name"]').type('John Doe');
+ cy.get('button').contains('Save').click();
+ cy.get('@saveSpy').should('not.have.been.called');
+ cy.get('@notifySpy').should((spy) => {
+ const [args] = spy.getCall(0)?.args || [];
+ expect(args.type).to.equal('negative');
+ expect(args.icon).to.equal('error');
+ expect(args.message).not.to.equal('No changes to save');
+ });
+ });
+ /*
+ it('should display the confirmation dialog on route leave with unsaved changes', () => {
+ // Simulate form change
+ cy.get('#formModel').then((form) => {
+ form[0].__vue__.formData.name = 'Changed';
+ });
+
+ // Attempt to navigate away
+ cy.get('.q-dialog').should('be.visible');
+ cy.get('.q-dialog .q-dialog__title').should(
+ 'contain',
+ 'globals.unsavedPopup.title'
+ );
+ });
+
+ it('should call save method on form submit', async () => {
+ const saveSpy = cy.spy(formModel.value, 'save');
+ await formModel.value.$refs.myForm.trigger('submit');
+ expect(saveSpy).to.have.been.called;
+ });
+
+ it('should reset the form data', async () => {
+ formModel.value.formData.name = 'Changed';
+ await formModel.value.reset();
+ expect(formModel.value.formData.name).toBe('Test');
+ });
+
+ it('should show loading indicator when saving', async () => {
+ formModel.value.isLoading = true;
+ await nextTick();
+ expect(wrapper.findComponent({ name: 'QInnerLoading' }).props('showing')).toBe(true);
+ });
+
+ it('should render form slot content', () => {
+ expect(wrapper.find('input').exists()).toBe(true);
+ });
+
+ it('should update form data through slot inputs', async () => {
+ const nameInput = wrapper.find('input[type="text"]');
+ const ageInput = wrapper.find('input[type="number"]');
+
+ await nameInput.setValue('Updated Name');
+ await ageInput.setValue(25);
+
+ expect(formModel.value.formData.name).toBe('Updated Name');
+ expect(formModel.value.formData.age).toBe(25);
+ });
+
+ it('should render moreActions slot content', () => {
+ expect(wrapper.find('button').exists()).toBe(true);
+ });
+
+ it('should call custom action on button click', async () => {
+ const customActionSpy = cy.spy(formModel.value, 'customAction');
+ await wrapper.find('button').trigger('click');
+ expect(customActionSpy).to.have.been.called;
+ });*/
});
diff --git a/test/cypress/support/component.js b/test/cypress/support/component.js
index 65e1bc61d..6def6fb64 100644
--- a/test/cypress/support/component.js
+++ b/test/cypress/support/component.js
@@ -1,9 +1,13 @@
+import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-e2e-cypress';
import { createTestingPinia } from '@pinia/testing';
import { mount } from 'cypress/vue';
import { i18n } from 'src/boot/i18n';
import { Quasar } from 'quasar';
+import { createPinia } from 'pinia';
const pinia = createTestingPinia({ createSpy: () => {}, stubActions: false });
-
+import axios from 'axios';
+installQuasarPlugin({ plugins: { Dialog, Notify } });
+// setActivePinia(pinia);
// // Run this code before each *test*.
// beforeEach(() => {
// // New Pinia
@@ -13,10 +17,72 @@ const pinia = createTestingPinia({ createSpy: () => {}, stubActions: false });
// setActivePinia(pinia);
// });
-function createWrapper(component, options) {
+// Crear un comando personalizado para montar componentes con Pinia
+// Cypress.Commands.add('mountWithPinia', (component, options = {}) => {
+// const pinia = createPinia();
+// options.global = options.global || {};
+// options.global.plugins = [Quasar, createPinia()]; // Incluye Quasar y Pinia
+// return mount(component, options);
+// });
+
+// Registrar Quasar y sus componentes
+
+setActivePinia(createPinia()); // Ensure Pinia is active
+axios.defaults.baseURL = Cypress.env('baseUrl');
+Cypress.Commands.add('mount', (component, options = {}) => {
+ const pinia = createTestingPinia(options.piniaOptions);
+ const components = options.global?.components || {};
+ const router = createRouter({
+ history: createWebHistory(),
+ routes: [],
+ });
const defaultOptions = {
global: {
- plugins: [Quasar, i18n, pinia],
+ mocks: {
+ t: (tKey) => tKey,
+ $t: (tKey) => tKey,
+
+ $axios: axios, // Añadir axios como un mock global
+ },
+ plugins: [
+ Quasar,
+ (app) => {
+ app.use(router);
+ app.use(i18n);
+ app.use(pinia);
+ },
+ ], // Añade Quasar y Pinia como plugins globales
+ },
+ };
+ const mountOptions = Object.assign({}, defaultOptions, options);
+
+ if (options.global) {
+ mountOptions.global.plugins = defaultOptions.global.plugins;
+ }
+
+ return mount(component, mountOptions);
+
+ // options.global.plugins.push({
+ // install(app) {
+ // app.use(i18n);
+ // app.use(router);
+ // // app.use(arrayDataStore);
+ // },
+ // });
+ // const wrapper = mount(component, mountOptions);
+ // const { vm } = wrapper;
+ // return wrapper;
+});
+function createWrapper(component, options = {}) {
+ const defaultOptions = {
+ global: {
+ plugins: [
+ Quasar,
+ i18n,
+ createTestingPinia({
+ createSpy: () => cy.spy(),
+ }),
+ ],
stubs: [
'router-link',
'router-view',
@@ -36,9 +102,13 @@ function createWrapper(component, options) {
$t: (tKey) => tKey,
},
};
-
+ const arrayDataStore = useArrayDataStore();
const mountOptions = Object.assign({}, defaultOptions);
-
+ options.global = options?.global || {};
+ options.global.plugins = options.global?.plugins || [];
+ // options.global.plugins.push([Quasar, {}]);
+ // options.global.plugins.push([i18n]);
+ // options.global.plugins.push(createTestingPinia());
if (options instanceof Object) {
Object.assign(mountOptions, options);
@@ -57,8 +127,10 @@ function createWrapper(component, options) {
install(app) {
app.use(i18n);
app.use(options.router);
+ // app.use(arrayDataStore);
},
});
+
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;
@@ -77,8 +149,7 @@ Cypress.Commands.add('createWrapper', createWrapper);
Cypress.Commands.add('_vnMount', (component, options = {}) => {
const globalConfig = {
global: {
- stubs: ['router-view', 'vue-i18n'],
- plugins: [Quasar, i18n, pinia],
+ plugins: [Quasar, i18n],
mocks: { t: (key) => key },
},
};
@@ -115,6 +186,11 @@ Cypress.Commands.add('_vnMount', (component, options = {}) => {
import 'quasar/dist/quasar.css';
import { createRouter } from 'vue-router';
import { createMemoryHistory } from 'vue-router';
+import { setActivePinia } from 'pinia';
+import { useArrayDataStore } from 'src/stores/useArrayDataStore';
+import { createWebHistory } from 'vue-router';
+import { Dialog } from 'quasar';
+import { Notify } from 'quasar';
Cypress.Commands.add('vue', () => {
return cy.wrap(Cypress.vueWrapper);
});
@@ -152,3 +228,12 @@ Cypress.Commands.add('login', (user) => {
});
});
});
+
+// Define el comando personalizado
+Cypress.Commands.add('stubUseArrayDataStore', (stubData = {}) => {
+ const arrayDataStore = useArrayDataStore();
+ if (arrayDataStore.get.restore) {
+ arrayDataStore.get.restore();
+ }
+ cy.stub(arrayDataStore, 'get').returns(stubData).as('getStub');
+});