회기 집계와 기록 복귀 및 감독 근거 링크 수정
Some checks failed
API contract / OpenAPI type drift (push) Failing after 4m46s

This commit is contained in:
Yun Chan 2026-09-09 14:41:54 +09:00
parent aa951c6c4a
commit 1306c524c1
20 changed files with 4631 additions and 60 deletions

View file

@ -239,8 +239,8 @@ test.describe("uc learner practice/history", () => {
"직장 내 대인관계 갈등을 호소",
);
await page.getByRole("button", { name: "새 회기 시작" }).click();
await expect(page).toHaveURL(/\/learn\/session\/P2$/);
await page.getByRole("button", { name: "완전히 새로 시작" }).click();
await expect(page).toHaveURL(/\/learn\/session\/P2\?continuity=fresh$/);
});
// usecase: 기록이 없는 신규 학습자에게 기초 난도부터 추천하되, 사용 불가
@ -438,6 +438,96 @@ test.describe("uc learner practice/history", () => {
await expect(page).toHaveURL(new RegExp(`/learn/session/${REV_ID}/review$`));
});
test("검색과 리뷰 필터를 URL에 보존해 리뷰 왕복과 새로고침 뒤에도 복구한다", async ({
page,
}) => {
await installFixtures(page);
await page.goto("/learn/history?source=dashboard");
const search = page.getByLabel("기록 검색");
const chips = page.locator(".lh-history-filter");
const historyLength = await page.evaluate(() => window.history.length);
await search.pressSequentially("성하늘");
await expect(search).toHaveValue("성하늘");
await expect
.poll(() => new URL(page.url()).searchParams.get("q"))
.toBe("성하늘");
await expect
.poll(() => page.evaluate(() => window.history.length))
.toBe(historyLength);
await chips.getByRole("button", { name: "리뷰 필요" }).click();
await expect
.poll(() => new URL(page.url()).searchParams.get("status"))
.toBe("review");
await expect
.poll(() => new URL(page.url()).searchParams.get("source"))
.toBe("dashboard");
const revCard = page.locator(".lh-session-card", {
hasText: "AI 피드백 대기",
});
await revCard.getByRole("button", { name: "리뷰", exact: true }).click();
await expect(page).toHaveURL(new RegExp(`/learn/session/${REV_ID}/review$`));
await page.goBack();
await expect
.poll(() => new URL(page.url()).searchParams.get("q"))
.toBe("성하늘");
await expect
.poll(() => new URL(page.url()).searchParams.get("status"))
.toBe("review");
await expect(search).toHaveValue("성하늘");
await expect(chips.getByRole("button", { name: "리뷰 필요" })).toHaveAttribute(
"aria-pressed",
"true",
);
await expect(page.locator(".lh-session-card")).toHaveCount(1);
await page.reload();
await expect(search).toHaveValue("성하늘");
await expect(chips.getByRole("button", { name: "리뷰 필요" })).toHaveAttribute(
"aria-pressed",
"true",
);
await search.fill("");
await chips.getByRole("button", { name: "전체" }).click();
await expect
.poll(() => new URL(page.url()).searchParams.has("q"))
.toBe(false);
await expect
.poll(() => new URL(page.url()).searchParams.has("status"))
.toBe(false);
await expect
.poll(() => new URL(page.url()).searchParams.get("source"))
.toBe("dashboard");
});
test("잘못된 상태 query는 전체 필터로 안전하게 처리한다", async ({ page }) => {
await installFixtures(page);
await page.goto("/learn/history?status=unknown&q=%EA%B9%80%EB%8F%84%EC%9C%A4&source=dashboard");
const chips = page.locator(".lh-history-filter");
await expect(page.getByLabel("기록 검색")).toHaveValue("김도윤");
await expect(chips.getByRole("button", { name: "전체" })).toHaveAttribute(
"aria-pressed",
"true",
);
await expect(page.locator(".lh-session-card")).toHaveCount(1);
await chips.getByRole("button", { name: "리뷰 필요" }).click();
await expect
.poll(() => new URL(page.url()).searchParams.get("status"))
.toBe("review");
await expect
.poll(() => new URL(page.url()).searchParams.get("q"))
.toBe("김도윤");
await expect
.poll(() => new URL(page.url()).searchParams.get("source"))
.toBe("dashboard");
});
// usecase: 종료된 기록 카드에서 다음 회기를 열어 같은 내담자의 맥락을 이어간다.
test("종료 기록의 다음 회기 이어가기 버튼이 같은 내담자 새 회기로 이동한다", async ({
page,
@ -450,7 +540,7 @@ test.describe("uc learner practice/history", () => {
await endCard
.getByRole("button", { name: "다음 회기 이어가기", exact: true })
.click();
await expect(page).toHaveURL(/\/learn\/session\/P2$/);
await expect(page).toHaveURL(/\/learn\/session\/P2\?continuity=continue$/);
});
// usecase: 상태 필터 칩과 검색어를 함께 걸어 조건을 좁히고, 조건이 어긋나면