feat: refs #7220 ok

This commit is contained in:
Javier Segarra 2024-10-18 13:51:41 +02:00
parent 1d7e3f6119
commit 3a04fc5029
7 changed files with 242 additions and 60 deletions

View File

@ -1,4 +1,7 @@
const { defineConfig } = require('cypress');
const {
injectQuasarDevServerConfig,
} = require('@quasar/quasar-app-extension-testing-e2e-cypress/cct-dev-server');
module.exports = defineConfig({
e2e: {
@ -18,6 +21,11 @@ module.exports = defineConfig({
},
setupNodeEvents(on, config) {
// implement node event listeners here
on('after:spec', (results) => {
// `results` is the tests results
console.error('results: ', results);
cy.exec('cd ../salix && gulp docker');
});
},
},
@ -25,9 +33,14 @@ module.exports = defineConfig({
indexHtmlFile: 'test/cypress/support/component-index.html',
supportFile: 'test/cypress/support/component.js',
specPattern: 'test/cypress/components/**/*.spec.js',
devServer: {
framework: 'vue',
bundler: 'vite',
devServer: injectQuasarDevServerConfig(),
setupNodeEvents(on, config) {
// implement node event listeners here
on('after:spec', (results) => {
// `results` is the tests results
console.error('results: ', results);
cy.exec('cd ../salix && gulp docker');
});
},
},
});

View File

@ -87,6 +87,7 @@ module.exports = configure(function (/* ctx */) {
alias: {
composables: path.join(__dirname, './src/composables'),
filters: path.join(__dirname, './src/filters'),
components: path.join(__dirname, './src/components'),
},
vitePlugins: [

View File

@ -363,7 +363,7 @@ defineExpose({
<QInnerLoading
:showing="isLoading"
:label="t('globals.pleaseWait')"
:label="$t('globals.pleaseWait')"
color="primary"
style="min-width: 100%"
/>

View File

@ -5,11 +5,11 @@ import { useI18n } from 'vue-i18n';
import { useQuasar } from 'quasar';
import { useRoute } from 'vue-router';
import { useStateStore } from 'stores/useStateStore';
import { useArrayData } from 'src/composables/useArrayData';
import { useArrayData } from 'composables/useArrayData';
import { toDate, toCurrency, toPercentage } from 'filters/index';
import CrudModel from 'src/components/CrudModel.vue';
import FetchData from 'src/components/FetchData.vue';
import VnDiscount from 'src/components/common/vnDiscount.vue';
import CrudModel from 'components/CrudModel.vue';
import FetchData from 'components/FetchData.vue';
import VnDiscount from 'components/common/vnDiscount.vue';
import ClaimLinesImport from './ClaimLinesImport.vue';
import ItemDescriptorProxy from 'src/pages/Item/Card/ItemDescriptorProxy.vue';
@ -20,7 +20,7 @@ const { t } = useI18n();
const stateStore = useStateStore();
const arrayData = useArrayData('ClaimLines');
const store = arrayData.store;
const itemDescriptorProxy = ref(null);
const claimFilter = {
fields: ['ticketFk'],
};
@ -221,10 +221,12 @@ async function saveWhenHasChanges() {
</template>
<template #body-cell-description="{ row, value }">
<QTd auto-width align="right" class="text-primary">
{{ value }}
<ItemDescriptorProxy
:id="row.sale.itemFk"
></ItemDescriptorProxy>
<span
@click="() => {
itemProxyRef.show()
"
>{{ value }}</span
>
</QTd>
</template>
<template #body-cell-discount="{ row, value, rowIndex }">
@ -319,6 +321,10 @@ async function saveWhenHasChanges() {
<QPageSticky position="bottom-right" :offset="[25, 25]">
<QBtn fab color="primary" shortcut="+" icon="add" @click="showImportDialog()" />
</QPageSticky>
<ItemDescriptorProxy
ref="itemProxyRef"
v-model="itemDescriptorProxy"
></ItemDescriptorProxy>
</template>
<style lang="scss" scoped>
@ -332,7 +338,7 @@ async function saveWhenHasChanges() {
}
</style>
<i18n lang="yml">
<i18n>
en:
You are about to remove {count} rows: '
You are about to remove <strong>{count}</strong> row |

View File

@ -1,8 +1,83 @@
import axios from 'axios';
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 vueRouter from 'vue-router';
describe('<CreateBankEntityForm />', () => {
it('TODO: boilerplate', () => {
// see: https://on.cypress.io/mounting-vue
cy.createWrapper(CreateBankEntityForm);
const mockApiResponse = { results: [{ id: 1, name: 'Test' }] };
const arrayDataStore = useArrayDataStore();
const mockStoreData = { filter: {}, userFilter: {}, userParams: {}, url: 'mockUrl' };
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(arrayData).callsFake(() => ({
userParams: {},
userFilter: {},
order: {},
searchUrl: 'searchUrl',
}));
// cy.stub(vueRouter, 'useRouter').callsFake(() => ({
// push: () => {},
// replace: () => {},
// currentRoute: {
// value: {
// params: {
// id: 1,
// },
// meta: { moduleName: 'mockName' },
// matched: [{ path: 'mockName/list' }],
// },
// },
// }));
});
beforeEach(() => {
// Stub del método get del store
// cy.spy(useRouter(), 'replace');
// cy.spy(useRouter(), 'push');
});
it('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) => {
if (url === 'Countries') {
return Promise.resolve({ data: mockApiResponse });
}
// Si la URL no coincide, llama al método original
return axios.get.wrappedMethod(url, params);
})
.as('axiosStub');
const onFetchSpy = cy.spy().as('onFetchSpy');
cy.createWrapper(CreateBankEntityForm, {
props: {
showEntityField: true,
},
attrs: {
onFetch: onFetchSpy,
},
});
cy.get('@axiosStub').should((spy) => {
expect(spy).to.have.been.calledWith('Countries');
});
cy.get('@onFetchSpy').should((spy) => {
expect(spy).to.have.been.calledWith(mockApiResponse);
});
// Verifica que los datos emitidos por el hijo son manejados por el padre
// cy.get('p').should('contain', 'Datos recibidos:'); // Verifica que los datos se muestran en el DOM
// cy.get('p').should('contain', 'Test'); // Verifica que el contenido de los datos es correcto
});
});

View File

@ -1,63 +1,46 @@
import axios from 'axios';
import FetchData from 'src/components/FetchData.vue';
describe.only('<FetchData />', () => {
const mockApiResponse = { results: [{ id: 1, name: 'Test' }] };
it('TODO: boilerplate', () => {
const url = '/api/Schemas/modelinfo';
it('Autoload: true', () => {
// see: https://on.cypress.io/mounting-vue
let _wrapper = null;
cy.stub(axios, 'get').resolves({ data: mockApiResponse }).as('axiosStub');
const onFetchSpy = cy.spy().as('onFetchSpy');
cy.createWrapper(FetchData, {
props: {
autoLoad: true,
url: 'http://localhost:9000/api/Schemas/modelinfo',
url,
},
emits: { onFetch: onFetchSpy },
});
cy.get('@onFetchSpy').should('have.been.called');
// Intercepta la petición de axios para simular una respuesta
// cy.intercept('http://localhost:9000/api/Schemas/modelinfo', {
// statusCode: 200,
// body: mockApiResponse,
// }).as('dataFetched'); // Alias para poder esperar en el test
// Verifica que la petición fue realizada automáticamente y la data es correcta
// cy.wait('@dataFetched').then(({ request, response }) => {
// expect(response.body).to.deep.equal(mockApiResponse); // Verifica la respuesta
// });
// debugger;
// Verifica que el evento onFetch fue emitido con los datos correctos
cy.get('@axiosStub').should((spy) => {
expect(spy).to.have.been.calledWith('/api/Schemas/modelinfo');
const [url, params] = spy.getCall(0).args;
expect(url).to.equal('/api/Schemas/modelinfo');
expect(params).to.deep.equal({
params: {
filter: '{}',
},
});
});
/*cy.get('@onFetchSpy').should('have.been.calledWith', mockApiResponse);*/
cy.get('@onFetchSpy').should((spy) => {
expect(spy).to.have.been.calledWith(mockApiResponse);
});
});
xit('TODO: boilerplate2', () => {
it('Autoload: false', () => {
// see: https://on.cypress.io/mounting-vue
cy.stub(axios, 'get').resolves({ data: mockApiResponse }).as('axiosStub');
const onFetchSpy = cy.spy().as('onFetchSpy');
cy.createWrapper(FetchData, {
props: {
autoLoad: false,
url: '/api/test-url', // La URL que va a usar en el fetch
url,
},
emits: { onFetch: onFetchSpy },
});
// Intercepta la petición de axios para simular una respuesta
cy.intercept('GET', '**/api/test-url', {
statusCode: 200,
body: mockApiResponse,
}).as('fetchData'); // Alias para poder esperar en el test
// Verifica que no se hizo ninguna petición al montar el componente
cy.get('@fetchDataManual').should('not.exist');
// Llama manualmente al método fetch desde el componente expuesto
cy.window().then((win) => {
win.$vm.fetch(); // Llama al método fetch
});
// Verifica que la petición se ejecutó manualmente y la data es correcta
cy.wait('@fetchDataManual').then(({ request, response }) => {
expect(response.body).to.deep.equal(mockApiResponse);
});
// Verifica que el evento onFetch fue emitido con los datos correctos
cy.wrap(Cypress.vueWrapper.emitted('onFetch')[0][0]).should(
'deep.equal',
mockApiResponse
);
cy.get('@onFetchSpy').should('not.to.have.been.called');
});
});

View File

@ -17,6 +17,19 @@ function createWrapper(component, options) {
const defaultOptions = {
global: {
plugins: [Quasar, i18n, pinia],
stubs: [
'router-link',
'router-view',
'vue-router',
'vnPaginate',
'useState',
'arrayData',
'arrayDataStore',
'useArrayData',
'useArrayDataStore',
'useStateStore',
'vue-i18n',
],
},
mocks: {
t: (tKey) => tKey,
@ -33,7 +46,19 @@ function createWrapper(component, options) {
mountOptions.global.plugins = defaultOptions.global.plugins;
}
}
// create router if one is not provided
if (!options.router) {
options.router = createRouter({
routes: [],
history: createMemoryHistory(),
});
}
mountOptions.global.plugins.push({
install(app) {
app.use(i18n);
app.use(options.router);
},
});
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;
@ -48,3 +73,82 @@ function createWrapper(component, options) {
// }
Cypress.Commands.add('createWrapper', createWrapper);
Cypress.Commands.add('_vnMount', (component, options = {}) => {
const globalConfig = {
global: {
stubs: ['router-view', 'vue-i18n'],
plugins: [Quasar, i18n, pinia],
mocks: { t: (key) => key },
},
};
options.global = options.global || {};
// options.global.stubs = options.global.stubs || {};
// options.global.stubs.transition = false;
// options.global.components = options.global.components || {};
options.global.plugins = options.global.plugins || [];
// Use store passed in from options, or initialize a new one
// const { /* store = getStore(), */ ...mountOptions } = options;
// Add plugins here
options.global.plugins.push({
install(app) {
app.use(i18n);
},
});
// Spy para capturar el evento onFetch
// Agregar el spy a los atributos del componente
const finalOptions = {
...globalConfig,
...options,
attrs: {
...options.attrs,
},
};
console.log(finalOptions);
const cmp = mount(component, finalOptions);
return cmp;
});
import 'quasar/dist/quasar.css';
import { createRouter } from 'vue-router';
import { createMemoryHistory } from 'vue-router';
Cypress.Commands.add('vue', () => {
return cy.wrap(Cypress.vueWrapper);
});
Cypress.Commands.add('_mount', (component, options) => {
// Wrap any parent components needed
// ie: return mount(<MyProvider>{component}</MyProvider>, options)
options.global = options.global || {};
options.global.plugins = options.global.plugins || [];
options.global.plugins.push([Quasar, {}]);
options.global.plugins.push([i18n]);
return mount(component, options);
});
Cypress.Commands.add('login', (user) => {
//cy.visit('/#/login');
cy.request({
method: 'POST',
url: 'http://localhost:9000/api/accounts/login',
body: {
user: user,
password: 'nightmare',
},
}).then((response) => {
window.localStorage.setItem('token', response.body.token);
cy.request({
method: 'GET',
url: 'http://localhost:9000/api/VnUsers/ShareToken',
headers: {
Authorization: window.localStorage.getItem('token'),
},
}).then(({ body }) => {
window.localStorage.setItem('tokenMultimedia', body.multimediaToken.id);
});
});
});