#8647 fix vitest warnings #1467

Merged
jon merged 91 commits from 8647_fix_warnings into dev 2025-04-16 11:18:11 +00:00
63 changed files with 400 additions and 358 deletions

View File

@ -67,7 +67,7 @@ describe('Axios boot', () => {
}; };
const result = onResponseError(error); const result = onResponseError(error);
expect(result).rejects.toEqual(expect.objectContaining(error)); await expect(result).rejects.toEqual(expect.objectContaining(error));
}); });
it('should call to the Notify plugin with a message from the response property', async () => { it('should call to the Notify plugin with a message from the response property', async () => {
@ -83,7 +83,7 @@ describe('Axios boot', () => {
}; };
const result = onResponseError(error); const result = onResponseError(error);
expect(result).rejects.toEqual(expect.objectContaining(error)); await expect(result).rejects.toEqual(expect.objectContaining(error));
}); });
}); });
}); });

View File

@ -20,7 +20,6 @@ const postcodeFormData = reactive({
provinceFk: null, provinceFk: null,
townFk: null, townFk: null,
}); });
const townFilter = ref({});
const countriesRef = ref(false); const countriesRef = ref(false);
const provincesOptions = ref([]); const provincesOptions = ref([]);
@ -33,11 +32,11 @@ function onDataSaved(formData) {
newPostcode.town = town.value.name; newPostcode.town = town.value.name;
newPostcode.townFk = town.value.id; newPostcode.townFk = town.value.id;
const provinceObject = provincesOptions.value.find( const provinceObject = provincesOptions.value.find(
({ id }) => id === formData.provinceFk ({ id }) => id === formData.provinceFk,
); );
newPostcode.province = provinceObject?.name; newPostcode.province = provinceObject?.name;
const countryObject = countriesRef.value.opts.find( const countryObject = countriesRef.value.opts.find(
({ id }) => id === formData.countryFk ({ id }) => id === formData.countryFk,
); );
newPostcode.country = countryObject?.name; newPostcode.country = countryObject?.name;
emit('onDataSaved', newPostcode); emit('onDataSaved', newPostcode);
@ -67,21 +66,11 @@ function setTown(newTown, data) {
} }
async function onCityCreated(newTown, formData) { async function onCityCreated(newTown, formData) {
newTown.province = provincesOptions.value.find( newTown.province = provincesOptions.value.find(
(province) => province.id === newTown.provinceFk (province) => province.id === newTown.provinceFk,
); );
formData.townFk = newTown; formData.townFk = newTown;
setTown(newTown, formData); setTown(newTown, formData);
} }
async function filterTowns(name) {
if (name !== '') {
townFilter.value.where = {
name: {
like: `%${name}%`,
},
};
}
}
</script> </script>
<template> <template>
@ -107,7 +96,6 @@ async function filterTowns(name) {
<VnSelectDialog <VnSelectDialog
:label="t('City')" :label="t('City')"
@update:model-value="(value) => setTown(value, data)" @update:model-value="(value) => setTown(value, data)"
@filter="filterTowns"
:tooltip="t('Create city')" :tooltip="t('Create city')"
v-model="data.townFk" v-model="data.townFk"
url="Towns/location" url="Towns/location"

View File

@ -65,7 +65,7 @@ const $props = defineProps({
default: null, default: null,
}, },
beforeSaveFn: { beforeSaveFn: {
type: Function, type: [String, Function],
jsegarra marked this conversation as resolved
Review

Hay que mirar quien le esta pasando un String, no aceptarlo

Hay que mirar quien le esta pasando un String, no aceptarlo
default: null, default: null,
}, },
goTo: { goTo: {

View File

@ -22,7 +22,6 @@ const { validate, validations } = useValidator();
const { notify } = useNotify(); const { notify } = useNotify();
const route = useRoute(); const route = useRoute();
const myForm = ref(null); const myForm = ref(null);
const attrs = useAttrs();
const $props = defineProps({ const $props = defineProps({
url: { url: {
type: String, type: String,
@ -99,8 +98,12 @@ const $props = defineProps({
type: Function, type: Function,
default: () => {}, default: () => {},
}, },
preventSubmit: {
type: Boolean,
default: true,
},
}); });
const emit = defineEmits(['onFetch', 'onDataSaved']); const emit = defineEmits(['onFetch', 'onDataSaved', 'submit']);
const modelValue = computed( const modelValue = computed(
() => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`, () => $props.model ?? `formModel_${route?.meta?.title ?? route.name}`,
).value; ).value;
@ -301,7 +304,7 @@ function onBeforeSave(formData, originalData) {
); );
} }
async function onKeyup(evt) { async function onKeyup(evt) {
if (evt.key === 'Enter' && !('prevent-submit' in attrs)) { if (evt.key === 'Enter' && !$props.preventSubmit) {
const input = evt.target; const input = evt.target;
if (input.type == 'textarea' && evt.shiftKey) { if (input.type == 'textarea' && evt.shiftKey) {
let { selectionStart, selectionEnd } = input; let { selectionStart, selectionEnd } = input;
@ -330,6 +333,7 @@ defineExpose({
<template> <template>
<div class="column items-center full-width"> <div class="column items-center full-width">
<QForm <QForm
v-on="$attrs"
ref="myForm" ref="myForm"
v-if="formData" v-if="formData"
@submit.prevent="save" @submit.prevent="save"

View File

@ -181,7 +181,7 @@ const searchModule = () => {
<template> <template>
<QList padding class="column-max-width"> <QList padding class="column-max-width">
<template v-if="$props.source === 'main'"> <template v-if="$props.source === 'main'">
<template v-if="$route?.matched[1]?.name === 'Dashboard'"> <template v-if="route?.matched[1]?.name === 'Dashboard'">
<QItem class="q-pb-md"> <QItem class="q-pb-md">
<VnInput <VnInput
v-model="search" v-model="search"
@ -262,7 +262,7 @@ const searchModule = () => {
</template> </template>
<template v-for="item in items" :key="item.name"> <template v-for="item in items" :key="item.name">
<template v-if="item.name === $route?.matched[1]?.name"> <template v-if="item.name === route?.matched[1]?.name">
<QItem class="header"> <QItem class="header">
<QItemSection avatar v-if="item.icon"> <QItemSection avatar v-if="item.icon">
<QIcon :name="item.icon" /> <QIcon :name="item.icon" />

View File

@ -16,7 +16,7 @@ const $props = defineProps({
required: true, required: true,
}, },
searchUrl: { searchUrl: {
type: String, type: [String, Boolean],
default: 'table', default: 'table',
}, },
vertical: { vertical: {

View File

@ -66,7 +66,7 @@ const $props = defineProps({
default: null, default: null,
}, },
create: { create: {
type: Object, type: [Boolean, Object],
default: null, default: null,
}, },
createAsDialog: { createAsDialog: {

View File

@ -30,6 +30,7 @@ function columnName(col) {
v-bind="$attrs" v-bind="$attrs"
:search-button="true" :search-button="true"
:disable-submit-event="true" :disable-submit-event="true"
:data-key="$attrs['data-key']"
Outdated
Review

Ja pasa con el v-bind no?

Ja pasa con el v-bind no?

comor?

comor?
:search-url :search-url
> >
<template #body="{ params, orders, searchFn }"> <template #body="{ params, orders, searchFn }">

View File

@ -58,7 +58,7 @@ async function getConfig(url, filter) {
const response = await axios.get(url, { const response = await axios.get(url, {
params: { filter: filter }, params: { filter: filter },
}); });
return response.data && response.data.length > 0 ? response.data[0] : null; return response?.data && response?.data?.length > 0 ? response.data[0] : null;
} }
async function fetchViewConfigData() { async function fetchViewConfigData() {

View File

@ -11,6 +11,9 @@ describe('VnTable', () => {
propsData: { propsData: {
columns: [], columns: [],
}, },
attrs: {
'data-key': 'test',
},
}); });
vm = wrapper.vm; vm = wrapper.vm;

View File

@ -11,13 +11,7 @@ describe('CrudModel', () => {
beforeAll(() => { beforeAll(() => {
wrapper = createWrapper(CrudModel, { wrapper = createWrapper(CrudModel, {
global: { global: {
stubs: [ stubs: ['vnPaginate', 'vue-i18n'],
'vnPaginate',
'useState',
'arrayData',
'useStateStore',
'vue-i18n',
],
mocks: { mocks: {
validate: vi.fn(), validate: vi.fn(),
}, },
@ -29,7 +23,7 @@ describe('CrudModel', () => {
dataKey: 'crudModelKey', dataKey: 'crudModelKey',
model: 'crudModel', model: 'crudModel',
Outdated
Review

Esto hay que repetirlo siempre?

Esto hay que repetirlo siempre?

No, solo cuando defines un createWrapper y le pasas un objeto global

No, solo cuando defines un createWrapper y le pasas un objeto global

Voy a darle una vuelta para hacer algo asi Object.assign(defaultOptions, options)

Voy a darle una vuelta para hacer algo asi `Object.assign(defaultOptions, options)`
url: 'crudModelUrl', url: 'crudModelUrl',
saveFn: '', saveFn: vi.fn(),
Review

undefined?

undefined?
Review

Esto es parte de lo que hizo @jsegarra

Esto es parte de lo que hizo @jsegarra
Review

no entiendo la pregunta.
Se modificó esta prop porque habia un warning y por tanto el test también

no entiendo la pregunta. Se modificó esta prop porque habia un warning y por tanto el test también
}, },
}); });
wrapper = wrapper.wrapper; wrapper = wrapper.wrapper;
@ -231,7 +225,7 @@ describe('CrudModel', () => {
expect(vm.isLoading).toBe(false); expect(vm.isLoading).toBe(false);
expect(vm.hasChanges).toBe(false); expect(vm.hasChanges).toBe(false);
await wrapper.setProps({ saveFn: '' }); await wrapper.setProps({ saveFn: null });
}); });
it("should use default url if there's not saveFn", async () => { it("should use default url if there's not saveFn", async () => {

View File

@ -170,7 +170,7 @@ describe('LeftMenu as card', () => {
vm = mount('card').vm; vm = mount('card').vm;
}); });
it('should get routes for card source', async () => { it('should get routes for card source', () => {
vm.getRoutes(); vm.getRoutes();
}); });
}); });
@ -251,7 +251,6 @@ describe('LeftMenu as main', () => {
}); });
it('should get routes for main source', () => { it('should get routes for main source', () => {
vm.props.source = 'main';
vm.getRoutes(); vm.getRoutes();
expect(navigation.getModules).toHaveBeenCalled(); expect(navigation.getModules).toHaveBeenCalled();
}); });

View File

@ -1,5 +1,5 @@
<script setup> <script setup>
const model = defineModel({ type: [String, Number], required: true }); const model = defineModel({ type: [String, Number], default: '' });
jorgep marked this conversation as resolved
Review

Siempre tiene que haber un v-model

Siempre tiene que haber un v-model
Review

Voy a revisar, pero no me suena haber cambiado esto

Voy a revisar, pero no me suena haber cambiado esto
Review
@jorgep
Review

Y siempre lo hay, pero con ese valor. Al usar un VnInputDate el valor por defecto era undefined y saltaba un warning

Y siempre lo hay, pero con ese valor. Al usar un VnInputDate el valor por defecto era undefined y saltaba un warning
</script> </script>
<template> <template>
<QDate v-model="model" :today-btn="true" :options="$attrs.options" /> <QDate v-model="model" :today-btn="true" :options="$attrs.options" />

View File

@ -61,8 +61,11 @@ function onFileChange(files) {
function mapperDms(data) { function mapperDms(data) {
const formData = new FormData(); const formData = new FormData();
const { files } = data; let files = data.files;
if (files) formData.append(files?.name, files); if (files) {
files = Array.isArray(files) ? files : [files];
files.forEach((file) => formData.append(file?.name, file));
}
const dms = { const dms = {
hasFile: !!data.hasFile, hasFile: !!data.hasFile,

View File

@ -5,7 +5,7 @@ import VnDate from './VnDate.vue';
import VnTime from './VnTime.vue'; import VnTime from './VnTime.vue';
const $attrs = useAttrs(); const $attrs = useAttrs();
const model = defineModel({ type: [Date] }); const model = defineModel({ type: [Date, String] });
const $props = defineProps({ const $props = defineProps({
isOutlined: { isOutlined: {
@ -29,7 +29,7 @@ const styleAttrs = computed(() => {
const mask = 'DD-MM-YYYY HH:mm'; const mask = 'DD-MM-YYYY HH:mm';
const selectedDate = computed({ const selectedDate = computed({
get() { get() {
if (!model.value) return new Date(model.value); if (!model.value) return JSON.stringify(new Date(model.value));
return date.formatDate(new Date(model.value), mask); return date.formatDate(new Date(model.value), mask);
}, },
set(value) { set(value) {

View File

@ -54,6 +54,10 @@ const $props = defineProps({
type: [Array], type: [Array],
default: () => [], default: () => [],
}, },
filterFn: {
type: Function,
default: null,
},
exprBuilder: { exprBuilder: {
type: Function, type: Function,
default: null, default: null,
@ -62,16 +66,12 @@ const $props = defineProps({
type: Boolean, type: Boolean,
default: true, default: true,
}, },
defaultFilter: {
type: Boolean,
default: true,
},
fields: { fields: {
type: Array, type: Array,
default: null, default: null,
}, },
include: { include: {
type: [Object, Array], type: [Object, Array, String],
default: null, default: null,
}, },
where: { where: {
@ -79,7 +79,7 @@ const $props = defineProps({
default: null, default: null,
}, },
sortBy: { sortBy: {
type: String, type: [String, Array],
default: null, default: null,
}, },
limit: { limit: {
@ -152,10 +152,22 @@ const value = computed({
}, },
}); });
const arrayDataKey =
$props.dataKey ??
($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
const arrayData = useArrayData(arrayDataKey, {
url: $props.url,
searchUrl: false,
mapKey: $attrs['map-key'],
});
const computedSortBy = computed(() => { const computedSortBy = computed(() => {
return $props.sortBy || $props.optionLabel + ' ASC'; return $props.sortBy || $props.optionLabel + ' ASC';
}); });
const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
watch(options, (newValue) => { watch(options, (newValue) => {
setOptions(newValue); setOptions(newValue);
}); });
@ -174,16 +186,6 @@ onMounted(() => {
if ($props.focusOnMount) setTimeout(() => vnSelectRef.value.showPopup(), 300); if ($props.focusOnMount) setTimeout(() => vnSelectRef.value.showPopup(), 300);
}); });
const arrayDataKey =
$props.dataKey ??
($props.url?.length > 0 ? $props.url : ($attrs.name ?? $attrs.label));
const arrayData = useArrayData(arrayDataKey, {
url: $props.url,
searchUrl: false,
mapKey: $attrs['map-key'],
});
function findKeyInOptions() { function findKeyInOptions() {
if (!$props.options) return; if (!$props.options) return;
return filter($props.modelValue, $props.options)?.length; return filter($props.modelValue, $props.options)?.length;
@ -252,43 +254,41 @@ async function fetchFilter(val) {
} }
Outdated
Review

@jorgep esto cambia?

@jorgep esto cambia?

Lo he probado y funciona como antes, pruebalo si quieres por si acaso.

Lo he probado y funciona como antes, pruebalo si quieres por si acaso.
async function filterHandler(val, update) { async function filterHandler(val, update) {
if (isLoading.value) return update();
if (!val && lastVal.value === val) {
lastVal.value = val;
return update();
}
lastVal.value = val;
let newOptions; let newOptions;
if (!$props.defaultFilter) return update(); if ($props.filterFn) update($props.filterFn(val));
if ( else if (!val && lastVal.value === val) update();
$props.url && else {
($props.limit || (!$props.limit && Object.keys(myOptions.value).length === 0)) const makeRequest =
) { ($props.url && $props.limit) ||
newOptions = await fetchFilter(val); (!$props.limit && Object.keys(myOptions.value).length === 0);
} else newOptions = filter(val, myOptionsOriginal.value); newOptions = makeRequest
update( ? await fetchFilter(val)
() => { : filter(val, myOptionsOriginal.value);
if ($props.noOne && noOneText.toLowerCase().includes(val.toLowerCase()))
newOptions.unshift(noOneOpt.value);
myOptions.value = newOptions; update(
}, () => {
(ref) => { if ($props.noOne && noOneText.toLowerCase().includes(val.toLowerCase()))
if (val !== '' && ref.options.length > 0) { newOptions.unshift(noOneOpt.value);
ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true); myOptions.value = newOptions;
} },
}, (ref) => {
); if (val !== '' && ref.options.length > 0) {
ref.setOptionIndex(-1);
ref.moveOptionSelection(1, true);
}
},
);
}
lastVal.value = val;
} }
function nullishToTrue(value) { function nullishToTrue(value) {
return value ?? true; return value ?? true;
} }
const getVal = (val) => ($props.useLike ? { like: `%${val}%` } : val);
async function onScroll({ to, direction, from, index }) { async function onScroll({ to, direction, from, index }) {
const lastIndex = myOptions.value.length - 1; const lastIndex = myOptions.value.length - 1;

View File

@ -12,7 +12,9 @@ describe('VnDiscount', () => {
price: 100, price: 100,
quantity: 2, quantity: 2,
discount: 10, discount: 10,
} mana: 10,
promise: vi.fn(),
},
}).vm; }).vm;
}); });

View File

@ -41,10 +41,12 @@ describe('VnDms', () => {
companyFk: 2, companyFk: 2,
dmsTypeFk: 3, dmsTypeFk: 3,
description: 'This is a test description', description: 'This is a test description',
files: { files: [
name: 'example.txt', {
content: new Blob(['file content'], { type: 'text/plain' }), name: 'example.txt',
}, content: new Blob(['file content'], { type: 'text/plain' }),
},
],
}; };
const expectedBody = { const expectedBody = {
@ -83,7 +85,7 @@ describe('VnDms', () => {
it('should map DMS data correctly and add file to FormData', () => { it('should map DMS data correctly and add file to FormData', () => {
const [formData, params] = vm.mapperDms(data); const [formData, params] = vm.mapperDms(data);
expect(formData.get('example.txt')).toBe(data.files); expect([formData.get('example.txt')]).toStrictEqual(data.files);
expect(expectedBody).toEqual(params.params); expect(expectedBody).toEqual(params.params);
}); });

View File

@ -2,7 +2,6 @@ import { createWrapper } from 'app/test/vitest/helper';
import { vi, describe, expect, it } from 'vitest'; import { vi, describe, expect, it } from 'vitest';
import VnInput from 'src/components/common/VnInput.vue'; import VnInput from 'src/components/common/VnInput.vue';
describe('VnInput', () => { describe('VnInput', () => {
let vm; let vm;
let wrapper; let wrapper;
@ -12,25 +11,27 @@ describe('VnInput', () => {
wrapper = createWrapper(VnInput, { wrapper = createWrapper(VnInput, {
props: { props: {
modelValue: value, modelValue: value,
isOutlined, emptyToNull, insertable, isOutlined,
maxlength: 101 emptyToNull,
insertable,
maxlength: 101,
}, },
attrs: { attrs: {
label: 'test', label: 'test',
required: true, required: true,
maxlength: 101, maxlength: 101,
maxLength: 10, maxLength: 10,
'max-length':20 'max-length': 20,
}, },
}); });
wrapper = wrapper.wrapper; wrapper = wrapper.wrapper;
vm = wrapper.vm; vm = wrapper.vm;
input = wrapper.find('[data-cy="test_input"]'); input = wrapper.find('[data-cy="test_input"]');
}; }
describe('value', () => { describe('value', () => {
it('should emit update:modelValue when value changes', async () => { it('should emit update:modelValue when value changes', async () => {
generateWrapper('12345', false, false, true) generateWrapper('12345', false, false, true);
await input.setValue('123'); await input.setValue('123');
expect(wrapper.emitted('update:modelValue')).toBeTruthy(); expect(wrapper.emitted('update:modelValue')).toBeTruthy();
expect(wrapper.emitted('update:modelValue')[0]).toEqual(['123']); expect(wrapper.emitted('update:modelValue')[0]).toEqual(['123']);
@ -62,7 +63,6 @@ describe('VnInput', () => {
expect(wrapper.emitted('update:modelValue')).toBeUndefined(); expect(wrapper.emitted('update:modelValue')).toBeUndefined();
const spyhandler = vi.spyOn(vm, 'handleInsertMode'); const spyhandler = vi.spyOn(vm, 'handleInsertMode');
expect(spyhandler).not.toHaveBeenCalled(); expect(spyhandler).not.toHaveBeenCalled();
}); });
/* /*
@ -71,12 +71,12 @@ describe('VnInput', () => {
it.skip('handleKeydown respects insertable behavior', async () => { it.skip('handleKeydown respects insertable behavior', async () => {
const expectedValue = '12345'; const expectedValue = '12345';
generateWrapper('1234', false, false, true); generateWrapper('1234', false, false, true);
vm.focus() vm.focus();
await input.trigger('keydown', { key: '5' }); await input.trigger('keydown', { key: '5' });
await vm.$nextTick(); await vm.$nextTick();
expect(wrapper.emitted('update:modelValue')).toBeTruthy(); expect(wrapper.emitted('update:modelValue')).toBeTruthy();
expect(wrapper.emitted('update:modelValue')[0]).toEqual([expectedValue ]); expect(wrapper.emitted('update:modelValue')[0]).toEqual([expectedValue]);
expect(vm.value).toBe( expectedValue); expect(vm.value).toBe(expectedValue);
}); });
}); });

View File

@ -33,7 +33,7 @@ describe('VnInputDateTime', () => {
it('handles null date value', async () => { it('handles null date value', async () => {
generateWrapper(null, false, true); generateWrapper(null, false, true);
await vm.$nextTick(); await vm.$nextTick();
expect(vm.selectedDate).toBeInstanceOf(Date); expect(vm.selectedDate).not.toBe(null);
}); });
it('updates the model value when a new datetime is set', async () => { it('updates the model value when a new datetime is set', async () => {

View File

@ -90,8 +90,10 @@ describe('VnLog', () => {
vm = createWrapper(VnLog, { vm = createWrapper(VnLog, {
global: { global: {
stubs: [], stubs: ['FetchData', 'vue-i18n'],
mocks: {}, mocks: {
fetch: vi.fn(),
},
}, },
propsData: { propsData: {
model: 'Claim', model: 'Claim',

View File

@ -26,7 +26,7 @@ describe('VnNotes', () => {
) { ) {
vi.spyOn(axios, 'get').mockResolvedValue({ data: [] }); vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
wrapper = createWrapper(VnNotes, { wrapper = createWrapper(VnNotes, {
propsData: options, propsData: { ...defaultOptions, ...options },
}); });
wrapper = wrapper.wrapper; wrapper = wrapper.wrapper;
vm = wrapper.vm; vm = wrapper.vm;

View File

@ -2,7 +2,9 @@
import { onBeforeUnmount, onMounted, ref, watch } from 'vue'; import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
import { useI18n } from 'vue-i18n'; import { useI18n } from 'vue-i18n';
import { useArrayData } from 'composables/useArrayData'; import { useArrayData } from 'composables/useArrayData';
import { useAttrs } from 'vue';
const attrs = useAttrs();
const { t } = useI18n(); const { t } = useI18n();
const props = defineProps({ const props = defineProps({
@ -67,7 +69,7 @@ const props = defineProps({
default: null, default: null,
}, },
searchUrl: { searchUrl: {
type: String, type: [String, Boolean],
default: null, default: null,
}, },
disableInfiniteScroll: { disableInfiniteScroll: {
@ -75,7 +77,7 @@ const props = defineProps({
default: false, default: false,
}, },
mapKey: { mapKey: {
type: String, type: [String, Boolean],
default: '', default: '',
}, },
keyData: { keyData: {
@ -220,7 +222,7 @@ defineExpose({
</script> </script>
<template> <template>
<div class="full-width"> <div class="full-width" v-bind="attrs">
<div <div
v-if="!store.data && !store.data?.length && !isLoading" v-if="!store.data && !store.data?.length && !isLoading"
class="info-row q-pa-md text-center" class="info-row q-pa-md text-center"

View File

@ -46,7 +46,7 @@ const props = defineProps({
default: null, default: null,
}, },
order: { order: {
type: String, type: [String, Array],
default: '', default: '',
}, },
limit: { limit: {

View File

@ -23,10 +23,15 @@ describe('CardSummary', () => {
beforeEach(() => { beforeEach(() => {
wrapper = createWrapper(CardSummary, { wrapper = createWrapper(CardSummary, {
global: {
mocks: {
validate: vi.fn(),
},
},
propsData: { propsData: {
dataKey: 'cardSummaryKey', dataKey: 'cardSummaryKey',
url: 'cardSummaryUrl', url: 'cardSummaryUrl',
filter: 'cardFilter', filter: { key: 'cardFilter' },
}, },
}); });
vm = wrapper.vm; vm = wrapper.vm;
@ -50,7 +55,7 @@ describe('CardSummary', () => {
it('should set correct props to the store', () => { it('should set correct props to the store', () => {
expect(vm.store.url).toEqual('cardSummaryUrl'); expect(vm.store.url).toEqual('cardSummaryUrl');
expect(vm.store.filter).toEqual('cardFilter'); expect(vm.store.filter).toEqual({ key: 'cardFilter' });
}); });
it('should respond to prop changes and refetch data', async () => { it('should respond to prop changes and refetch data', async () => {

View File

@ -7,7 +7,7 @@ describe('VnSearchbar', () => {
let wrapper; let wrapper;
let applyFilterSpy; let applyFilterSpy;
const searchText = 'Bolas de madera'; const searchText = 'Bolas de madera';
const userParams = {staticKey: 'staticValue'}; const userParams = { staticKey: 'staticValue' };
beforeEach(async () => { beforeEach(async () => {
wrapper = createWrapper(VnSearchbar, { wrapper = createWrapper(VnSearchbar, {
@ -23,8 +23,9 @@ describe('VnSearchbar', () => {
vm.searchText = searchText; vm.searchText = searchText;
vm.arrayData.store.userParams = userParams; vm.arrayData.store.userParams = userParams;
applyFilterSpy = vi.spyOn(vm.arrayData, 'applyFilter').mockImplementation(() => {}); applyFilterSpy = vi
.spyOn(vm.arrayData, 'applyFilter')
.mockImplementation(() => {});
}); });
afterEach(() => { afterEach(() => {
@ -32,7 +33,9 @@ describe('VnSearchbar', () => {
}); });
it('search resets pagination and applies filter', async () => { it('search resets pagination and applies filter', async () => {
const resetPaginationSpy = vi.spyOn(vm.arrayData, 'resetPagination').mockImplementation(() => {}); const resetPaginationSpy = vi
.spyOn(vm.arrayData, 'resetPagination')
.mockImplementation(() => {});
await vm.search(); await vm.search();
expect(resetPaginationSpy).toHaveBeenCalled(); expect(resetPaginationSpy).toHaveBeenCalled();
@ -48,7 +51,7 @@ describe('VnSearchbar', () => {
expect(applyFilterSpy).toHaveBeenCalledWith({ expect(applyFilterSpy).toHaveBeenCalledWith({
params: { staticKey: 'staticValue', search: searchText }, params: { staticKey: 'staticValue', search: searchText },
filter: {skip: 0}, filter: { skip: 0 },
}); });
}); });

View File

@ -1,5 +1,4 @@
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest'; import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import axios from 'axios';
import { createWrapper } from 'app/test/vitest/helper'; import { createWrapper } from 'app/test/vitest/helper';
import VnSms from 'src/components/ui/VnSms.vue'; import VnSms from 'src/components/ui/VnSms.vue';
@ -12,6 +11,9 @@ describe('VnSms', () => {
stubs: ['VnPaginate'], stubs: ['VnPaginate'],
mocks: {}, mocks: {},
}, },
propsData: {
url: 'SmsUrl',
},
}).vm; }).vm;
}); });

View File

@ -4,6 +4,8 @@ import { useArrayData } from 'composables/useArrayData';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import * as vueRouter from 'vue-router'; import * as vueRouter from 'vue-router';
import { setActivePinia, createPinia } from 'pinia'; import { setActivePinia, createPinia } from 'pinia';
import { defineComponent, h } from 'vue';
import { mount } from '@vue/test-utils';
describe('useArrayData', () => { describe('useArrayData', () => {
const filter = '{"limit":20,"skip":0}'; const filter = '{"limit":20,"skip":0}';
@ -43,7 +45,7 @@ describe('useArrayData', () => {
it('should fetch and replace url with new params', async () => { it('should fetch and replace url with new params', async () => {
vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: [] }); vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: [] });
const arrayData = useArrayData('ArrayData', { const arrayData = mountArrayData('ArrayData', {
url: 'mockUrl', url: 'mockUrl',
searchUrl: 'params', searchUrl: 'params',
}); });
@ -72,7 +74,7 @@ describe('useArrayData', () => {
data: [{ id: 1 }], data: [{ id: 1 }],
}); });
const arrayData = useArrayData('ArrayData', { const arrayData = mountArrayData('ArrayData', {
url: 'mockUrl', url: 'mockUrl',
navigate: {}, navigate: {},
}); });
@ -94,7 +96,7 @@ describe('useArrayData', () => {
], ],
}); });
const arrayData = useArrayData('ArrayData', { const arrayData = mountArrayData('ArrayData', {
url: 'mockUrl', url: 'mockUrl',
oneRecord: true, oneRecord: true,
}); });
@ -107,3 +109,17 @@ describe('useArrayData', () => {
}); });
}); });
}); });
function mountArrayData(...args) {
let arrayData;
const TestComponent = defineComponent({
setup() {
arrayData = useArrayData(...args);
return () => h('div');
},
});
const asd = mount(TestComponent);
return arrayData;
}

View File

@ -64,88 +64,84 @@ describe('session', () => {
}); });
}); });
describe( describe('login', () => {
'login', const expectedUser = {
() => { id: 999,
const expectedUser = { name: `T'Challa`,
id: 999, nickname: 'Black Panther',
name: `T'Challa`, lang: 'en',
nickname: 'Black Panther', userConfig: {
lang: 'en', darkMode: false,
userConfig: { },
darkMode: false, worker: { department: { departmentFk: 155 } },
};
const rolesData = [
{
role: {
name: 'salesPerson',
}, },
worker: { department: { departmentFk: 155 } }, },
}; {
const rolesData = [ role: {
{ name: 'admin',
role: {
name: 'salesPerson',
},
}, },
{ },
role: { ];
name: 'admin', beforeEach(() => {
}, vi.spyOn(axios, 'get').mockImplementation((url) => {
}, if (url === 'VnUsers/acls') return Promise.resolve({ data: [] });
]; return Promise.resolve({
beforeEach(() => { data: { roles: rolesData, user: expectedUser },
vi.spyOn(axios, 'get').mockImplementation((url) => {
if (url === 'VnUsers/acls') return Promise.resolve({ data: [] });
return Promise.resolve({
data: { roles: rolesData, user: expectedUser },
});
}); });
}); });
});
it('should fetch the user roles and then set token in the sessionStorage', async () => { it('should fetch the user roles and then set token in the sessionStorage', async () => {
const expectedRoles = ['salesPerson', 'admin']; const expectedRoles = ['salesPerson', 'admin'];
const expectedToken = 'mySessionToken'; const expectedToken = 'mySessionToken';
const expectedTokenMultimedia = 'mySessionTokenMultimedia'; const expectedTokenMultimedia = 'mySessionTokenMultimedia';
const keepLogin = false; const keepLogin = false;
await session.login({ await session.login({
token: expectedToken, token: expectedToken,
tokenMultimedia: expectedTokenMultimedia, tokenMultimedia: expectedTokenMultimedia,
keepLogin, keepLogin,
});
const roles = state.getRoles();
const localToken = localStorage.getItem('token');
const sessionToken = sessionStorage.getItem('token');
expect(roles.value).toEqual(expectedRoles);
expect(localToken).toBeNull();
expect(sessionToken).toEqual(expectedToken);
await session.destroy(); // this clears token and user for any other test
}); });
it('should fetch the user roles and then set token in the localStorage', async () => { const roles = state.getRoles();
const expectedRoles = ['salesPerson', 'admin']; const localToken = localStorage.getItem('token');
const expectedToken = 'myLocalToken'; const sessionToken = sessionStorage.getItem('token');
const expectedTokenMultimedia = 'myLocalTokenMultimedia';
const keepLogin = true;
await session.login({ expect(roles.value).toEqual(expectedRoles);
token: expectedToken, expect(localToken).toBeNull();
tokenMultimedia: expectedTokenMultimedia, expect(sessionToken).toEqual(expectedToken);
keepLogin,
});
const roles = state.getRoles(); await session.destroy(); // this clears token and user for any other test
const localToken = localStorage.getItem('token'); });
const sessionToken = sessionStorage.getItem('token');
expect(roles.value).toEqual(expectedRoles); it('should fetch the user roles and then set token in the localStorage', async () => {
expect(localToken).toEqual(expectedToken); const expectedRoles = ['salesPerson', 'admin'];
expect(sessionToken).toBeNull(); const expectedToken = 'myLocalToken';
const expectedTokenMultimedia = 'myLocalTokenMultimedia';
const keepLogin = true;
await session.destroy(); // this clears token and user for any other test await session.login({
token: expectedToken,
tokenMultimedia: expectedTokenMultimedia,
keepLogin,
}); });
},
{}, const roles = state.getRoles();
); const localToken = localStorage.getItem('token');
const sessionToken = sessionStorage.getItem('token');
expect(roles.value).toEqual(expectedRoles);
expect(localToken).toEqual(expectedToken);
expect(sessionToken).toBeNull();
await session.destroy(); // this clears token and user for any other test
});
});
describe('RenewToken', () => { describe('RenewToken', () => {
const expectedToken = 'myToken'; const expectedToken = 'myToken';

View File

@ -23,7 +23,7 @@ const claimDms = ref([
]); ]);
const client = ref({}); const client = ref({});
const inputFile = ref(); const inputFile = ref();
const files = ref({}); const files = ref([]);
const spinnerRef = ref(); const spinnerRef = ref();
const claimDmsRef = ref(); const claimDmsRef = ref();
const dmsType = ref({}); const dmsType = ref({});
@ -255,9 +255,8 @@ function onDrag() {
icon="add" icon="add"
color="primary" color="primary"
> >
<QInput <QFile
ref="inputFile" ref="inputFile"
type="file"
style="display: none" style="display: none"
multiple multiple
v-model="files" v-model="files"

View File

@ -52,7 +52,7 @@ describe('ClaimLines', () => {
expectedData, expectedData,
{ {
signal: canceller.signal, signal: canceller.signal,
} },
); );
}); });
}); });
@ -69,7 +69,7 @@ describe('ClaimLines', () => {
expect.objectContaining({ expect.objectContaining({
message: 'Discount updated', message: 'Discount updated',
type: 'positive', type: 'positive',
}) }),
); );
}); });
}); });

