Vitest migration final step
gitea/salix-front/pipeline/head This commit looks good Details

This commit is contained in:
Joan Sanchez 2023-01-03 14:17:22 +01:00
parent df203ddb9b
commit 9d0d6ad0c8
26 changed files with 13255 additions and 12690 deletions

View File

@ -3,16 +3,17 @@ const { defineConfig } = require('cypress');
module.exports = defineConfig({ module.exports = defineConfig({
e2e: { e2e: {
baseUrl: 'http://localhost:8080/', baseUrl: 'http://localhost:8080/',
fixturesFolder: 'tests/cypress/fixtures', fixturesFolder: 'test/cypress/fixtures',
screenshotsFolder: 'tests/cypress/screenshots', screenshotsFolder: 'test/cypress/screenshots',
supportFile: 'tests/cypress/support/index.js', supportFile: 'test/cypress/support/index.js',
videosFolder: 'tests/cypress/videos', videosFolder: 'test/cypress/videos',
video: true, video: true,
specPattern: 'tests/cypress/integration/*.spec.js', specPattern: 'test/cypress/integration/*.spec.js',
experimentalRunAllSpecs: true,
component: { component: {
componentFolder: 'src', componentFolder: 'src',
testFiles: '**/*.spec.js', testFiles: '**/*.spec.js',
supportFile: 'tests/cypress/support/unit.js', supportFile: 'test/cypress/support/unit.js',
}, },
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
// implement node event listeners here // implement node event listeners here

25121
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,53 @@
{ {
"name": "salix-front", "name": "salix-front",
"version": "0.0.1", "version": "0.0.1",
"description": "Salix frontend", "description": "Salix frontend",
"productName": "Salix", "productName": "Salix",
"author": "Verdnatura", "author": "Verdnatura",
"private": true, "private": true,
"scripts": { "scripts": {
"lint": "eslint --ext .js,.vue ./", "lint": "eslint --ext .js,.vue ./",
"format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore", "format": "prettier --write \"**/*.{js,vue,scss,html,md,json}\" --ignore-path .gitignore",
"test:e2e": "cypress open", "test:e2e": "cypress open",
"test:e2e:ci": "cypress run --browser chromium", "test:e2e:ci": "cypress run --browser chromium",
"test": "echo \"See package.json => scripts for available tests.\" && exit 0", "test": "echo \"See package.json => scripts for available tests.\" && exit 0",
"test:unit": "vitest", "test:unit": "vitest",
"test:unit:ci": "vitest run" "test:unit:ci": "vitest run"
}, },
"dependencies": { "dependencies": {
"@quasar/extras": "^1.15.8", "@quasar/extras": "^1.15.8",
"axios": "^1.2.1", "axios": "^1.2.1",
"pinia": "^2.0.28", "pinia": "^2.0.28",
"quasar": "^2.11.1", "quasar": "^2.11.1",
"validator": "^13.7.0", "validator": "^13.7.0",
"vue": "^3.2.45", "vue": "^3.2.45",
"vue-i18n": "^9.2.2", "vue-i18n": "^9.2.2",
"vue-router": "^4.1.6", "vue-router": "^4.1.6",
"vue-router-mock": "^0.1.9" "vue-router-mock": "^0.1.9"
}, },
"devDependencies": { "devDependencies": {
"@intlify/vite-plugin-vue-i18n": "^3.3.1", "@intlify/vite-plugin-vue-i18n": "^3.3.1",
"@pinia/testing": "^0.0.14", "@pinia/testing": "^0.0.14",
"@quasar/app-vite": "^1.1.3", "@quasar/app-vite": "^1.1.3",
"@quasar/quasar-app-extension-testing-unit-vitest": "^0.1.2", "@quasar/quasar-app-extension-testing-unit-vitest": "^0.1.2",
"@vue/test-utils": "^2.0.0", "@vue/test-utils": "^2.0.0",
"autoprefixer": "^10.4.13", "autoprefixer": "^10.4.13",
"cypress": "^12.2.0", "cypress": "^12.2.0",
"eslint": "^8.30.0", "eslint": "^8.30.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-vue": "^9.8.0", "eslint-plugin-vue": "^9.8.0",
"postcss": "^8.4.20", "postcss": "^8.4.20",
"prettier": "^2.8.1", "prettier": "^2.8.1",
"vitest": "^0.15.0" "vitest": "^0.26.3"
}, },
"engines": { "engines": {
"node": "^18 || ^16 || ^14.19", "node": "^18 || ^16 || ^14.19",
"npm": ">= 6.13.4", "npm": ">= 6.13.4",
"yarn": ">= 1.21.1" "yarn": ">= 1.21.1"
} },
"overrides": {
"@vitejs/plugin-vue": "^4.0.0",
"vite": "^4.0.3",
"vitest": "^0.26.3"
}
} }

View File

@ -106,4 +106,4 @@ axios.interceptors.response.use((response) => {
.body--light { .body--light {
background-color: #eee; background-color: #eee;
} }
</style> </style>

View File

@ -1,77 +0,0 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals';
import { createWrapper } from 'app/test/jest/jestHelpers';
import App from '../App.vue';
import { useSession } from 'src/composables/useSession';
const mockPush = jest.fn();
const mockLoggedIn = jest.fn();
const mockDestroy = jest.fn();
const session = useSession();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
}));
jest.mock('src/composables/useSession', () => ({
useSession: () => ({
isLoggedIn: mockLoggedIn,
destroy: mockDestroy,
}),
}));
describe('App', () => {
let vm;
beforeAll(() => {
const options = {
global: {
stubs: ['router-view'],
},
};
vm = createWrapper(App, options).vm;
});
it('should return a login error message', async () => {
jest.spyOn(vm.quasar, 'notify');
session.isLoggedIn.mockReturnValue(false);
const response = {
response: {
status: 401,
},
};
expect(vm.responseError(response)).rejects.toEqual(expect.objectContaining(response));
expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
message: 'Invalid username or password',
type: 'negative',
})
);
});
it('should return an unauthorized error message', async () => {
jest.spyOn(vm.quasar, 'notify');
session.isLoggedIn.mockReturnValue(true);
const response = {
response: {
status: 401,
},
};
expect(vm.responseError(response)).rejects.toEqual(expect.objectContaining(response));
expect(vm.quasar.notify).toHaveBeenCalledWith(
expect.objectContaining({
message: 'Access denied',
type: 'negative',
})
);
expect(session.destroy).toHaveBeenCalled();
});
});

View File

@ -1,104 +0,0 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals';
import { createWrapper } from 'app/test/jest/jestHelpers';
import Leftmenu from '../LeftMenu.vue';
import { createTestingPinia } from '@pinia/testing';
import { useNavigationStore } from 'src/stores/useNavigationStore';
const mockPush = jest.fn();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
useRoute: () => ({
matched: [],
}),
}));
jest.mock('src/router/modules', () => [
{
path: '/customer',
name: 'Customer',
meta: {
title: 'customers',
icon: 'vn:client',
},
menus: {
main: ['CustomerList', 'CustomerCreate'],
card: ['CustomerBasicData'],
},
children: [
{
path: '',
name: 'CustomerMain',
children: [
{
path: 'list',
name: 'CustomerList',
meta: {
title: 'list',
icon: 'view_list',
},
},
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'createCustomer',
icon: 'vn:addperson',
},
},
],
},
],
},
]);
describe('Leftmenu', () => {
let vm;
let navigation;
beforeAll(async () => {
vm = createWrapper(Leftmenu, {
propsData: {
source: 'main',
},
global: {
plugins: [createTestingPinia({ stubActions: false })],
},
}).vm;
navigation = useNavigationStore();
navigation.modules = ['customer']; // I should mock to have just one module but isn´t working
navigation.fetchPinned = jest.fn().mockReturnValue(Promise.resolve(true));
navigation.getModules = jest.fn().mockReturnValue({
value: [
{
name: 'customer',
title: 'customer.pageTitles.customers',
icon: 'vn:customer',
module: 'customer',
},
],
});
});
it('should return a proper formated object with two child items', async () => {
const expectedMenuItem = [
{
name: 'CustomerList',
title: 'customer.pageTitles.list',
icon: 'view_list',
},
{
name: 'CustomerCreate',
title: 'customer.pageTitles.createCustomer',
icon: 'vn:addperson',
},
];
const firstMenuItem = vm.items[0];
expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
});
});

