From dd6bdbaaed282bb4065a8298b9aecc3a6e34b30c Mon Sep 17 00:00:00 2001 From: Codex Date: Fri, 30 Oct 2026 11:09:23 +0000 Subject: [PATCH] test: expose current backend integration contract --- README.md | 6 ++++-- docs/validation.md | 15 +++++++-------- package.json | 1 + tests/integration/real-backend.mjs | 7 ++----- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index e9673f3..262f05b 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,10 @@ npm run test:integration:automation ``` Browser tests use explicit fixtures and do not call a paid model. The optional -`tests/integration/real-backend.mjs` path runs the real FastAPI service against -the loopback provider in `tests/fixtures/llm-stub.py`. +`npm run test:integration:backend` path runs against separately started UI and +FastAPI processes using the loopback provider in `tests/fixtures/llm-stub.py`. +It is intentionally not part of CI because it orchestrates sibling-repository +processes; it never needs a live provider key. ## Repository structure diff --git a/docs/validation.md b/docs/validation.md index 9d8eedd..d19c7fb 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -5,10 +5,9 @@ requests are outside this record. This is dated evidence for the initial backend revision named below, not a statement of the current FastAPI contract. The current contract is maintained in -[ui-foundation.md](ui-foundation.md): successful project history now includes the -assistant reply and provider failures return HTTP 502. The integration fixture and -UI copy still encode the older history expectation and require a functional -follow-up before this check can be rerun against current FastAPI `main`. +[ui-foundation.md](ui-foundation.md): successful project history includes the +assistant reply and provider failures return HTTP 502. The optional +`npm run test:integration:backend` fixture now checks that current contract. | Check | Result | | ------------------------------------------------------------------- | --------------------------------------------------------------------------- | @@ -34,10 +33,10 @@ Browser → Next route handler → public backend is disabled and its SQLite database is disposable. There are no browser API mocks in this check and no real provider credentials are used. -The UI creates a project, displays a reply and reloads the saved input request -after reopening the route. It explicitly verifies that the assistant response -does not reappear after reload, matching the backend's current persistence -contract. Health 200 and optional behavior 404 are also checked. +The UI creates a project, displays a reply and reloads the successful transcript +after reopening the route. The current integration fixture verifies that both +the submitted message and assistant reply persist. Health 200 and optional +behavior 404 are also checked. A regression covers Next's internal hostname differing from the browser Host. The proxy accepts valid same-origin POSTs while rejecting cross-origin writes. diff --git a/package.json b/package.json index 1ced2b5..7d1bfed 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "test:watch": "vitest", "test:e2e": "playwright test", "test:integration:automation": "node tests/integration/automation-proxy.mjs", + "test:integration:backend": "node tests/integration/real-backend.mjs", "check": "npm run typecheck && npm run lint && npm test", "format:check": "prettier --check .", "format": "prettier --write ." diff --git a/tests/integration/real-backend.mjs b/tests/integration/real-backend.mjs index dba383e..7fc529d 100644 --- a/tests/integration/real-backend.mjs +++ b/tests/integration/real-backend.mjs @@ -47,10 +47,7 @@ try { await page.goto(`${base}${projectPath}`); await page.getByText("История запросов проекта", { exact: true }).click(); await expect(page.getByText(/user: Проверка приложения/)).toBeVisible(); - // The backend stored only the input; do not pretend the reply persisted. - await expect( - page.getByText("Локальная проверка: Проверка приложения", { exact: true }), - ).toHaveCount(0); + await expect(page.getByText(/assistant: Локальная проверка: Проверка приложения/)).toBeVisible(); await page.setViewportSize({ width: 390, height: 844 }); await page.screenshot({ path: `${destination}/project-mobile-dark.png`, fullPage: true }); expect(errors).toEqual([]); @@ -58,7 +55,7 @@ try { JSON.stringify({ result: "PASS", stack: "browser -> Next proxy -> real FastAPI -> explicit loopback LLM fixture", - persistedRequestVerified: true, + persistedTranscriptVerified: true, provider: "fixture", projectPath, screenshots: destination,