All checks were successful
Vercel Production Deployment / Deploy-Production (push) Successful in 1m1s
134 lines
3.7 KiB
JavaScript
134 lines
3.7 KiB
JavaScript
import { afterEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
const importService = async (supabaseMock) => {
|
|
vi.resetModules();
|
|
vi.doMock('./supabaseClient', () => ({
|
|
supabase: supabaseMock
|
|
}));
|
|
return import('./assessmentShareService');
|
|
};
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.resetModules();
|
|
vi.doUnmock('./supabaseClient');
|
|
delete globalThis.window;
|
|
});
|
|
|
|
describe('assessmentShareService', () => {
|
|
it('creates a share link with the current browser URL', async () => {
|
|
globalThis.window = {
|
|
location: {
|
|
origin: 'https://pat.example.com',
|
|
pathname: '/manager'
|
|
}
|
|
};
|
|
|
|
const rpc = vi.fn().mockResolvedValue({
|
|
data: { share_token: 'token-123' },
|
|
error: null
|
|
});
|
|
|
|
const { createAssessmentShareLink } = await importService({ rpc });
|
|
const result = await createAssessmentShareLink({ id: 'assessment-1' });
|
|
|
|
expect(rpc).toHaveBeenCalledWith('create_or_get_assessment_share', {
|
|
p_assessment_id: 'assessment-1'
|
|
});
|
|
expect(result).toEqual({
|
|
token: 'token-123',
|
|
url: 'https://pat.example.com/manager?share=token-123'
|
|
});
|
|
});
|
|
|
|
it('maps profile visibility RPC errors to a user-facing German message', async () => {
|
|
const rpc = vi.fn().mockResolvedValue({
|
|
data: null,
|
|
error: { message: 'Tests are hidden in the profile' }
|
|
});
|
|
|
|
const { createAssessmentShareLink } = await importService({ rpc });
|
|
|
|
await expect(createAssessmentShareLink({ id: 'assessment-1' })).rejects.toThrow(
|
|
'Deine Tests sind im Profil aktuell nicht sichtbar.'
|
|
);
|
|
});
|
|
|
|
it('lists existing shares by assessment id', async () => {
|
|
const inMock = vi.fn().mockResolvedValue({
|
|
data: [
|
|
{ assessment_id: 'a1', share_token: 'share-a1' },
|
|
{ assessment_id: 'a2', share_token: 'share-a2' }
|
|
],
|
|
error: null
|
|
});
|
|
const selectMock = vi.fn(() => ({ in: inMock }));
|
|
const fromMock = vi.fn(() => ({ select: selectMock }));
|
|
|
|
const { listAssessmentShares } = await importService({ from: fromMock });
|
|
const result = await listAssessmentShares(['a1', 'a2']);
|
|
|
|
expect(fromMock).toHaveBeenCalledWith('assessment_shares');
|
|
expect(selectMock).toHaveBeenCalledWith('assessment_id, share_token');
|
|
expect(inMock).toHaveBeenCalledWith('assessment_id', ['a1', 'a2']);
|
|
expect(result).toEqual({
|
|
a1: 'share-a1',
|
|
a2: 'share-a2'
|
|
});
|
|
});
|
|
|
|
it('hydrates shared assessments and recalculates derived exercise values', async () => {
|
|
const rpc = vi.fn().mockResolvedValue({
|
|
data: [
|
|
{
|
|
id: 'shared-1',
|
|
pat_type: 'PAT 2',
|
|
datum: '2026-03-28',
|
|
name: 'Max Mustermann',
|
|
exercises: [
|
|
{
|
|
name: 'Gerade Einsteiger',
|
|
soll: 6,
|
|
faktor: 10,
|
|
values: ['2', '4', '']
|
|
},
|
|
{
|
|
name: 'Split Drill',
|
|
soll: 4,
|
|
faktor: 5,
|
|
subA: ['1', '3'],
|
|
subB: ['5', ''],
|
|
subLabels: ['A', 'B']
|
|
}
|
|
]
|
|
}
|
|
],
|
|
error: null
|
|
});
|
|
|
|
const { getSharedAssessment } = await importService({ rpc });
|
|
const result = await getSharedAssessment('share-token');
|
|
|
|
expect(rpc).toHaveBeenCalledWith('get_shared_assessment', {
|
|
p_share_token: 'share-token'
|
|
});
|
|
expect(result).toMatchObject({
|
|
id: 'shared-1',
|
|
patType: 'PAT 2',
|
|
datum: '2026-03-28',
|
|
name: 'Max Mustermann'
|
|
});
|
|
expect(result.exercises[0]).toMatchObject({
|
|
name: 'Gerade Einsteiger',
|
|
durchschnitt: 3,
|
|
points: 30
|
|
});
|
|
expect(result.exercises[1]).toMatchObject({
|
|
name: 'Split Drill',
|
|
durchschnitt: 3,
|
|
points: 15,
|
|
subLabels: ['A', 'B']
|
|
});
|
|
});
|
|
});
|