Files
jobtrackingapp/job-tracker-ui/import-tests/admin-processing-docling.spec.ts
T

48 lines
3.9 KiB
TypeScript

import { expect, test, type APIRequestContext } from '@playwright/test';
import path from 'node:path';
const api = 'http://localhost:5302/api';
const password = 'E2ePassword123!';
async function login(client: APIRequestContext, email: string) {
expect((await client.post(`${api}/auth/login`, { data: { email, password } })).status()).toBe(200);
const me = await (await client.get(`${api}/auth/me`)).json();
return { id: me.id as string, headers: { 'X-CSRF-TOKEN': (await client.storageState()).cookies.find(cookie => cookie.name === 'XSRF-TOKEN')!.value, 'X-Session-Context': me.sessionContext as string } };
}
test('real Docling produces owner-scoped administrator history without exposing source text', async ({ page, playwright }, info) => {
await page.context().route('**/*', route => ['localhost', '127.0.0.1'].includes(new URL(route.request().url()).hostname) ? route.continue() : route.abort());
const admin = await playwright.request.newContext();
try {
const administrator = await login(admin, 'e2e@example.test');
const email = `processing-docling-${Date.now()}@example.test`;
expect((await admin.post(`${api}/users`, { headers: administrator.headers, data: { email, password, roles: ['Premium'] } })).status()).toBe(200);
const owner = await login(page.request, email);
await page.goto('/career?section=import');
await page.locator('input[type=file][accept*=".pdf"]').setInputFiles(path.resolve(process.env.CV_IMPORT_FIXTURE_ROOT || '../.artifacts/cv-import/corpus-02', 'dev-en-simple.pdf'));
await expect.poll(async () => (await (await page.request.get(`${api}/profile-cv/runs`)).json())[0]?.operation?.status, { timeout: 90000 }).toBe('succeeded');
const run = (await (await page.request.get(`${api}/profile-cv/runs`)).json())[0];
const id = run.operation.id;
expect(run.status).toBe('pending_review');
expect((await admin.get(`${api}/profile-cv/runs/${run.id}/source`)).status()).toBe(404);
const history = await (await admin.get(`${api}/admin/processing/${id}/events`)).json();
expect(history.items.map((item: { kind: string }) => item.kind)).toEqual(['Created', 'Claimed', ...Array(7).fill('StageChanged'), 'Completed']);
expect(history.items.filter((item: { kind: string }) => item.kind === 'StageChanged').map((item: { stage: string }) => item.stage)).toEqual(['cv_validating_file', 'cv_extracting', 'cv_identifying_sections', 'cv_analysing', 'cv_validating_details', 'cv_preparing_review', 'cv_review_ready']);
const detail = await (await admin.get(`${api}/admin/processing/${id}`)).json();
expect(detail.owner.id).toBe(owner.id);
expect(detail.document.name).toBe('dev-en-simple.pdf');
expect(detail.document.pages).toBeGreaterThan(0);
expect(detail.worker).toBe('document');
expect(detail.workerEnabled).toBe(true);
for (const field of ['rawExtractedText', 'documentJson', 'structuredProfileJson', 'leaseToken', 'failureMessage', 'resultReference']) expect(detail).not.toHaveProperty(field);
await login(page.request, 'e2e@example.test');
await page.goto('/admin/processing');
await page.getByLabel('Owner ID', { exact: true }).fill(owner.id);
await page.getByRole('button', { name: 'Apply filters', exact: true }).click();
await page.getByRole('button', { name: `View processing details ${id}`, exact: true }).click();
await expect(page.getByText(/^Processing completed/)).toBeVisible();
await expect(page.getByLabel('Correlation ID', { exact: true })).toHaveValue(id);
await page.screenshot({ path: info.outputPath('real-docling-processing-history.png'), fullPage: true });
await info.attach('real-parser-evidence-limit', { body: 'Actual pinned Docling conversion and deterministic interpretation; no generative model inference or model accuracy acceptance. Administrator source-download access remains denied by the ordinary ownership API.', contentType: 'text/plain' });
} finally { await admin.dispose(); }
});