View File

@ -14,6 +14,9 @@ describe('ClaimLinesImport', () => {
fetch: vi.fn(), fetch: vi.fn(),
}, },
}, },
propsData: {
ticketId: 1,
},
}).vm; }).vm;
}); });
@ -40,7 +43,7 @@ describe('ClaimLinesImport', () => {
expect.objectContaining({ expect.objectContaining({
message: 'Lines added to claim', message: 'Lines added to claim',
type: 'positive', type: 'positive',
}) }),
); );
expect(vm.canceller).toEqual(null); expect(vm.canceller).toEqual(null);
}); });

View File

@ -41,10 +41,10 @@ describe('ClaimPhoto', () => {
await vm.deleteDms({ index: 0 }); await vm.deleteDms({ index: 0 });
expect(axios.post).toHaveBeenCalledWith( expect(axios.post).toHaveBeenCalledWith(
`ClaimDms/${claimMock.claimDms[0].dmsFk}/removeFile` `ClaimDms/${claimMock.claimDms[0].dmsFk}/removeFile`,
); );
expect(vm.quasar.notify).toHaveBeenCalledWith( expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'positive' }) expect.objectContaining({ type: 'positive' }),
); );
}); });
}); });
@ -63,7 +63,7 @@ describe('ClaimPhoto', () => {
data: { index: 1 }, data: { index: 1 },
promise: vm.deleteDms, promise: vm.deleteDms,
}, },
}) }),
); );
}); });
}); });
@ -102,10 +102,10 @@ describe('ClaimPhoto', () => {
new FormData(), new FormData(),
expect.objectContaining({ expect.objectContaining({
params: expect.objectContaining({ hasFile: false }), params: expect.objectContaining({ hasFile: false }),
}) }),
); );
expect(vm.quasar.notify).toHaveBeenCalledWith( expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({ type: 'positive' }) expect.objectContaining({ type: 'positive' }),
); );
expect(vm.claimDmsRef.fetch).toHaveBeenCalledOnce(); expect(vm.claimDmsRef.fetch).toHaveBeenCalledOnce();

