Stabilize runtime auth and E2E coverage
This commit is contained in:
parent
6a3e3b541c
commit
188e899394
133 changed files with 55987 additions and 6775 deletions
95
apps/web/e2e/session-persistence.spec.ts
Normal file
95
apps/web/e2e/session-persistence.spec.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { fetchAvailablePersona, signInAsLearner, signInAsTeacher } from "./support";
|
||||
|
||||
interface SessionStartResponse {
|
||||
session_id: string;
|
||||
degraded: boolean;
|
||||
}
|
||||
|
||||
async function expectResponseOk(response: { ok: () => boolean; text: () => Promise<string> }) {
|
||||
if (!response.ok()) {
|
||||
expect(response.ok(), await response.text()).toBeTruthy();
|
||||
}
|
||||
}
|
||||
|
||||
async function createSessionWithTurn(page: Page) {
|
||||
const persona = await fetchAvailablePersona(page);
|
||||
const startedResponse = await page.request.post("/api/sessions", {
|
||||
data: {
|
||||
persona_code: persona.code,
|
||||
theory_mode: "humanistic",
|
||||
},
|
||||
});
|
||||
await expectResponseOk(startedResponse);
|
||||
|
||||
const started = (await startedResponse.json()) as SessionStartResponse;
|
||||
expect(started.degraded).toBe(false);
|
||||
|
||||
let turnResponse = await page.request.post(`/api/sessions/${started.session_id}/turn`, {
|
||||
data: {
|
||||
text: "오늘 많이 버거웠겠어요. 지금 가장 크게 남아 있는 마음은 어떤 건가요?",
|
||||
},
|
||||
});
|
||||
for (let attempt = 0; attempt < 2 && !turnResponse.ok(); attempt += 1) {
|
||||
await page.waitForTimeout(1000);
|
||||
turnResponse = await page.request.post(`/api/sessions/${started.session_id}/turn`, {
|
||||
data: {
|
||||
text: "조금 천천히 이야기해도 괜찮습니다. 지금 마음에 남는 장면이 있나요?",
|
||||
},
|
||||
});
|
||||
}
|
||||
let expectedMinTurns = 2;
|
||||
if (!turnResponse.ok()) {
|
||||
expect(turnResponse.status(), await turnResponse.text()).toBe(503);
|
||||
expectedMinTurns = 1;
|
||||
}
|
||||
|
||||
const endedResponse = await page.request.post(`/api/sessions/${started.session_id}/end`);
|
||||
await expectResponseOk(endedResponse);
|
||||
|
||||
return { sessionId: started.session_id, expectedMinTurns };
|
||||
}
|
||||
|
||||
test.describe("session persistence", () => {
|
||||
test("persists learner turns into DB-backed review and teacher dashboard @single-run", async ({ page }) => {
|
||||
await signInAsLearner(page);
|
||||
const { sessionId, expectedMinTurns } = await createSessionWithTurn(page);
|
||||
|
||||
const reviewResponse = await page.request.get(`/api/sessions/${sessionId}/review`);
|
||||
await expectResponseOk(reviewResponse);
|
||||
const review = await reviewResponse.json();
|
||||
expect(review.session_id).toBe(sessionId);
|
||||
expect(review.turns.length).toBeGreaterThanOrEqual(expectedMinTurns);
|
||||
expect(review.turns[0].speaker).toBe("learner");
|
||||
if (review.reviewReady) {
|
||||
expect(review.degraded).toBe(false);
|
||||
expect(review.summary).toContain("평가 AI");
|
||||
} else {
|
||||
expect(review.degraded).toBe(true);
|
||||
expect(review.rubric).toHaveLength(0);
|
||||
expect(review.goodMoments).toHaveLength(0);
|
||||
expect(review.growthPoints).toHaveLength(0);
|
||||
expect(review.summary).not.toContain("잘한 구체적");
|
||||
}
|
||||
|
||||
const hasClientTurn = review.turns.some(
|
||||
(turn: { speaker: string }) => turn.speaker === "client",
|
||||
);
|
||||
if (hasClientTurn) {
|
||||
expect(review.clientFeedback).toEqual(expect.any(String));
|
||||
expect(review.clientFeedback.length).toBeGreaterThan(0);
|
||||
}
|
||||
|
||||
await signInAsTeacher(page);
|
||||
const dashboardResponse = await page.request.get("/api/teacher/dashboard");
|
||||
await expectResponseOk(dashboardResponse);
|
||||
const dashboard = await dashboardResponse.json();
|
||||
expect(dashboard.source).toBe("database");
|
||||
expect(
|
||||
dashboard.recent_sessions.some(
|
||||
(session: { session_id: string; turn_count: number }) =>
|
||||
session.session_id === sessionId && session.turn_count >= expectedMinTurns,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue