fix(capacity): stabilize PTO flows and calendar consistency
Make PTO creation immediately approved, add PTO deletion, and ensure cache invalidation updates individual/team/revenue capacity consistently. Harden holiday duplicate handling (422), support PTO-day availability overrides without disabling edits, and align tests plus OpenSpec artifacts with the new behavior.
This commit is contained in:
19
frontend/tests/unit/api-error-sanitization.spec.ts
Normal file
19
frontend/tests/unit/api-error-sanitization.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { GENERIC_SERVER_ERROR_MESSAGE, sanitizeApiErrorMessage } from '$lib/services/api';
|
||||
|
||||
describe('sanitizeApiErrorMessage', () => {
|
||||
it('replaces HTML payloads with the generic server error message', () => {
|
||||
const htmlMessage = '<!DOCTYPE html><html><body>SQL error</body></html>';
|
||||
expect(sanitizeApiErrorMessage(htmlMessage)).toBe(GENERIC_SERVER_ERROR_MESSAGE);
|
||||
});
|
||||
|
||||
it('replaces SQLSTATE content with the generic server error message', () => {
|
||||
const sqlMessage = 'SQLSTATE[HY000]: General error: 1 Unknown column';
|
||||
expect(sanitizeApiErrorMessage(sqlMessage)).toBe(GENERIC_SERVER_ERROR_MESSAGE);
|
||||
});
|
||||
|
||||
it('returns short API messages unchanged', () => {
|
||||
const userMessage = 'User not found';
|
||||
expect(sanitizeApiErrorMessage(userMessage)).toBe(userMessage);
|
||||
});
|
||||
});
|
||||
40
frontend/tests/unit/capacity-api.spec.ts
Normal file
40
frontend/tests/unit/capacity-api.spec.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('$lib/services/api', () => ({
|
||||
api: {
|
||||
get: vi.fn()
|
||||
}
|
||||
}));
|
||||
|
||||
import { getTeamCapacity } from '$lib/api/capacity';
|
||||
import { api } from '$lib/services/api';
|
||||
|
||||
describe('capacity api mapping', () => {
|
||||
it('maps legacy team capacity payload keys', async () => {
|
||||
vi.mocked(api.get).mockResolvedValueOnce({
|
||||
month: '2026-02',
|
||||
person_days: 10.5,
|
||||
hours: 84,
|
||||
members: []
|
||||
});
|
||||
|
||||
const payload = await getTeamCapacity('2026-02');
|
||||
|
||||
expect(payload.total_person_days).toBe(10.5);
|
||||
expect(payload.total_hours).toBe(84);
|
||||
});
|
||||
|
||||
it('maps new team capacity payload keys', async () => {
|
||||
vi.mocked(api.get).mockResolvedValueOnce({
|
||||
month: '2026-03',
|
||||
total_person_days: 12,
|
||||
total_hours: 96,
|
||||
members: []
|
||||
});
|
||||
|
||||
const payload = await getTeamCapacity('2026-03');
|
||||
|
||||
expect(payload.total_person_days).toBe(12);
|
||||
expect(payload.total_hours).toBe(96);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user