View File

@ -39,7 +39,7 @@ const route = useRoute();
const { t } = useI18n(); const { t } = useI18n();
const entityId = computed(() => { const entityId = computed(() => {
return $props.id || route.params.id; return Number($props.id || route.params.id);
}); });
const data = ref(useCardDescription()); const data = ref(useCardDescription());

View File

@ -86,7 +86,7 @@ async function acceptPropagate({ isEqualizated }) {
:required="true" :required="true"
:rules="validate('client.socialName')" :rules="validate('client.socialName')"
clearable clearable
uppercase="true" :uppercase="true"
v-model="data.socialName" v-model="data.socialName"
> >
<template #append> <template #append>

View File

@ -25,7 +25,7 @@ const $props = defineProps({
}, },
}); });
const entityId = computed(() => $props.id || route.params.id); const entityId = computed(() => Number($props.id || route.params.id));
const customer = computed(() => summary.value.entity); const customer = computed(() => summary.value.entity);
const summary = ref(); const summary = ref();
const defaulterAmount = computed(() => customer.value.defaulters[0]?.amount); const defaulterAmount = computed(() => customer.value.defaulters[0]?.amount);

View File

@ -72,7 +72,7 @@ const exprBuilder = (param, value) => {
option-value="id" option-value="id"
option-label="name" option-label="name"
url="Departments" url="Departments"
no-one="true" :no-one="true"
/> />
</QItemSection> </QItemSection>
</QItem> </QItem>

View File

@ -32,7 +32,7 @@ describe('CustomerPayments', () => {
expect.objectContaining({ expect.objectContaining({
message: 'Payment confirmed', message: 'Payment confirmed',
type: 'positive', type: 'positive',
}) }),
); );
}); });
}); });

