Move TimeOff test to vite
All checks were successful
CI / Go tests & lint (push) Successful in 7s
CI / Frontend tests & type-check (push) Successful in 26s
CI / Go tests & lint (pull_request) Successful in 7s
CI / Frontend tests & type-check (pull_request) Successful in 24s

This commit is contained in:
2026-04-09 10:48:45 -03:00
parent 07f11fa94e
commit 704f11cec3
2 changed files with 20 additions and 45 deletions

30
web/package-lock.json generated
View File

@@ -8,7 +8,6 @@
"name": "web", "name": "web",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@types/react-router-dom": "^5.3.3",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4",
"react-router-dom": "^7.13.1" "react-router-dom": "^7.13.1"
@@ -835,12 +834,6 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/history": {
"version": "4.7.11",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
"integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
"license": "MIT"
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "25.5.2", "version": "25.5.2",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
@@ -855,6 +848,7 @@
"version": "19.2.14", "version": "19.2.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
"integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.2.2" "csstype": "^3.2.2"
@@ -870,27 +864,6 @@
"@types/react": "^19.2.0" "@types/react": "^19.2.0"
} }
}, },
"node_modules/@types/react-router": {
"version": "5.1.20",
"resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
"integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
"license": "MIT",
"dependencies": {
"@types/history": "^4.7.11",
"@types/react": "*"
}
},
"node_modules/@types/react-router-dom": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
"integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
"license": "MIT",
"dependencies": {
"@types/history": "^4.7.11",
"@types/react": "*",
"@types/react-router": "*"
}
},
"node_modules/@vitejs/plugin-react": { "node_modules/@vitejs/plugin-react": {
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.1.tgz",
@@ -1162,6 +1135,7 @@
"version": "3.2.3", "version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/data-urls": { "node_modules/data-urls": {

View File

@@ -1,11 +1,12 @@
import React from 'react'; import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { vi, type Mock } from 'vitest';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import TimeOff from './TimeOff'; import TimeOff from './TimeOff';
import { api, TimeOffRequest, ApiError } from '../api'; import { api, TimeOffRequest, ApiError } from '../api';
import { AuthProvider } from '../auth'; import { AuthProvider } from '../auth';
jest.mock('../api', () => { vi.mock('../api', () => {
class MockApiError extends Error { class MockApiError extends Error {
status: number; status: number;
data: any; data: any;
@@ -17,24 +18,24 @@ jest.mock('../api', () => {
} }
return { return {
api: { api: {
listTimeOff: jest.fn(), listTimeOff: vi.fn(),
createTimeOff: jest.fn(), createTimeOff: vi.fn(),
updateTimeOff: jest.fn(), updateTimeOff: vi.fn(),
deleteTimeOff: jest.fn(), deleteTimeOff: vi.fn(),
reviewTimeOff: jest.fn(), reviewTimeOff: vi.fn(),
getRemovedShifts: jest.fn(), getRemovedShifts: vi.fn(),
listVolunteers: jest.fn(), listVolunteers: vi.fn(),
}, },
ApiError: MockApiError, ApiError: MockApiError,
}; };
}); });
const mockListTimeOff = api.listTimeOff as jest.Mock; const mockListTimeOff = api.listTimeOff as Mock;
const mockCreateTimeOff = api.createTimeOff as jest.Mock; const mockCreateTimeOff = api.createTimeOff as Mock;
const mockDeleteTimeOff = api.deleteTimeOff as jest.Mock; const mockDeleteTimeOff = api.deleteTimeOff as Mock;
const mockReviewTimeOff = api.reviewTimeOff as jest.Mock; const mockReviewTimeOff = api.reviewTimeOff as Mock;
const mockGetRemovedShifts = api.getRemovedShifts as jest.Mock; const mockGetRemovedShifts = api.getRemovedShifts as Mock;
const mockListVolunteers = api.listVolunteers as jest.Mock; const mockListVolunteers = api.listVolunteers as Mock;
function buildFakeJWT(payload: object): string { function buildFakeJWT(payload: object): string {
const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' })); const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' }));
@@ -90,7 +91,7 @@ function renderAsAdmin() {
} }
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); vi.clearAllMocks();
localStorage.clear(); localStorage.clear();
mockListVolunteers.mockResolvedValue([]); mockListVolunteers.mockResolvedValue([]);
}); });
@@ -147,10 +148,10 @@ describe('TimeOff page', () => {
it('shows conflict warning on 409 and allows confirmation', async () => { it('shows conflict warning on 409 and allows confirmation', async () => {
mockListTimeOff.mockResolvedValue([]); mockListTimeOff.mockResolvedValue([]);
const { ApiError: MockApiError } = jest.requireMock('../api'); const { ApiError: MockApiError } = await vi.importMock<typeof import('../api')>('../api');
mockCreateTimeOff mockCreateTimeOff
.mockRejectedValueOnce( .mockRejectedValueOnce(
new MockApiError('conflict', 409, { new (MockApiError as any)('conflict', 409, {
message: 'Time off conflicts with assigned shifts.', message: 'Time off conflicts with assigned shifts.',
conflicts: [ conflicts: [
{ instance_id: 100, name: 'Morning Walk', date: '2026-06-01', start_time: '08:00', end_time: '12:00' }, { instance_id: 100, name: 'Morning Walk', date: '2026-06-01', start_time: '08:00', end_time: '12:00' },