forked from verdnatura/salix-front
refactor: refs #6897 clean up alignment and improve data attributes for better testing
This commit is contained in:
parent
af2cbda077
commit
5f624bbf7f
|
@ -46,7 +46,6 @@ const enterEvent = {
|
|||
|
||||
const defaultAttrs = {
|
||||
filled: !$props.showTitle,
|
||||
// class: 'q-px-xs q-pb-xs q-pt-none fit',
|
||||
dense: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -137,6 +137,7 @@ const $props = defineProps({
|
|||
type: Object,
|
||||
},
|
||||
});
|
||||
|
||||
const { t } = useI18n();
|
||||
const stateStore = useStateStore();
|
||||
const route = useRoute();
|
||||
|
@ -165,6 +166,7 @@ const editingField = ref(null);
|
|||
const isTableMode = computed(() => mode.value == TABLE_MODE);
|
||||
const showRightIcon = computed(() => $props.rightSearch || $props.rightSearchIcon);
|
||||
const selectRegex = /select/;
|
||||
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
||||
const tableModes = [
|
||||
{
|
||||
icon: 'view_column',
|
||||
|
@ -184,6 +186,7 @@ onBeforeMount(() => {
|
|||
const urlParams = route.query[$props.searchUrl];
|
||||
hasParams.value = urlParams && Object.keys(urlParams).length !== 0;
|
||||
});
|
||||
|
||||
onMounted(async () => {
|
||||
if ($props.isEditable) document.addEventListener('click', clickHandler);
|
||||
mode.value =
|
||||
|
@ -206,6 +209,7 @@ onMounted(async () => {
|
|||
};
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(async () => {
|
||||
if ($props.isEditable) document.removeEventListener('click', clickHandler);
|
||||
});
|
||||
|
@ -216,6 +220,16 @@ watch(
|
|||
{ immediate: true },
|
||||
);
|
||||
|
||||
defineExpose({
|
||||
create: createForm,
|
||||
reload,
|
||||
redirect: redirectFn,
|
||||
selected,
|
||||
CrudModelRef,
|
||||
params,
|
||||
tableRef,
|
||||
});
|
||||
|
||||
function splitColumns(columns) {
|
||||
splittedColumns.value = {
|
||||
columns: [],
|
||||
|
@ -281,17 +295,6 @@ function columnName(col) {
|
|||
return name;
|
||||
}
|
||||
|
||||
const emit = defineEmits(['onFetch', 'update:selected', 'saveChanges']);
|
||||
defineExpose({
|
||||
create: createForm,
|
||||
reload,
|
||||
redirect: redirectFn,
|
||||
selected,
|
||||
CrudModelRef,
|
||||
params,
|
||||
tableRef,
|
||||
});
|
||||
|
||||
function handleOnDataSaved(_) {
|
||||
if (_.onDataSaved) _.onDataSaved({ CrudModelRef: CrudModelRef.value });
|
||||
else $props.create.onDataSaved(_);
|
||||
|
@ -512,6 +515,7 @@ function getCheckboxIcon(value) {
|
|||
return 'indeterminate_check_box';
|
||||
}
|
||||
}
|
||||
|
||||
function getToggleIcon(value) {
|
||||
if (value === null) return 'help_outline';
|
||||
return value ? 'toggle_on' : 'toggle_off';
|
||||
|
@ -679,7 +683,8 @@ const checkbox = ref(null);
|
|||
}"
|
||||
:class="[
|
||||
col.columnClass,
|
||||
'body-cell no-margin no-padding text-center',
|
||||
'body-cell no-margin no-padding',
|
||||
getColAlign(col),
|
||||
]"
|
||||
:data-row-index="rowIndex"
|
||||
:data-col-field="col?.name"
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
export function getColAlign(col) {
|
||||
let align;
|
||||
|
||||
switch (col.component) {
|
||||
case 'select':
|
||||
align = 'left';
|
||||
break;
|
||||
case 'number':
|
||||
align = 'right';
|
||||
break;
|
||||
|
|
|
@ -640,6 +640,7 @@ onMounted(() => {
|
|||
:table-height="$props.tableHeight ?? '84vh'"
|
||||
auto-load
|
||||
footer
|
||||
data-cy="entry-buys"
|
||||
>
|
||||
<template #column-hex="{ row }">
|
||||
<VnColor :colors="row?.hexJson" style="height: 100%; min-width: 2000px" />
|
||||
|
|
|
@ -124,7 +124,7 @@ async function recalculateRates(entity) {
|
|||
async function cloneEntry() {
|
||||
try {
|
||||
const response = await axios.post(`Entries/${entityId.value}/cloneEntry`);
|
||||
push({ path: `/entry/${response.data[0].vNewEntryFk}` });
|
||||
push({ path: `/entry/${response.data}` });
|
||||
showNotification('positive', 'Entry cloned');
|
||||
} catch (error) {
|
||||
showNotification('negative', 'Failed to clone entry');
|
||||
|
@ -174,13 +174,7 @@ async function deleteEntry() {
|
|||
<QItem v-ripple clickable @click="cloneEntry(entity)" data-cy="clone-entry">
|
||||
<QItemSection>{{ t('Clone') }}</QItemSection>
|
||||
</QItem>
|
||||
<QItem
|
||||
v-ripple
|
||||
clickable
|
||||
@click="deleteEntry(entity)"
|
||||
data-cy="delete-entry"
|
||||
v-if="entity?.travelFk"
|
||||
>
|
||||
<QItem v-ripple clickable @click="deleteEntry(entity)" data-cy="delete-entry">
|
||||
<QItemSection>{{ t('Delete') }}</QItemSection>
|
||||
</QItem>
|
||||
</template>
|
||||
|
@ -293,4 +287,7 @@ es:
|
|||
Failed to recalculate rates: No se pudieron recalcular las tarifas
|
||||
Failed to clone entry: No se pudo clonar la entrada
|
||||
Failed to delete entry: No se pudo eliminar la entrada
|
||||
Recalculate rates: Recalcular tarifas
|
||||
Clone: Clonar
|
||||
Delete: Eliminar
|
||||
</i18n>
|
||||
|
|
|
@ -51,6 +51,7 @@ onMounted(async () => {
|
|||
:url="`Entries/${entityId}/getEntry`"
|
||||
@on-fetch="(data) => setEntryData(data)"
|
||||
data-key="EntrySummary"
|
||||
data-cy="entry-summary"
|
||||
>
|
||||
<template #header-left>
|
||||
<VnToSummary
|
||||
|
|
|
@ -44,7 +44,6 @@ const entryQueryFilter = {
|
|||
|
||||
const columns = computed(() => [
|
||||
{
|
||||
align: 'center',
|
||||
label: 'Ex',
|
||||
toolTip: t('entry.list.tableVisibleColumns.isExcludedFromAvailable'),
|
||||
name: 'isExcludedFromAvailable',
|
||||
|
@ -52,7 +51,6 @@ const columns = computed(() => [
|
|||
width: '35px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
label: 'Pe',
|
||||
toolTip: t('entry.list.tableVisibleColumns.isOrdered'),
|
||||
name: 'isOrdered',
|
||||
|
@ -60,7 +58,6 @@ const columns = computed(() => [
|
|||
width: '35px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
label: 'Le',
|
||||
toolTip: t('entry.list.tableVisibleColumns.isConfirmed'),
|
||||
name: 'isConfirmed',
|
||||
|
@ -68,7 +65,6 @@ const columns = computed(() => [
|
|||
width: '35px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
label: 'Re',
|
||||
toolTip: t('entry.list.tableVisibleColumns.isReceived'),
|
||||
name: 'isReceived',
|
||||
|
@ -76,7 +72,6 @@ const columns = computed(() => [
|
|||
width: '35px',
|
||||
},
|
||||
{
|
||||
align: 'center',
|
||||
label: t('entry.list.tableVisibleColumns.landed'),
|
||||
name: 'landed',
|
||||
component: 'date',
|
||||
|
@ -87,16 +82,15 @@ const columns = computed(() => [
|
|||
width: '105px',
|
||||
},
|
||||
{
|
||||
align: 'right',
|
||||
label: t('globals.id'),
|
||||
name: 'id',
|
||||
isId: true,
|
||||
component: 'number',
|
||||
chip: {
|
||||
condition: () => true,
|
||||
},
|
||||
},
|
||||
{
|
||||
align: 'left',
|
||||
label: t('entry.list.tableVisibleColumns.supplierFk'),
|
||||
name: 'supplierFk',
|
||||
create: true,
|
||||
|
|
|
@ -7,8 +7,8 @@ describe('Entry', () => {
|
|||
|
||||
it('Filter deleted entries and other fields', () => {
|
||||
createEntry();
|
||||
|
||||
cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
|
||||
cy.waitForElement('[data-cy="entry-buys"]');
|
||||
deleteEntry();
|
||||
cy.typeSearchbar('{enter}');
|
||||
cy.get('span[title="Date"]').click().click();
|
||||
|
@ -31,30 +31,37 @@ describe('Entry', () => {
|
|||
|
||||
it('Clone entry and recalculate rates', () => {
|
||||
createEntry();
|
||||
cy.get('.q-notification__message').eq(0).should('have.text', 'Data created');
|
||||
|
||||
cy.url().then((perviousUrl) => {
|
||||
cy.log('URL antes de clonar:', perviousUrl);
|
||||
cy.waitForElement('[data-cy="entry-buys"]');
|
||||
|
||||
cy.url().then((previousUrl) => {
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
cy.get('div[data-cy="clone-entry"]').click();
|
||||
cy.get('div[data-cy="clone-entry"]').should('be.visible').click();
|
||||
|
||||
cy.url().then((newUrl) => {
|
||||
expect(perviousUrl).not.to.eq(newUrl);
|
||||
cy.get('.q-notification__message').eq(1).should('have.text', 'Entry cloned');
|
||||
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
cy.get('div[data-cy="recalculate-rates"]').click();
|
||||
cy.url()
|
||||
.should('not.eq', previousUrl)
|
||||
.then(() => {
|
||||
cy.waitForElement('[data-cy="entry-buys"]');
|
||||
|
||||
cy.get('.q-notification__message')
|
||||
.eq(1)
|
||||
.should('have.text', 'Entry prices recalculated');
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
cy.get('div[data-cy="recalculate-rates"]').click();
|
||||
|
||||
deleteEntry();
|
||||
cy.get('.q-notification__message')
|
||||
.eq(2)
|
||||
.should('have.text', 'Entry prices recalculated');
|
||||
|
||||
cy.visit(perviousUrl);
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
deleteEntry();
|
||||
|
||||
deleteEntry();
|
||||
});
|
||||
cy.log(previousUrl);
|
||||
|
||||
cy.visit(previousUrl);
|
||||
|
||||
cy.waitForElement('[data-cy="entry-buys"]');
|
||||
deleteEntry();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -174,13 +181,14 @@ describe('Entry', () => {
|
|||
function goToEntryBuys() {
|
||||
const entryBuySelector = 'a[data-cy="EntryBuys-menu-item"]';
|
||||
cy.get(entryBuySelector).should('be.visible');
|
||||
cy.get(entryBuySelector).click();
|
||||
cy.waitForElement('[data-cy="entry-buys"]');
|
||||
cy.get(entryBuySelector).click();
|
||||
}
|
||||
|
||||
function deleteEntry() {
|
||||
cy.get('[data-cy="descriptor-more-opts"]').click();
|
||||
cy.get('div[data-cy="delete-entry"]').click();
|
||||
cy.waitForElement('div[data-cy="delete-entry"]');
|
||||
cy.get('div[data-cy="delete-entry"]').should('be.visible').click();
|
||||
cy.url().should('include', 'list');
|
||||
}
|
||||
|
||||
|
|
|
@ -87,36 +87,55 @@ Cypress.Commands.add('getValue', (selector) => {
|
|||
});
|
||||
|
||||
// Fill Inputs
|
||||
Cypress.Commands.add('selectOption', (selector, option, timeout = 5000) => {
|
||||
Cypress.Commands.add('selectOption', (selector, option, timeout = 2500) => {
|
||||
cy.waitForElement(selector, timeout);
|
||||
cy.get(selector).click();
|
||||
cy.get(selector).invoke('data', 'url').as('dataUrl');
|
||||
cy.get(selector)
|
||||
.clear()
|
||||
.type(option)
|
||||
.then(() => {
|
||||
cy.get('.q-menu', { timeout })
|
||||
.should('be.visible') // Asegurarse de que el menú está visible
|
||||
.and('exist') // Verificar que el menú existe
|
||||
.then(() => {
|
||||
cy.get('@dataUrl').then((url) => {
|
||||
if (url) {
|
||||
// Esperar a que el menú no esté visible (desaparezca)
|
||||
cy.get('.q-menu').should('not.be.visible');
|
||||
// Ahora esperar a que el menú vuelva a aparecer
|
||||
cy.get('.q-menu').should('be.visible').and('exist');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Finalmente, seleccionar la opción deseada
|
||||
cy.get('.q-menu:visible') // Asegurarse de que estamos dentro del menú visible
|
||||
.find('.q-item') // Encontrar los elementos de las opciones
|
||||
.contains(option) // Verificar que existe una opción que contenga el texto deseado
|
||||
.click(); // Hacer clic en la opción
|
||||
cy.get(selector, { timeout })
|
||||
.should('exist')
|
||||
.should('be.visible')
|
||||
.click()
|
||||
.then(($el) => {
|
||||
cy.wrap($el.is('input') ? $el : $el.find('input'))
|
||||
.invoke('attr', 'aria-controls')
|
||||
.then((ariaControl) => selectItem(selector, option, ariaControl));
|
||||
});
|
||||
});
|
||||
|
||||
function selectItem(selector, option, ariaControl, hasWrite = true) {
|
||||
if (!hasWrite) cy.wait(100);
|
||||
|
||||
getItems(ariaControl).then((items) => {
|
||||
const matchingItem = items
|
||||
.toArray()
|
||||
.find((item) => item.innerText.includes(option));
|
||||
if (matchingItem) return cy.wrap(matchingItem).click();
|
||||
|
||||
if (hasWrite) cy.get(selector).clear().type(option, { delay: 0 });
|
||||
return selectItem(selector, option, ariaControl, false);
|
||||
});
|
||||
}
|
||||
|
||||
function getItems(ariaControl, startTime = Cypress._.now(), timeout = 2500) {
|
||||
// Se intenta obtener la lista de opciones del desplegable de manera recursiva
|
||||
return cy
|
||||
.get('#' + ariaControl, { timeout })
|
||||
.should('exist')
|
||||
.find('.q-item')
|
||||
.should('exist')
|
||||
.then(($items) => {
|
||||
if (!$items?.length || $items.first().text().trim() === '') {
|
||||
if (Cypress._.now() - startTime > timeout) {
|
||||
throw new Error(
|
||||
`getItems: Tiempo de espera (${timeout}ms) excedido.`,
|
||||
);
|
||||
}
|
||||
return getItems(ariaControl, startTime, timeout);
|
||||
}
|
||||
|
||||
return cy.wrap($items);
|
||||
});
|
||||
}
|
||||
|
||||
Cypress.Commands.add('countSelectOptions', (selector, option) => {
|
||||
cy.waitForElement(selector);
|
||||
cy.get(selector).click({ force: true });
|
||||
|
|
Loading…
Reference in New Issue