View File

@ -5,7 +5,7 @@ import InvoiceInSummary from './InvoiceInSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
required: true, default: null,
Review

Deberia ser requirod un descriptor sin id no debe funcionar

Deberia ser requirod un descriptor sin id no debe funcionar
Review

El tema está en que si la carga es dinámica al principio se pasa undefined, hasta que carga y muestra un warning tipo: "Expected number but got undefined

El tema está en que si la carga es dinámica al principio se pasa undefined, hasta que carga y muestra un warning tipo: "Expected number but got undefined
Review

Un v-if diria que es mas correcto @jorgep

Un v-if diria que es mas correcto @jorgep
Review

Tiene v-if

Tiene v-if
}, },
}); });
</script> </script>

View File

@ -120,7 +120,6 @@ watch(
:data-key="dataKey" :data-key="dataKey"
:tag-value="tagValue" :tag-value="tagValue"
:tags="tags" :tags="tags"
:initial-catalog-params="catalogParams"
:arrayData :arrayData
/> />
</template> </template>

View File

@ -27,7 +27,7 @@ const getTotalRef = ref();
const total = ref(0); const total = ref(0);
const entityId = computed(() => { const entityId = computed(() => {
return $props.id || route.params.id; return Number($props.id || route.params.id);
}); });
const orderTotal = computed(() => state.get('orderTotal') ?? 0); const orderTotal = computed(() => state.get('orderTotal') ?? 0);

View File

@ -80,7 +80,7 @@ const columns = computed(() => [
<VnTable <VnTable
:data-key="dataKey" :data-key="dataKey"
:columns="columns" :columns="columns"
is-editable="false" :is-editable="false"
:right-search="false" :right-search="false"
:use-model="true" :use-model="true"
:disable-option="{ table: true }" :disable-option="{ table: true }"

View File

@ -90,7 +90,7 @@ const onDataSaved = ({ id }) => {
<VnTable <VnTable
:data-key="dataKey" :data-key="dataKey"
:columns="columns" :columns="columns"
is-editable="false" :is-editable="false"
:right-search="false" :right-search="false"
:use-model="true" :use-model="true"
:disable-option="{ table: true }" :disable-option="{ table: true }"

View File

@ -65,15 +65,13 @@ function findBankFk(value, row) {
if (bankEntityFk) row.bankEntityFk = bankEntityFk.id; if (bankEntityFk) row.bankEntityFk = bankEntityFk.id;
} }
function bankEntityFilter(val, update) { function bankEntityFilter(val) {
update(() => { const needle = val.toLowerCase();
const needle = val.toLowerCase(); filteredBankEntitiesOptions.value = bankEntitiesOptions.value.filter(
filteredBankEntitiesOptions.value = bankEntitiesOptions.value.filter( (bank) =>
(bank) => bank.bic.toLowerCase().startsWith(needle) ||
bank.bic.toLowerCase().startsWith(needle) || bank.name.toLowerCase().includes(needle),
bank.name.toLowerCase().includes(needle), );
);
});
} }
</script> </script>
<template> <template>
@ -82,7 +80,8 @@ function bankEntityFilter(val, update) {
url="BankEntities" url="BankEntities"
@on-fetch=" @on-fetch="
(data) => { (data) => {
(bankEntitiesOptions = data), (filteredBankEntitiesOptions = data); bankEntitiesOptions = data;
filteredBankEntitiesOptions = data;
} }
" "
auto-load auto-load
@ -135,10 +134,8 @@ function bankEntityFilter(val, update) {
:label="t('worker.create.bankEntity')" :label="t('worker.create.bankEntity')"
v-model="row.bankEntityFk" v-model="row.bankEntityFk"
:options="filteredBankEntitiesOptions" :options="filteredBankEntitiesOptions"
:default-filter="false" :filter-fn="bankEntityFilter"
@filter="(val, update) => bankEntityFilter(val, update)"
option-label="bic" option-label="bic"
option-value="id"
hide-selected hide-selected
:required="true" :required="true"
:roles-allowed-to-create="['financial']" :roles-allowed-to-create="['financial']"

View File

@ -5,7 +5,7 @@ import SupplierSummary from './SupplierSummary.vue';
const $props = defineProps({ const $props = defineProps({
id: { id: {
type: Number, type: Number,
required: true, default: null,
Review

=

=
Review

El tema está en que si la carga es dinámica al principio se pasa undefined, hasta que carga y muestra un warning tipo: "Expected number but got undefined

El tema está en que si la carga es dinámica al principio se pasa undefined, hasta que carga y muestra un warning tipo: "Expected number but got undefined
Review

Un v-if diria que es mas correcto @jorgep

Un v-if diria que es mas correcto @jorgep
Review

tiene v-if

tiene v-if
}, },
}); });
</script> </script>

View File

@ -27,7 +27,7 @@ const entityId = computed(() => {
<template> <template>
<EntityDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone"> <EntityDescriptor :url="`Zones/${entityId}`" :filter="filter" data-key="Zone">
<template #menu="{ entity }"> <template #menu="{ entity }">
<ZoneDescriptorMenuItems :zone="entity" /> <ZoneDescriptorMenuItems />
</template> </template>
<template #body="{ entity }"> <template #body="{ entity }">
<VnLv :label="$t('list.agency')" :value="entity.agencyMode?.name" /> <VnLv :label="$t('list.agency')" :value="entity.agencyMode?.name" />

View File

@ -93,6 +93,7 @@ const columns = computed(() => [
optionLabel: 'name', optionLabel: 'name',
optionValue: 'id', optionValue: 'id',
}, },
columnClass: 'expand',
}, },
{ {
align: 'left', align: 'left',
@ -247,74 +248,70 @@ const closeEventForm = () => {
</QBtnGroup> </QBtnGroup>
</template> </template>
</VnSubToolbar> </VnSubToolbar>
<div class="table-container"> <VnTable
<div class="column items-center"> ref="tableRef"
<VnTable :data-key="dataKey"
ref="tableRef" :columns="columns"
:data-key="dataKey" redirect="Zone"
:columns="columns" :create="{
redirect="Zone" urlCreate: 'Zones',
:create="{ title: t('list.createZone'),
urlCreate: 'Zones', onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`),
title: t('list.createZone'), formInitialData: {},
onDataSaved: ({ id }) => tableRef.redirect(`${id}/location`), }"
formInitialData: {}, table-height="85vh"
}" v-model:selected="selectedRows"
table-height="85vh" :table="{
v-model:selected="selectedRows" 'row-key': 'id',
:table="{ selection: 'multiple',
'row-key': 'id', }"
selection: 'multiple', >
}" <template #column-addressFk="{ row }">
> {{ dashIfEmpty(formatRow(row)) }}
<template #column-addressFk="{ row }"> </template>
{{ dashIfEmpty(formatRow(row)) }} <template #more-create-dialog="{ data }">
</template> <VnSelect
<template #more-create-dialog="{ data }"> url="AgencyModes"
<VnSelect v-model="data.agencyModeFk"
url="AgencyModes" option-value="id"
v-model="data.agencyModeFk" option-label="name"
option-value="id" :label="t('list.agency')"
option-label="name" />
:label="t('list.agency')" <VnInput
/> v-model="data.price"
<VnInput :label="t('list.price')"
v-model="data.price" min="0"
:label="t('list.price')" type="number"
min="0" required="true"
type="number" />
required="true" <VnInput
/> v-model="data.bonus"
<VnInput :label="t('zone.bonus')"
v-model="data.bonus" min="0"
:label="t('zone.bonus')" type="number"
min="0" />
type="number" <VnInput
/> v-model="data.travelingDays"
<VnInput :label="t('zone.travelingDays')"
v-model="data.travelingDays" type="number"
:label="t('zone.travelingDays')" min="0"
type="number" />
min="0" <VnInputTime v-model="data.hour" :label="t('list.close')" />
/> <VnSelect
<VnInputTime v-model="data.hour" :label="t('list.close')" /> url="Warehouses"
<VnSelect v-model="data.warehouseFK"
url="Warehouses" option-value="id"
v-model="data.warehouseFK" option-label="name"
option-value="id" :label="t('list.warehouse')"
option-label="name" :options="warehouseOptions"
:label="t('list.warehouse')" />
:options="warehouseOptions" <QCheckbox
/> v-model="data.isVolumetric"
<QCheckbox :label="t('list.isVolumetric')"
v-model="data.isVolumetric" :toggle-indeterminate="false"
:label="t('list.isVolumetric')" />
:toggle-indeterminate="false" </template>
/> </VnTable>
</template>
</VnTable>
</div>
</div>
</template> </template>
</VnSection> </VnSection>
<QDialog v-model="showZoneEventForm" @hide="closeEventForm()"> <QDialog v-model="showZoneEventForm" @hide="closeEventForm()">
@ -333,24 +330,6 @@ const closeEventForm = () => {
/> />
</QDialog> </QDialog>
</template> </template>
<style lang="scss" scoped>
.table-container {
display: flex;
justify-content: center;
}
.column {
display: flex;
flex-direction: column;
align-items: center;
min-width: 70%;
}
:deep(.shrink-column) {
width: 8%;
}
</style>
<i18n> <i18n>
es: es:
Search zone: Buscar zona Search zone: Buscar zona

View File

@ -1,22 +1,23 @@
import { describe, expect, it, beforeEach, beforeAll } from 'vitest'; import { describe, expect, it, beforeEach, beforeAll } from 'vitest';
import { createWrapper } from 'app/test/vitest/helper'; import { setActivePinia, createPinia } from 'pinia';
import { useStateQueryStore } from 'src/stores/useStateQueryStore'; import { useStateQueryStore } from 'src/stores/useStateQueryStore';
describe('useStateQueryStore', () => { describe('useStateQueryStore', () => {
beforeAll(() => { let stateQueryStore;
createWrapper({}, {}); let add, isLoading, remove, reset;
});
const stateQueryStore = useStateQueryStore();
const { add, isLoading, remove, reset } = useStateQueryStore();
const firstQuery = { url: 'myQuery' }; const firstQuery = { url: 'myQuery' };
function getQueries() { function getQueries() {
return stateQueryStore.queries; return stateQueryStore.queries;
} }
beforeAll(() => {
setActivePinia(createPinia());
});
beforeEach(() => { beforeEach(() => {
stateQueryStore = useStateQueryStore();
({ add, isLoading, remove, reset } = useStateQueryStore());
reset(); reset();
expect(getQueries().size).toBeFalsy(); expect(getQueries().size).toBeFalsy();
}); });

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe.skip('ClaimAction', () => { describe('ClaimAction', () => {
const claimId = 1; const claimId = 1;
const firstRow = 'tbody > :nth-child(1)'; const firstRow = 'tbody > :nth-child(1)';
@ -15,13 +15,13 @@ describe.skip('ClaimAction', () => {
}); });
// https://redmine.verdnatura.es/issues/8756 // https://redmine.verdnatura.es/issues/8756
xit('should change destination', () => { it.skip('should change destination', () => {
const rowData = [true, null, null, 'Bueno']; const rowData = [true, null, null, 'Bueno'];
cy.fillRow(firstRow, rowData); cy.fillRow(firstRow, rowData);
}); });
// https://redmine.verdnatura.es/issues/8756 // https://redmine.verdnatura.es/issues/8756
xit('should change destination from other button', () => { it.skip('should change destination from other button', () => {
const rowData = [true]; const rowData = [true];
cy.fillRow(firstRow, rowData); cy.fillRow(firstRow, rowData);
@ -35,7 +35,7 @@ describe.skip('ClaimAction', () => {
}); });
// https://redmine.verdnatura.es/issues/8756 // https://redmine.verdnatura.es/issues/8756
xit('should remove the line', () => { it.skip('should remove the line', () => {
cy.fillRow(firstRow, [true]); cy.fillRow(firstRow, [true]);
cy.removeCard(); cy.removeCard();
cy.clickConfirm(); cy.clickConfirm();

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe.skip('ClaimDevelopment', () => { describe('ClaimDevelopment', () => {
const claimId = 1; const claimId = 1;
const firstLineReason = 'tbody > :nth-child(1) > :nth-child(2)'; const firstLineReason = 'tbody > :nth-child(1) > :nth-child(2)';
const thirdRow = 'tbody > :nth-child(3)'; const thirdRow = 'tbody > :nth-child(3)';

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe.skip('Client list', () => { describe('Client list', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.visit('/#/customer/list', { cy.visit('/#/customer/list', {

View File

@ -7,7 +7,7 @@ Cypress.Commands.add('selectTravel', (warehouse = '1') => {
}); });
Cypress.Commands.add('deleteEntry', () => { Cypress.Commands.add('deleteEntry', () => {
cy.get('[data-cy="descriptor-more-opts"]').should('be.visible').click(); cy.dataCy('descriptor-more-opts').should('be.visible').click();
cy.waitForElement('div[data-cy="delete-entry"]').click(); cy.waitForElement('div[data-cy="delete-entry"]').click();
}); });

View File

@ -1,6 +1,6 @@
import '../commands.js'; import '../commands.js';
describe('EntryBasicData', () => { describe.skip('EntryBasicData', () => {
beforeEach(() => { beforeEach(() => {
cy.login('buyer'); cy.login('buyer');
cy.visit(`/#/entry/list`); cy.visit(`/#/entry/list`);

View File

@ -84,7 +84,7 @@ describe('InvoiceInDescriptor', () => {
beforeEach(() => cy.visit(`/#/invoice-in/${originalId}/summary`)); beforeEach(() => cy.visit(`/#/invoice-in/${originalId}/summary`));
it('should create a correcting invoice and redirect to original invoice', () => { it.skip('should create a correcting invoice and redirect to original invoice', () => {
createCorrective(); createCorrective();
redirect(originalId); redirect(originalId);
}); });

View File

@ -31,7 +31,7 @@ describe('InvoiceOut list', () => {
it.skip('should open the invoice descriptor from table icon', () => { it.skip('should open the invoice descriptor from table icon', () => {
cy.get(firstSummaryIcon).click(); cy.get(firstSummaryIcon).click();
cy.get('.cardSummary').should('be.visible'); cy.get('.cardSummary').should('be.visible');
cy.get('.summaryHeader > div').should('include.text', 'A1111111'); cy.get('.summaryHeader > div').should('include.text', 'V10100001');
}); });
it('should open the client descriptor', () => { it('should open the client descriptor', () => {

View File

@ -1,6 +1,6 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe.skip('Item list', () => { describe('Item list', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.visit(`/#/item/list`); cy.visit(`/#/item/list`);

View File

@ -1,5 +1,5 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
describe.skip('Logout', () => { describe('Logout', () => {
beforeEach(() => { beforeEach(() => {
cy.login('developer'); cy.login('developer');
cy.visit(`/#/dashboard`); cy.visit(`/#/dashboard`);

View File

@ -34,7 +34,7 @@ describe('OrderCatalog', () => {
searchByCustomTagInput('Silver'); searchByCustomTagInput('Silver');
}); });
it.skip('filters by custom value dialog', () => { it('filters by custom value dialog', () => {
Cypress.on('uncaught:exception', (err) => { Cypress.on('uncaught:exception', (err) => {
if (err.message.includes('canceled')) { if (err.message.includes('canceled')) {
return false; return false;

View File

@ -1,4 +1,4 @@
describe.skip('RouteAutonomous', () => { describe('RouteAutonomous', () => {
const getLinkSelector = (colField) => const getLinkSelector = (colField) =>
`tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`; `tr:first-child > [data-col-field="${colField}"] > .no-padding > .link`;
@ -44,7 +44,7 @@ describe.skip('RouteAutonomous', () => {
.should('have.length.greaterThan', 0); .should('have.length.greaterThan', 0);
}); });
it('Should create invoice in to selected route', () => { it.skip('Should create invoice in to selected route', () => {
cy.get(selectors.firstRowCheckbox).click(); cy.get(selectors.firstRowCheckbox).click();
cy.get(selectors.createInvoiceBtn).click(); cy.get(selectors.createInvoiceBtn).click();
cy.dataCy(selectors.reference).type(data.reference); cy.dataCy(selectors.reference).type(data.reference);
@ -68,7 +68,7 @@ describe.skip('RouteAutonomous', () => {
cy.url().should('include', summaryUrl); cy.url().should('include', summaryUrl);
}); });
describe('Received pop-ups', () => { describe.skip('Received pop-ups', () => {
it('Should redirect to invoice in summary from the received descriptor pop-up', () => { it('Should redirect to invoice in summary from the received descriptor pop-up', () => {
cy.get(selectors.received).click(); cy.get(selectors.received).click();
cy.validateContent(selectors.descriptorTitle, data.reference); cy.validateContent(selectors.descriptorTitle, data.reference);

View File

@ -1,6 +1,6 @@
/// <reference types="cypress" /> /// <reference types="cypress" />
// https://redmine.verdnatura.es/issues/8848 // https://redmine.verdnatura.es/issues/8848
describe.skip('VnShortcuts', () => { describe('VnShortcuts', () => {
const modules = { const modules = {
item: 'a', item: 'a',
customer: 'c', customer: 'c',

View File

@ -1,4 +1,4 @@
describe.skip('WorkerBusiness', () => { describe('WorkerBusiness', () => {
const saveBtn = '.q-mt-lg > .q-btn--standard'; const saveBtn = '.q-mt-lg > .q-btn--standard';
const contributionCode = `Representantes de comercio`; const contributionCode = `Representantes de comercio`;
const contractType = `INDEFINIDO A TIEMPO COMPLETO`; const contractType = `INDEFINIDO A TIEMPO COMPLETO`;

View File

@ -4,6 +4,7 @@ import { createTestingPinia } from '@pinia/testing';
import { vi } from 'vitest'; import { vi } from 'vitest';
import { i18n } from 'src/boot/i18n'; import { i18n } from 'src/boot/i18n';
import { Notify, Dialog } from 'quasar'; import { Notify, Dialog } from 'quasar';
import keyShortcut from 'src/boot/keyShortcut';
import * as useValidator from 'src/composables/useValidator'; import * as useValidator from 'src/composables/useValidator';
installQuasarPlugin({ installQuasarPlugin({
@ -16,6 +17,26 @@ const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false });
const mockPush = vi.fn(); const mockPush = vi.fn();
const mockReplace = vi.fn(); const mockReplace = vi.fn();
vi.mock('vue', async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
inject: vi.fn((key) => {
if (key === 'app') {
return {};
}
return actual.inject(key);
}),
onMounted: vi.fn((fn) => (fn && typeof fn === 'function' ? fn() : undefined)),
onBeforeMount: vi.fn((fn) => (fn && typeof fn === 'function' ? fn() : undefined)),
onUpdated: vi.fn((fn) => (fn && typeof fn === 'function' ? fn() : undefined)),
onUnmounted: vi.fn((fn) => (fn && typeof fn === 'function' ? fn() : undefined)),
onBeforeUnmount: vi.fn((fn) =>
fn && typeof fn === 'function' ? fn() : undefined,
),
};
});
vi.mock('vue-router', () => ({ vi.mock('vue-router', () => ({
useRouter: () => ({ useRouter: () => ({
push: mockPush, push: mockPush,
@ -87,6 +108,10 @@ export function createWrapper(component, options) {
const defaultOptions = { const defaultOptions = {
global: { global: {
plugins: [i18n, pinia], plugins: [i18n, pinia],
directives: {
shortcut: keyShortcut,
},
stubs: ['useState', 'arrayData', 'useStateStore', 'vue-i18n', 'RouterLink'],
}, },
mocks: { mocks: {
t: (tKey) => tKey, t: (tKey) => tKey,
@ -94,15 +119,11 @@ export function createWrapper(component, options) {
}, },
}; };
const mountOptions = Object.assign({}, defaultOptions); const mountOptions = {
...defaultOptions,
if (options instanceof Object) { ...options,
Object.assign(mountOptions, options); global: { ...defaultOptions.global, ...options?.global },
};
if (options.global) {
mountOptions.global.plugins = defaultOptions.global.plugins;
}
}
const wrapper = mount(component, mountOptions); const wrapper = mount(component, mountOptions);
const vm = wrapper.vm; const vm = wrapper.vm;

View File

@ -1,5 +1,26 @@
// This file will be run before each test file, don't delete or vitest will not work. import { afterAll, beforeAll, vi } from 'vitest';
import { vi } from 'vitest';
let vueWarnings = [];
const originalConsoleWarn = console.warn;
beforeAll(() => {
console.warn = (...args) => {
vueWarnings.push(args.join(' '));
};
});
afterEach(() => {
if (vueWarnings.length > 0) {
const allWarnings = vueWarnings.join('\n');
vueWarnings = [];
throw new Error(`Vue warnings detected during test:\n${allWarnings}`);
}
});
afterAll(() => {
console.warn = originalConsoleWarn;
});
vi.mock('axios'); vi.mock('axios');
vi.mock('vue-router', () => ({ vi.mock('vue-router', () => ({