diff --git a/src/assets/logo.svg b/src/assets/salix.svg
similarity index 100%
rename from src/assets/logo.svg
rename to src/assets/salix.svg
diff --git a/src/assets/salix_dark.svg b/src/assets/salix_dark.svg
new file mode 100644
index 000000000..10de3af4f
--- /dev/null
+++ b/src/assets/salix_dark.svg
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/assets/logo_icon.svg b/src/assets/salix_icon.svg
similarity index 100%
rename from src/assets/logo_icon.svg
rename to src/assets/salix_icon.svg
diff --git a/src/assets/vn.svg b/src/assets/vn.svg
new file mode 100644
index 000000000..23b6df49c
--- /dev/null
+++ b/src/assets/vn.svg
@@ -0,0 +1,158 @@
+
+image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/vn_dark.svg b/src/assets/vn_dark.svg
new file mode 100644
index 000000000..4d53b7b39
--- /dev/null
+++ b/src/assets/vn_dark.svg
@@ -0,0 +1,161 @@
+
+image/svg+xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/assets/vn_icon.svg b/src/assets/vn_icon.svg
new file mode 100644
index 000000000..738c8157c
--- /dev/null
+++ b/src/assets/vn_icon.svg
@@ -0,0 +1,72 @@
+
+
+
+image/svg+xml
\ No newline at end of file
diff --git a/src/components/FormModel.vue b/src/components/FormModel.vue
index 540c37d01..e8a9e4c17 100644
--- a/src/components/FormModel.vue
+++ b/src/components/FormModel.vue
@@ -122,9 +122,24 @@ watch(formUrl, async () => {
{{ t('globals.changesToSave') }}
-
-
-
+
+
+
+
+
+
+
@@ -156,3 +171,12 @@ watch(formUrl, async () => {
color="primary"
/>
+
diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue
index 7d09b09b8..778f6bfb9 100644
--- a/src/components/NavBar.vue
+++ b/src/components/NavBar.vue
@@ -7,6 +7,7 @@ import { useStateStore } from 'stores/useStateStore';
import { useQuasar } from 'quasar';
import PinnedModules from './PinnedModules.vue';
import UserPanel from 'components/UserPanel.vue';
+import VnBreadcrumbs from './common/VnBreadcrumbs.vue';
const { t } = useI18n();
const session = useSession();
@@ -47,7 +48,7 @@ const pinnedModulesRef = ref();
>
@@ -57,10 +58,7 @@ const pinnedModulesRef = ref();
-
- {{ appName }}
-
-
+
@@ -112,6 +110,7 @@ const pinnedModulesRef = ref();
+
diff --git a/src/components/common/VnBreadcrumbs.vue b/src/components/common/VnBreadcrumbs.vue
new file mode 100644
index 000000000..792671e21
--- /dev/null
+++ b/src/components/common/VnBreadcrumbs.vue
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/VnFilterPanel.vue b/src/components/ui/VnFilterPanel.vue
index 68b3a7676..d78c3ba13 100644
--- a/src/components/ui/VnFilterPanel.vue
+++ b/src/components/ui/VnFilterPanel.vue
@@ -20,6 +20,10 @@ const props = defineProps({
required: false,
default: null,
},
+ showAll: {
+ type: Boolean,
+ default: true,
+ },
});
const emit = defineEmits(['refresh', 'clear']);
@@ -29,31 +33,34 @@ const store = arrayData.store;
const userParams = ref({});
onMounted(() => {
- if (props.params) userParams.value = props.params;
- const params = store.userParams;
- if (Object.keys(params).length > 0) {
- userParams.value = Object.assign({}, params);
+ if (props.params) userParams.value = JSON.parse(JSON.stringify(props.params));
+ if (Object.keys(store.userParams).length > 0) {
+ userParams.value = JSON.parse(JSON.stringify(store.userParams));
}
});
const isLoading = ref(false);
async function search() {
- const params = userParams.value;
- for (const param in params) {
- if (params[param] === '' || params[param] === null) {
+ for (const param in userParams.value) {
+ if (userParams.value[param] === '' || userParams.value[param] === null) {
delete userParams.value[param];
delete store.userParams[param];
}
}
-
+ const params = { ...userParams.value };
isLoading.value = true;
await arrayData.addFilter({ params });
+ if (!props.showAll && !Object.values(params).length) store.data = [];
+
isLoading.value = false;
}
async function reload() {
isLoading.value = true;
+ const params = Object.values(userParams.value).filter((param) => param);
+
await arrayData.fetch({ append: false });
+ if (!props.showAll && !params.length) store.data = [];
isLoading.value = false;
emit('refresh');
}
@@ -62,6 +69,7 @@ async function clearFilters() {
userParams.value = {};
isLoading.value = true;
await arrayData.applyFilter({ params: {} });
+ if (!props.showAll) store.data = [];
isLoading.value = false;
emit('clear');
diff --git a/src/components/ui/VnLogo.vue b/src/components/ui/VnLogo.vue
new file mode 100644
index 000000000..3b955289d
--- /dev/null
+++ b/src/components/ui/VnLogo.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
diff --git a/src/components/ui/VnRow.vue b/src/components/ui/VnRow.vue
new file mode 100644
index 000000000..c3c951528
--- /dev/null
+++ b/src/components/ui/VnRow.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/src/components/ui/VnSearchbar.vue b/src/components/ui/VnSearchbar.vue
index af6999b5b..693d6fce2 100644
--- a/src/components/ui/VnSearchbar.vue
+++ b/src/components/ui/VnSearchbar.vue
@@ -105,7 +105,11 @@ async function search() {
class="cursor-pointer"
/>
-
+
{{ props.info }}
diff --git a/src/composables/getUrl.js b/src/composables/getUrl.js
index e020d7f18..f2bd9ddb9 100644
--- a/src/composables/getUrl.js
+++ b/src/composables/getUrl.js
@@ -1,14 +1,11 @@
import axios from 'axios';
export async function getUrl(route, appName = 'salix') {
- let url;
const filter = {
where: { and: [{ appName: appName }, { environment: process.env.NODE_ENV }] },
};
- await axios.get('Urls/findOne', { params: { filter } }).then((res) => {
- url = res.data.url + route;
- });
-
- return url;
+ const { data } = await axios.get('Urls/findOne', { params: { filter } });
+ const url = data.url;
+ return route ? url + route : url;
}
diff --git a/src/composables/useArrayData.js b/src/composables/useArrayData.js
index 4535cde0f..9aff0eaa8 100644
--- a/src/composables/useArrayData.js
+++ b/src/composables/useArrayData.js
@@ -136,7 +136,7 @@ export function useArrayData(key, userOptions) {
}
async function refresh() {
- await fetch({ append: false });
+ if (Object.values(store.userParams).length) await fetch({ append: false });
}
function updateStateParams() {
diff --git a/src/composables/useCamelCase.js b/src/composables/useCamelCase.js
new file mode 100644
index 000000000..5285b022a
--- /dev/null
+++ b/src/composables/useCamelCase.js
@@ -0,0 +1,3 @@
+export function useCamelCase(value) {
+ return value.replace(/[-_](.)/g, (_, char) => char.toUpperCase());
+}
diff --git a/src/css/quasar.variables.scss b/src/css/quasar.variables.scss
index 808bf3468..6a3700561 100644
--- a/src/css/quasar.variables.scss
+++ b/src/css/quasar.variables.scss
@@ -21,6 +21,7 @@ $positive: #21ba45;
$negative: #c10015;
$info: #31ccec;
$warning: #f2c037;
+$vnColor: #8ebb27;
// Pendiente de cuadrar con la base de datos
$success: $positive;
diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js
index eae06dbf0..792bd3965 100644
--- a/src/i18n/en/index.js
+++ b/src/i18n/en/index.js
@@ -77,6 +77,11 @@ export default {
twoFactor: 'Two-Factor',
},
},
+ verifyEmail: {
+ pageTitles: {
+ verifyEmail: 'Email verification',
+ },
+ },
dashboard: {
pageTitles: {
dashboard: 'Dashboard',
diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js
index dc1ace47e..4ce8c23d6 100644
--- a/src/i18n/es/index.js
+++ b/src/i18n/es/index.js
@@ -77,6 +77,11 @@ export default {
twoFactor: 'Doble factor',
},
},
+ verifyEmail: {
+ pageTitles: {
+ verifyEmail: 'Verificación de correo',
+ },
+ },
dashboard: {
pageTitles: {
dashboard: 'Tablón',
diff --git a/src/layouts/OutLayout.vue b/src/layouts/OutLayout.vue
index 6ea14622f..f21e6e568 100644
--- a/src/layouts/OutLayout.vue
+++ b/src/layouts/OutLayout.vue
@@ -80,7 +80,7 @@ const langs = ['en', 'es'];
-
+
@@ -97,15 +97,4 @@ const langs = ['en', 'es'];
min-height: inherit;
flex-direction: column;
}
-
-.formCard {
- max-width: 350px;
- min-width: 300px;
-}
-
-@media (max-width: $breakpoint-xs-max) {
- .formCard {
- min-width: 100%;
- }
-}
diff --git a/src/pages/Claim/Card/ClaimBasicData.vue b/src/pages/Claim/Card/ClaimBasicData.vue
index ddf669dd0..94e447e13 100644
--- a/src/pages/Claim/Card/ClaimBasicData.vue
+++ b/src/pages/Claim/Card/ClaimBasicData.vue
@@ -6,6 +6,7 @@ import { useI18n } from 'vue-i18n';
import { useSession } from 'src/composables/useSession';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue';
+import VnRow from 'components/ui/VnRow.vue';
const route = useRoute();
const { t } = useI18n();
@@ -90,138 +91,119 @@ const statesFilter = {
auto-load
/>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- filter(value, update, workerFilter)
- "
- :rules="validate('claim.claimStateFk')"
- :input-debounce="0"
- >
-
-
-
-
-
-
-
-
- filter(value, update, statesFilter)
- "
- :rules="validate('claim.claimStateFk')"
- :input-debounce="0"
- >
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ filter(value, update, workerFilter)"
+ :rules="validate('claim.claimStateFk')"
+ :input-debounce="0"
+ >
+
+
+
+
+
+
+
+
+ filter(value, update, statesFilter)"
+ :rules="validate('claim.claimStateFk')"
+ :input-debounce="0"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
diff --git a/src/pages/Customer/Card/CustomerBasicData.vue b/src/pages/Customer/Card/CustomerBasicData.vue
index ffd3c3476..08c661f0b 100644
--- a/src/pages/Customer/Card/CustomerBasicData.vue
+++ b/src/pages/Customer/Card/CustomerBasicData.vue
@@ -6,6 +6,7 @@ import { useI18n } from 'vue-i18n';
import { useSession } from 'src/composables/useSession';
import FetchData from 'components/FetchData.vue';
import FormModel from 'components/FormModel.vue';
+import VnRow from 'components/ui/VnRow.vue';
const route = useRoute();
const { t } = useI18n();
@@ -58,121 +59,109 @@ const filterOptions = {
@on-fetch="(data) => (businessTypes = data)"
auto-load
/>
-
-
-
-
-
-
-
-
-
-
- filter(value, update, filterOptions)
- "
- :rules="validate('client.salesPersonFk')"
- :input-debounce="0"
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ filter(value, update, filterOptions)"
+ :rules="validate('client.salesPersonFk')"
+ :input-debounce="0"
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/Customer/CustomerPayments.vue b/src/pages/Customer/CustomerPayments.vue
index 608aca2af..24e5efa39 100644
--- a/src/pages/Customer/CustomerPayments.vue
+++ b/src/pages/Customer/CustomerPayments.vue
@@ -110,12 +110,18 @@ function stateColor(row) {
-
+
-
+
{{ t('Web Payments') }}
@@ -138,7 +144,7 @@ function stateColor(row) {
order="created DESC"
:limit="20"
:offset="50"
- auto-load
+ :auto-load="!!$route?.query.params"
>
@@ -167,6 +173,13 @@ function stateColor(row) {
+
+
+
+ {{ row.id }}
+
+
+
@@ -175,6 +188,13 @@ function stateColor(row) {
+
+
+
+ {{ row.customerName }}
+
+
+
@@ -188,9 +208,9 @@ function stateColor(row) {
-
+
-
+
-
diff --git a/src/pages/Customer/CustomerPaymentsFilter.vue b/src/pages/Customer/CustomerPaymentsFilter.vue
index d2a9160ab..56fb52d79 100644
--- a/src/pages/Customer/CustomerPaymentsFilter.vue
+++ b/src/pages/Customer/CustomerPaymentsFilter.vue
@@ -9,10 +9,14 @@ const props = defineProps({
required: true,
},
});
+
+function isValidNumber(value) {
+ return /^(\d|\d+(\.|,)?\d+)$/.test(value);
+}
-
+
{{ t(`params.${tag.label}`) }}:
@@ -49,9 +53,99 @@ const props = defineProps({
-
+ {
+ if (value.includes(','))
+ params.amount = params.amount.replace(',', '.');
+ }
+ "
+ :rules="[
+ (val) =>
+ isValidNumber(val) || !val || 'Please type a number',
+ ]"
+ >
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -67,12 +161,19 @@ en:
orderFk: Order
clientFk: Customer
amount: Amount
+ from: From
+ to: To
es:
params:
orderFk: Pedido
clientFk: Cliente
amount: Importe
+ from: Desde
+ to: Hasta
Order ID: ID pedido
Customer ID: ID cliente
Amount: Importe
+ Please type a number: Por favor, escriba un número
+ From: Desde
+ To: Hasta
diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue
index 7c0bbbd44..2e4fd91ca 100644
--- a/src/pages/Login/LoginMain.vue
+++ b/src/pages/Login/LoginMain.vue
@@ -8,6 +8,8 @@ import axios from 'axios';
import { useSession } from 'src/composables/useSession';
import { useLogin } from 'src/composables/useLogin';
+import VnLogo from 'components/ui/VnLogo.vue';
+
const quasar = useQuasar();
const session = useSession();
const loginCache = useLogin();
@@ -64,14 +66,8 @@ async function onSubmit() {
-
-
+
+
-
+
diff --git a/src/pages/Login/TwoFactor.vue b/src/pages/Login/TwoFactor.vue
index f14e85418..1c99e8dec 100644
--- a/src/pages/Login/TwoFactor.vue
+++ b/src/pages/Login/TwoFactor.vue
@@ -48,7 +48,7 @@ async function onSubmit() {
}
-
+
{{ t('twoFactor.insert') }}
@@ -77,4 +77,15 @@ async function onSubmit() {
-
+
diff --git a/src/pages/Login/VerifyEmail.vue b/src/pages/Login/VerifyEmail.vue
new file mode 100644
index 000000000..dae20e8b6
--- /dev/null
+++ b/src/pages/Login/VerifyEmail.vue
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+ {
+ "en": {
+ "verifyEmail": "Your email has been successfully verified. You can now log in to enjoy all the features of our platform.",
+ "goToShop": "Go to the shop",
+ "logIn": "Log In"
+ },
+ "es": {
+ "verifyEmail": "Su correo electrónico ha sido verificado con éxito. Ahora puede iniciar sesión para disfrutar de todas las funcionalidades de nuestra plataforma.",
+ "goToShop": "Ir a la tienda",
+ "logIn": "Iniciar sesión"
+ },
+ "fr": {
+ "verifyEmail": "Votre courrier électronique a été vérifié avec succès. Vous pouvez maintenant vous connecter pour profiter de toutes les fonctionnalités de notre plateforme.",
+ "goToShop": "Aller à la boutique",
+ "logIn": "Se connecter"
+ },
+ "pt": {
+ "verifyEmail": "Seu e-mail foi verificado com sucesso. Agora você pode fazer o login para aproveitar todas as funcionalidades da nossa plataforma.",
+ "goToShop": "Ir para a loja",
+ "logIn": "Fazer login"
+ },
+ "it": {
+ "verifyEmail": "La tua email è stata verificata con successo. Ora puoi accedere per godere di tutte le funzionalità della nostra piattaforma.",
+ "goToShop": "Vai al negozio",
+ "logIn": "Accedi"
+ }
+ }
+
+
+
diff --git a/src/pages/Ticket/Card/TicketDescriptor.vue b/src/pages/Ticket/Card/TicketDescriptor.vue
index 25c9dfb1c..641ffee0c 100644
--- a/src/pages/Ticket/Card/TicketDescriptor.vue
+++ b/src/pages/Ticket/Card/TicketDescriptor.vue
@@ -8,6 +8,7 @@ import CardDescriptor from 'components/ui/CardDescriptor.vue';
import TicketDescriptorMenu from './TicketDescriptorMenu.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import useCardDescription from 'src/composables/useCardDescription';
+import WorkerDescriptorProxy from 'src/pages/Worker/Card/WorkerDescriptorProxy.vue';
const $props = defineProps({
id: {
diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
index f55229bcf..95f6a94d9 100644
--- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue
+++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue
@@ -87,7 +87,7 @@ function showSmsDialog(template, customData) {
componentProps: {
phone: phone,
template: template,
- locale: client.user.lang,
+ locale: client?.user?.lang ?? 'default_locale',
data: data,
promise: sendSms,
},
diff --git a/src/pages/Wagon/Card/WagonCard.vue b/src/pages/Wagon/Card/WagonCard.vue
new file mode 100644
index 000000000..18ec121e3
--- /dev/null
+++ b/src/pages/Wagon/Card/WagonCard.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+es:
+ Search customer: Buscar cliente
+ You can search by customer id or name: Puedes buscar por id o nombre del cliente
+
diff --git a/src/router/index.js b/src/router/index.js
index cccf9af6d..ca560e9c9 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -45,7 +45,7 @@ export { Router };
export default route(function (/* { store, ssrContext } */) {
Router.beforeEach(async (to, from, next) => {
const { isLoggedIn } = session;
- const outLayout = ['Login', 'TwoFactor'];
+ const outLayout = ['Login', 'TwoFactor', 'VerifyEmail'];
if (!isLoggedIn() && !outLayout.includes(to.name)) {
return next({ name: 'Login', query: { redirect: to.fullPath } });
}
diff --git a/src/router/modules/route.js b/src/router/modules/route.js
index a3550885c..acda898de 100644
--- a/src/router/modules/route.js
+++ b/src/router/modules/route.js
@@ -21,13 +21,13 @@ export default {
redirect: { name: 'CmrList' },
children: [
{
- path: 'cmr/list',
+ path: 'cmr',
name: 'CmrList',
meta: {
title: 'cmrsList',
icon: 'fact_check',
},
- component: () => import('src/pages/Route/Cmr/CmrList.vue')
+ component: () => import('src/pages/Route/Cmr/CmrList.vue'),
},
],
},
diff --git a/src/router/modules/wagon.js b/src/router/modules/wagon.js
index 02513d5a8..3fb808778 100644
--- a/src/router/modules/wagon.js
+++ b/src/router/modules/wagon.js
@@ -27,7 +27,7 @@ export default {
title: 'wagonsList',
icon: 'vn:trolley',
},
- component: () => import('src/pages/Wagon/WagonList.vue')
+ component: () => import('src/pages/Wagon/WagonList.vue'),
},
{
path: 'create',
@@ -36,7 +36,7 @@ export default {
title: 'wagonCreate',
icon: 'create',
},
- component: () => import('src/pages/Wagon/WagonCreate.vue')
+ component: () => import('src/pages/Wagon/WagonCreate.vue'),
},
{
path: ':id/edit',
@@ -45,7 +45,7 @@ export default {
title: 'wagonEdit',
icon: 'edit',
},
- component: () => import('src/pages/Wagon/WagonCreate.vue')
+ component: () => import('src/pages/Wagon/WagonCreate.vue'),
},
],
},
@@ -62,7 +62,7 @@ export default {
title: 'typesList',
icon: 'view_list',
},
- component: () => import('src/pages/Wagon/Type/WagonTypeList.vue')
+ component: () => import('src/pages/Wagon/Type/WagonTypeList.vue'),
},
{
path: 'create',
@@ -71,7 +71,7 @@ export default {
title: 'typeCreate',
icon: 'create',
},
- component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue')
+ component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue'),
},
{
path: ':id/edit',
@@ -80,9 +80,9 @@ export default {
title: 'typeEdit',
icon: 'edit',
},
- component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue')
+ component: () => import('src/pages/Wagon/Type/WagonTypeCreate.vue'),
},
],
- }
+ },
],
};
diff --git a/src/router/routes.js b/src/router/routes.js
index 4425996b0..e3aa22a06 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -23,6 +23,12 @@ const routes = [
meta: { title: 'twoFactor' },
component: () => import('../pages/Login/TwoFactor.vue'),
},
+ {
+ path: '/verifyEmail',
+ name: 'VerifyEmail',
+ meta: { title: 'verifyEmail' },
+ component: () => import('../pages/Login/VerifyEmail.vue'),
+ },
],
},
{
diff --git a/test/cypress/integration/vnBreadcrumbs.spec.js b/test/cypress/integration/vnBreadcrumbs.spec.js
new file mode 100644
index 000000000..3c839c1c7
--- /dev/null
+++ b/test/cypress/integration/vnBreadcrumbs.spec.js
@@ -0,0 +1,21 @@
+///
+describe('VnBreadcrumbs', () => {
+ const firstCard = '.q-infinite-scroll > :nth-child(1)';
+ const lastBreadcrumb = '.q-breadcrumbs--last > .q-breadcrumbs__el';
+ beforeEach(() => {
+ cy.login('developer');
+ cy.visit('/');
+ });
+
+ it('should not be breadcrumbs', () => {
+ cy.get('.q-breadcrumbs').should('not.exist');
+ });
+
+ it('should get the correct breadcrumbs', () => {
+ cy.visit('#/customer/list');
+ cy.get('.q-breadcrumbs__el').should('have.length', 2);
+
+ cy.get(firstCard).click();
+ cy.get(`${lastBreadcrumb} > .q-icon`).should('have.text', 'launch');
+ });
+});
diff --git a/test/vitest/helper.js b/test/vitest/helper.js
index 4bbdc337a..89cc640fd 100644
--- a/test/vitest/helper.js
+++ b/test/vitest/helper.js
@@ -64,6 +64,7 @@ class FormDataMock {
}
}
global.FormData = FormDataMock;
+global.URL = class URL {};
export function createWrapper(component, options) {
const defaultOptions = {