케이스 이어하기 UI와 공통 탭·이미지 복구를 반영

This commit is contained in:
Yun Chan 2026-09-01 11:45:23 +09:00
parent 72353ecd82
commit f1b80676c1
38 changed files with 3581 additions and 455 deletions

View file

@ -394,6 +394,10 @@ test.describe("session review", () => {
growthPoints: [],
degraded: true,
reviewReady: false,
evaluationFailure: {
code: "timeout",
retryable: true,
},
teacherReview: {
status: "pending",
note: "",
@ -440,6 +444,9 @@ test.describe("session review", () => {
page.getByText("저장된 축어록은 확인했지만 deep-loop 평가 AI 산출물을 표시하지 못했습니다. AI 평가 재시도가 필요합니다."),
).toBeVisible();
await expect(page.getByText("engine_error: evaluator timeout")).toHaveCount(0);
await expect(
page.getByText("평가 생성이 제한 시간 안에 끝나지 않았습니다. 축어록은 보존됐으며 다시 시도할 수 있습니다."),
).toBeVisible();
await expect(page.getByRole("button", { name: "AI 평가 재시도" })).toBeVisible();
await expect(page.getByRole("button", { name: "검토 완료" })).toBeDisabled();
@ -474,6 +481,10 @@ test.describe("session review", () => {
growthPoints: [],
degraded: true,
reviewReady: false,
evaluationFailure: {
code: "timeout",
retryable: true,
},
teacherReview: {
status: "pending",
note: "",
@ -503,13 +514,110 @@ test.describe("session review", () => {
await page.getByRole("button", { name: "AI 평가 재시도" }).click();
await expect(
page.getByText("AI 평가 재시도를 완료하지 못했습니다. 잠시 뒤 다시 실행해 주세요."),
page.getByText("AI 평가가 제한 시간 안에 끝나지 않았습니다. 최신 상태를 다시 불러왔습니다."),
).toBeVisible();
await expect(page.getByText("engine_error: retry timeout")).toHaveCount(0);
await expect(page.getByText("평가 실패")).toBeVisible();
await expect(page.getByRole("button", { name: "AI 평가 재시도" })).toBeEnabled();
expect(reevaluateRequests).toBe(1);
expect(reviewRequests).toBe(reviewRequestsBeforeRetry);
await expect.poll(() => reviewRequests).toBeGreaterThan(reviewRequestsBeforeRetry);
});
test("does not offer a futile retry when the evaluation input is too large", async ({ page }) => {
await routeSupervisorCapableLearner(page);
await routePrepostMeasures(page);
const sessionId = "review-failed-input-too-large";
await page.route(`**/api/sessions/${sessionId}/review`, async (route) => {
const ready = filledReviewResponse(sessionId);
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
...ready,
supervisorState: "평가 실패",
summary:
"저장된 축어록은 확인했지만 deep-loop 평가 AI 산출물을 표시하지 못했습니다. 평가 입력 경로를 조정한 뒤 다시 생성해야 합니다.",
rubric: [],
goodMoments: [],
growthPoints: [],
degraded: true,
reviewReady: false,
evaluationFailure: {
code: "prompt_too_large",
retryable: false,
},
teacherReview: {
status: "pending",
note: "",
reviewedAt: null,
reviewerId: null,
updatedAt: null,
worksheetStatus: "pending",
worksheetNote: "",
worksheetReviewedAt: null,
},
}),
});
});
await page.goto(`/teach/session/${sessionId}/review`);
await openReviewTab(page, "피드백");
await expect(page.getByText("평가 실패")).toBeVisible();
await expect(
page.getByText("평가 입력이 허용 크기를 넘어섰습니다. 같은 재시도 대신 입력 경로를 조정해야 합니다."),
).toBeVisible();
await expect(page.getByRole("button", { name: "AI 평가 재시도" })).toHaveCount(0);
});
test("offers recovery retry for a legacy Windows argv-limit evaluation", async ({ page }) => {
await routeSupervisorCapableLearner(page);
await routePrepostMeasures(page);
const sessionId = "review-legacy-windows-argv-limit";
await page.route(`**/api/sessions/${sessionId}/review`, async (route) => {
const ready = filledReviewResponse(sessionId);
await route.fulfill({
status: 200,
contentType: "application/json",
body: JSON.stringify({
...ready,
supervisorState: "평가 실패",
summary:
"저장된 축어록은 확인했지만 deep-loop 평가 AI 산출물을 표시하지 못했습니다. AI 평가 재시도가 필요합니다.",
rubric: [],
goodMoments: [],
growthPoints: [],
degraded: true,
reviewReady: false,
evaluationFailure: {
code: "legacy_argv_limit",
retryable: true,
},
teacherReview: {
status: "pending",
note: "",
reviewedAt: null,
reviewerId: null,
updatedAt: null,
worksheetStatus: "pending",
worksheetNote: "",
worksheetReviewedAt: null,
},
}),
});
});
await page.goto(`/teach/session/${sessionId}/review`);
await openReviewTab(page, "피드백");
await expect(
page.getByText(
"이전 Windows 입력 한도에 걸린 평가입니다. 축어록은 보존됐으며 현재 입력 경로로 다시 시도할 수 있습니다.",
),
).toBeVisible();
await expect(page.getByRole("button", { name: "AI 평가 재시도" })).toBeVisible();
});
test("renders server review data without legacy transcript fixtures", async ({ page }) => {