View File

@ -1,6 +1,10 @@
// app global css in SCSS form // app global css in SCSS form
@import './icons.scss'; @import './icons.scss';
a {
text-decoration: none;
}
.link { .link {
color: $primary; color: $primary;
cursor: pointer; cursor: pointer;

View File

@ -1,46 +0,0 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals';
import { createWrapper, axios } from 'app/test/jest/jestHelpers';
import ClaimDescriptorMenu from '../Card/ClaimDescriptorMenu.vue';
const mockPush = jest.fn();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: {
value: {
params: {
id: 1,
},
},
},
}),
}));
describe('ClaimDescriptorMenu', () => {
let vm;
beforeAll(() => {
vm = createWrapper(ClaimDescriptorMenu, {
propsData: {
claim: {
id: 1,
},
},
}).vm;
});
afterEach(() => {
jest.clearAllMocks();
});
describe('deleteClaim()', () => {
it('should delete the claim', async () => {
jest.spyOn(axios, 'delete').mockResolvedValue({ data: true });
jest.spyOn(vm.quasar, 'notify');
await vm.deleteClaim();
expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining({ type: 'positive' }));
});
});
});

View File

@ -1,10 +0,0 @@
module.exports = {
extends: [
// Removes 'no-undef' lint errors for Jest global functions (`describe`, `it`, etc),
// add Jest-specific lint rules and Jest plugin
// See https://github.com/jest-community/eslint-plugin-jest#recommended
'plugin:jest/recommended',
// Uncomment following line to apply style rules
// 'plugin:jest/style',
],
};

View File

@ -1 +0,0 @@
coverage/*

View File

@ -1,33 +0,0 @@
import { mount, flushPromises } from '@vue/test-utils';
import { installQuasarPlugin, installRouter } from '@quasar/quasar-app-extension-testing-unit-jest';
import { i18n } from 'src/boot/i18n';
import { Notify, Dialog } from 'quasar';
import axios from 'axios';
installQuasarPlugin({
plugins: {
Notify,
Dialog,
},
});
installRouter();
export function createWrapper(component, options) {
const mountOptions = {};
if (options instanceof Object) Object.assign(mountOptions, options);
if (mountOptions.global && mountOptions.global.plugins) {
mountOptions.global.plugins.push(i18n);
} else {
if (!mountOptions.global) mountOptions.global = {};
mountOptions.global.plugins = [i18n];
}
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;
return { vm, wrapper };
}
export { axios, flushPromises };

View File

@ -1,34 +0,0 @@
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest';
import { mount } from '@vue/test-utils';
import { describe, expect, it } from 'vitest';
import ExampleComponent from './demo/ExampleComponent.vue';
installQuasar();
describe('example Component', () => {
it('should mount component with todos', () => {
const wrapper = mount(ExampleComponent, {
props: {
title: 'Hello',
totalCount: 4,
todos: [
{ id: 1, content: 'Hallo' },
{ id: 2, content: 'Hoi' },
],
},
});
expect(wrapper.vm.clickCount).toBe(0);
wrapper.find('.q-item').trigger('click');
expect(wrapper.vm.clickCount).toBe(1);
});
it('should mount component without todos', () => {
const wrapper = mount(ExampleComponent, {
props: {
title: 'Hello',
totalCount: 4,
},
});
expect(wrapper.findAll('.q-item')).toHaveLength(0);
});
});

View File

@ -1,19 +0,0 @@
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest';
import { mount } from '@vue/test-utils';
import { Notify } from 'quasar';
import { describe, expect, it, vi } from 'vitest';
import NotifyComponent from './demo/NotifyComponent.vue';
installQuasar({ plugins: { Notify } });
describe('notify example', () => {
it('should call notify on click', async () => {
expect(NotifyComponent).toBeTruthy();
const wrapper = mount(NotifyComponent, {});
const spy = vi.spyOn(Notify, 'create');
expect(spy).not.toHaveBeenCalled();
wrapper.trigger('click');
expect(spy).toHaveBeenCalled();
});
});

View File

@ -1,44 +0,0 @@
<template>
<div>
<p>{{ title }}</p>
<q-list>
<q-item v-for="todo in todos" :key="todo.id" @click="increment" clickable>
{{ todo.id }} - {{ todo.content }}
</q-item>
</q-list>
<p>Count: {{ todoCount }} / {{ totalCount }}</p>
<p>Active: {{ active ? 'yes' : 'no' }}</p>
<p>Clicks on todos: {{ clickCount }}</p>
</div>
</template>
<script setup>
import { computed, ref } from 'vue';
const props = defineProps({
title: {
type: String,
required: true,
},
todos: {
type: Array,
default() {
return [];
},
},
totalCount: {
type: Number,
required: true,
},
active: Boolean,
});
const clickCount = ref(0);
function increment() {
clickCount.value += 1;
return clickCount.value;
}
const todoCount = computed(() => props.todos.length);
</script>

View File

@ -1,11 +0,0 @@
<template>
<q-btn @click="onClick"> Click me! </q-btn>
</template>
<script setup>
import { Notify } from 'quasar';
function onClick() {
Notify.create('Hello there!');
}
</script>

View File

@ -1,31 +1,12 @@
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest';
import { vi, describe, expect, it, beforeAll } from 'vitest'; import { vi, describe, expect, it, beforeAll } from 'vitest';
// import { createWrapper } from 'app/test/jest/jestHelpers'; import { createWrapper } from 'app/test/vitest/helper';
import { mount } from '@vue/test-utils';
import { i18n } from 'src/boot/i18n';
import { Notify, Dialog } from 'quasar';
import App from 'src/App.vue'; import App from 'src/App.vue';
import { useSession } from 'src/composables/useSession'; import { useSession } from 'src/composables/useSession';
installQuasar({
plugins: {
Notify,
Dialog,
},
});
const mockPush = vi.fn();
const mockLoggedIn = vi.fn(); const mockLoggedIn = vi.fn();
const mockDestroy = vi.fn(); const mockDestroy = vi.fn();
const session = useSession(); const session = useSession();
vi.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
}));
vi.mock('src/composables/useSession', () => ({ vi.mock('src/composables/useSession', () => ({
useSession: () => ({ useSession: () => ({
isLoggedIn: mockLoggedIn, isLoggedIn: mockLoggedIn,
@ -40,10 +21,9 @@ describe('App', () => {
const options = { const options = {
global: { global: {
stubs: ['router-view'], stubs: ['router-view'],
plugins: [i18n],
}, },
}; };
vm = mount(App, options).vm; vm = createWrapper(App, options).vm;
}); });
it('should return a login error message', async () => { it('should return a login error message', async () => {
@ -70,7 +50,7 @@ describe('App', () => {
vi.spyOn(vm.quasar, 'notify'); vi.spyOn(vm.quasar, 'notify');
session.isLoggedIn.mockReturnValue(true); session.isLoggedIn.mockReturnValue(true);
const response = { const response = {
response: { response: {
status: 401, status: 401,

View File

@ -0,0 +1,92 @@
import { vi, describe, expect, it, beforeAll } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import Leftmenu from 'components/LeftMenu.vue';
import { useNavigationStore } from 'src/stores/useNavigationStore';
vi.mock('src/router/modules', () => ({
default: [
{
path: '/customer',
name: 'Customer',
meta: {
title: 'customers',
icon: 'vn:client',
},
menus: {
main: ['CustomerList', 'CustomerCreate'],
card: ['CustomerBasicData'],
},
children: [
{
path: '',
name: 'CustomerMain',
children: [
{
path: 'list',
name: 'CustomerList',
meta: {
title: 'list',
icon: 'view_list',
},
},
{
path: 'create',
name: 'CustomerCreate',
meta: {
title: 'createCustomer',
icon: 'vn:addperson',
},
},
],
},
],
},
],
}));
describe('Leftmenu', () => {
let vm;
let navigation;
beforeAll(() => {
vi.spyOn(axios, 'get').mockResolvedValue({
data: [],
});
vm = createWrapper(Leftmenu, {
propsData: {
source: 'main',
},
}).vm;
navigation = useNavigationStore();
navigation.fetchPinned = vi.fn().mockReturnValue(Promise.resolve(true));
navigation.getModules = vi.fn().mockReturnValue({
value: [
{
name: 'customer',
title: 'customer.pageTitles.customers',
icon: 'vn:customer',
module: 'customer',
},
],
});
});
it('should return a proper formated object with two child items', async () => {
const expectedMenuItem = [
{
name: 'CustomerList',
title: 'customer.pageTitles.list',
icon: 'view_list',
},
{
name: 'CustomerCreate',
title: 'customer.pageTitles.createCustomer',
icon: 'vn:addperson',
},
];
const firstMenuItem = vm.items[0];
expect(firstMenuItem.children).toEqual(expect.arrayContaining(expectedMenuItem));
});
});

View File

@ -1,15 +1,6 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals'; import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/jest/jestHelpers'; import { createWrapper, axios } from 'app/test/vitest/helper';
import Paginate from '../PaginateData.vue'; import Paginate from 'components/PaginateData.vue';
const mockPush = jest.fn();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
}));
describe('Paginate', () => { describe('Paginate', () => {
const expectedUrl = '/api/customers'; const expectedUrl = '/api/customers';
@ -24,7 +15,7 @@ describe('Paginate', () => {
}; };
vm = createWrapper(Paginate, options).vm; vm = createWrapper(Paginate, options).vm;
jest.spyOn(axios, 'get').mockResolvedValue({ vi.spyOn(axios, 'get').mockResolvedValue({
data: [ data: [
{ id: 1, name: 'Tony Stark' }, { id: 1, name: 'Tony Stark' },
{ id: 2, name: 'Jessica Jones' }, { id: 2, name: 'Jessica Jones' },
@ -95,7 +86,7 @@ describe('Paginate', () => {
describe('onLoad()', () => { describe('onLoad()', () => {
it('should call to the done() callback and not increment the pagination', async () => { it('should call to the done() callback and not increment the pagination', async () => {
const index = 1; const index = 1;
const done = jest.fn(); const done = vi.fn();
await vm.onLoad(index, done); await vm.onLoad(index, done);
@ -113,7 +104,7 @@ describe('Paginate', () => {
expect(vm.pagination.page).toEqual(1); expect(vm.pagination.page).toEqual(1);
const index = 1; const index = 1;
const done = jest.fn(); const done = vi.fn();
await vm.onLoad(index, done); await vm.onLoad(index, done);
@ -122,7 +113,7 @@ describe('Paginate', () => {
}); });
it('should call to the done() callback with true as argument to finish pagination', async () => { it('should call to the done() callback with true as argument to finish pagination', async () => {
jest.spyOn(axios, 'get').mockResolvedValue({ vi.spyOn(axios, 'get').mockResolvedValue({
data: [ data: [
{ id: 1, name: 'Tony Stark' }, { id: 1, name: 'Tony Stark' },
{ id: 2, name: 'Jessica Jones' }, { id: 2, name: 'Jessica Jones' },
@ -138,7 +129,7 @@ describe('Paginate', () => {
expect(vm.pagination.page).toEqual(1); expect(vm.pagination.page).toEqual(1);
const index = 1; const index = 1;
const done = jest.fn(); const done = vi.fn();
vm.hasMoreData = false; vm.hasMoreData = false;

View File

@ -1,6 +1,6 @@
import { describe, expect, it, jest } from '@jest/globals'; import { vi, describe, expect, it } from 'vitest';
import { axios, flushPromises } from 'app/test/jest/jestHelpers'; import { axios, flushPromises } from 'app/test/vitest/helper';
import { useRole } from '../useRole'; import { useRole } from 'composables/useRole';
const role = useRole(); const role = useRole();
describe('useRole', () => { describe('useRole', () => {
@ -35,12 +35,12 @@ describe('useRole', () => {
darkMode: false, darkMode: false,
}; };
const expectedRoles = ['salesPerson', 'admin']; const expectedRoles = ['salesPerson', 'admin'];
jest.spyOn(axios, 'get').mockResolvedValue({ vi.spyOn(axios, 'get').mockResolvedValue({
data: { roles: rolesData, user: fetchedUser }, data: { roles: rolesData, user: fetchedUser },
}); });
jest.spyOn(role.state, 'setUser'); vi.spyOn(role.state, 'setUser');
jest.spyOn(role.state, 'setRoles'); vi.spyOn(role.state, 'setRoles');
role.fetch(); role.fetch();
@ -52,6 +52,7 @@ describe('useRole', () => {
role.state.setRoles([]); role.state.setRoles([]);
}); });
}); });
describe('hasAny', () => { describe('hasAny', () => {
it('should return true if a role matched', async () => { it('should return true if a role matched', async () => {
role.state.setRoles(['admin']); role.state.setRoles(['admin']);

View File

@ -1,7 +1,7 @@
import { describe, expect, it, jest } from '@jest/globals'; import { vi, describe, expect, it } from 'vitest';
import { useSession } from '../useSession'; import { axios } from 'app/test/vitest/helper';
import { useState } from '../useState'; import { useSession } from 'composables/useSession';
import { axios } from 'app/test/jest/jestHelpers'; import { useState } from 'composables/useState';
const session = useSession(); const session = useSession();
const state = useState(); const state = useState();
@ -87,7 +87,7 @@ describe('session', () => {
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'];
jest.spyOn(axios, 'get').mockResolvedValue({ vi.spyOn(axios, 'get').mockResolvedValue({
data: { roles: rolesData, user: expectedUser }, data: { roles: rolesData, user: expectedUser },
}); });
@ -109,7 +109,7 @@ describe('session', () => {
it('should fetch the user roles and then set token in the localStorage', async () => { it('should fetch the user roles and then set token in the localStorage', async () => {
const expectedRoles = ['salesPerson', 'admin']; const expectedRoles = ['salesPerson', 'admin'];
jest.spyOn(axios, 'get').mockResolvedValue({ vi.spyOn(axios, 'get').mockResolvedValue({
data: { roles: rolesData, user: expectedUser }, data: { roles: rolesData, user: expectedUser },
}); });

View File

@ -0,0 +1,31 @@
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/vitest/helper';
import ClaimDescriptorMenu from 'pages/Claim/Card/ClaimDescriptorMenu.vue';
describe('ClaimDescriptorMenu', () => {
let vm;
beforeAll(() => {
vm = createWrapper(ClaimDescriptorMenu, {
propsData: {
claim: {
id: 1,
},
},
}).vm;
});
afterEach(() => {
vi.clearAllMocks();
});
describe('deleteClaim()', () => {
it('should delete the claim', async () => {
vi.spyOn(axios, 'delete').mockResolvedValue({ data: true });
vi.spyOn(vm.quasar, 'notify');
await vm.deleteClaim();
expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining({ type: 'positive' }));
});
});
});

View File

@ -1,15 +1,6 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals'; import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/jest/jestHelpers'; import { createWrapper, axios } from 'app/test/vitest/helper';
import Login from '../LoginMain.vue'; import Login from 'pages/Login/LoginMain.vue';
const mockPush = jest.fn();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
}));
describe('Login', () => { describe('Login', () => {
let vm; let vm;
@ -18,7 +9,7 @@ describe('Login', () => {
}); });
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); vi.clearAllMocks();
}); });
it('should successfully set the token into session', async () => { it('should successfully set the token into session', async () => {
@ -31,9 +22,9 @@ describe('Login', () => {
darkMode: false, darkMode: false,
}, },
}; };
jest.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } }); vi.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } });
jest.spyOn(axios, 'get').mockResolvedValue({ data: { roles: [], user: expectedUser } }); vi.spyOn(axios, 'get').mockResolvedValue({ data: { roles: [], user: expectedUser } });
jest.spyOn(vm.quasar, 'notify'); vi.spyOn(vm.quasar, 'notify');
expect(vm.session.getToken()).toEqual(''); expect(vm.session.getToken()).toEqual('');
@ -45,8 +36,8 @@ describe('Login', () => {
}); });
it('should not set the token into session if any error occurred', async () => { it('should not set the token into session if any error occurred', async () => {
jest.spyOn(axios, 'post').mockReturnValue({ data: null }); vi.spyOn(axios, 'post').mockReturnValue({ data: null });
jest.spyOn(vm.quasar, 'notify'); vi.spyOn(vm.quasar, 'notify');
await vm.onSubmit(); await vm.onSubmit();

View File

@ -1,32 +1,17 @@
import { jest, describe, expect, it, beforeAll } from '@jest/globals'; import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
import { createWrapper, axios } from 'app/test/jest/jestHelpers'; import { createWrapper, axios } from 'app/test/vitest/helper';
import TicketBoxing from '../TicketBoxing.vue'; import TicketBoxing from 'pages/Ticket/Card/TicketBoxing.vue';
const mockPush = jest.fn();
jest.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: {
value: {
params: {
id: 1,
},
},
},
}),
}));
// #4836 - Investigate how to test q-drawer outside // #4836 - Investigate how to test q-drawer outside
// q-layout or how to teleport q-drawer inside // q-layout or how to teleport q-drawer inside
xdescribe('TicketBoxing', () => { describe.skip('TicketBoxing', () => {
let vm; let vm;
beforeAll(() => { beforeAll(() => {
vm = createWrapper(TicketBoxing).vm; vm = createWrapper(TicketBoxing).vm;
}); });
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); vi.clearAllMocks();
}); });
describe('getVideoList()', () => { describe('getVideoList()', () => {
@ -38,8 +23,8 @@ xdescribe('TicketBoxing', () => {
}; };
const videoList = ['2022-01-01T01-01-00.mp4', '2022-02-02T02-02-00.mp4', '2022-03-03T03-03-00.mp4']; const videoList = ['2022-01-01T01-01-00.mp4', '2022-02-02T02-02-00.mp4', '2022-03-03T03-03-00.mp4'];
jest.spyOn(axios, 'get').mockResolvedValue({ data: videoList }); vi.spyOn(axios, 'get').mockResolvedValue({ data: videoList });
jest.spyOn(vm.quasar, 'notify'); vi.spyOn(vm.quasar, 'notify');
await vm.getVideoList(expeditionId, timed); await vm.getVideoList(expeditionId, timed);
@ -54,8 +39,8 @@ xdescribe('TicketBoxing', () => {
max: 2, max: 2,
}; };
jest.spyOn(axios, 'get').mockResolvedValue({ data: [] }); vi.spyOn(axios, 'get').mockResolvedValue({ data: [] });
jest.spyOn(vm.quasar, 'notify'); vi.spyOn(vm.quasar, 'notify');
await vm.getVideoList(expeditionId, timed); await vm.getVideoList(expeditionId, timed);

52
test/vitest/helper.js Normal file
View File

@ -0,0 +1,52 @@
import { installQuasar } from '@quasar/quasar-app-extension-testing-unit-vitest';
import { mount, flushPromises } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import { vi } from 'vitest';
import { i18n } from 'src/boot/i18n';
import { Notify, Dialog } from 'quasar';
import axios from 'axios';
installQuasar({
plugins: {
Notify,
Dialog,
},
});
const mockPush = vi.fn();
vi.mock('vue-router', () => ({
useRouter: () => ({
push: mockPush,
currentRoute: { value: 'myCurrentRoute' },
}),
useRoute: () => ({
matched: [],
}),
}));
export function createWrapper(component, options) {
const pinia = createTestingPinia({ createSpy: vi.fn, stubActions: false });
const defaultOptions = {
global: {
plugins: [i18n, pinia],
},
};
const mountOptions = Object.assign({}, defaultOptions);
if (options instanceof Object) {
Object.assign(mountOptions, options);
if (options.global) {
mountOptions.global.plugins = defaultOptions.global.plugins;
}
}
const wrapper = mount(component, mountOptions);
const vm = wrapper.vm;
return { vm, wrapper };
}
export { axios, flushPromises };

View File

@ -1,13 +0,0 @@
import { beforeEach } from 'vitest';
import { createRouterMock, injectRouterMock, VueRouterMock } from 'vue-router-mock';
import { config } from '@vue/test-utils';
// https://github.com/posva/vue-router-mock
export function installRouter(options) {
beforeEach(() => {
const router = createRouterMock(options);
injectRouterMock(router);
});
config.plugins.VueWrapper.install(VueRouterMock);
}

View File

@ -2,6 +2,8 @@ import { defineConfig } from 'vitest/config';
import vue from '@vitejs/plugin-vue'; import vue from '@vitejs/plugin-vue';
import { quasar, transformAssetUrls } from '@quasar/vite-plugin'; import { quasar, transformAssetUrls } from '@quasar/vite-plugin';
import jsconfigPaths from 'vite-jsconfig-paths'; import jsconfigPaths from 'vite-jsconfig-paths';
import vueI18n from '@intlify/vite-plugin-vue-i18n';
import path from 'path';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
@ -22,6 +24,9 @@ export default defineConfig({
quasar({ quasar({
sassVariables: 'src/quasar-variables.scss', sassVariables: 'src/quasar-variables.scss',
}), }),
vueI18n({
include: path.resolve(__dirname, 'src/i18n/**'),
}),
jsconfigPaths(), jsconfigPaths(),
], ],
}); });