런타임 계약과 학습자 흐름 보강

This commit is contained in:
Yun Chan 2026-06-29 08:12:14 +09:00
parent f456b8997a
commit 206018b088
56 changed files with 4306 additions and 1008 deletions

View file

@ -174,6 +174,10 @@ async function gateScreen(
await page.evaluate(() => new Promise((r) => requestAnimationFrame(() => r(null))));
await prepareReady();
await expect(
page.locator("html"),
`[${screen} @ ${vp.label}] layout gate must capture the dark UI surface`,
).toHaveAttribute("data-theme", "dark");
await expectNoHorizontalOverflow(page);
const report = await auditClipping(page);
expect(
@ -227,22 +231,26 @@ async function expectEmptyReviewNoDeadThirdColumn(page: Page) {
).toBeLessThanOrEqual(2);
}
async function expectFilledReviewLearnerTwoColumn(page: Page) {
async function expectFilledReviewLearnerWorkbench(page: Page) {
const report = await page.evaluate(() => {
const cols = document.querySelector<HTMLElement>(".sr-cols--learner");
const transcript = document.querySelector<HTMLElement>(".sr-card--transcript");
const overview = document.querySelector<HTMLElement>(".sr-overview");
const rubric = document.querySelector<HTMLElement>(".sr-card--rubric");
const worksheet = document.querySelector<HTMLElement>(".sr-card--worksheet");
if (!cols || !transcript || !overview || !rubric || !worksheet) {
const prepost = document.querySelector<HTMLElement>(".sr-card--prepost");
if (!cols || !transcript || !overview || !rubric || !worksheet || !prepost) {
return {
present: false,
viewportWidth: window.innerWidth,
columnCount: 0,
overviewRight: 0,
transcriptLeft: 0,
transcriptRight: 0,
overviewLeft: 0,
rubricLeft: 0,
worksheetLeft: 0,
worksheetRight: 0,
prepostLeft: 0,
};
}
@ -251,23 +259,28 @@ async function expectFilledReviewLearnerTwoColumn(page: Page) {
const overviewRect = overview.getBoundingClientRect();
const rubricRect = rubric.getBoundingClientRect();
const worksheetRect = worksheet.getBoundingClientRect();
const prepostRect = prepost.getBoundingClientRect();
return {
present: true,
viewportWidth: window.innerWidth,
columnCount,
overviewRight: Math.ceil(overviewRect.right),
transcriptLeft: Math.floor(transcriptRect.left),
transcriptRight: Math.ceil(transcriptRect.right),
overviewLeft: Math.floor(overviewRect.left),
rubricLeft: Math.floor(rubricRect.left),
worksheetLeft: Math.floor(worksheetRect.left),
worksheetRight: Math.ceil(worksheetRect.right),
prepostLeft: Math.floor(prepostRect.left),
};
});
expect(report.present, "filled learner review layout should be mounted").toBe(true);
if (report.viewportWidth > 1180) {
expect(report.columnCount, "desktop learner review should use transcript + work column").toBe(2);
expect(report.transcriptRight).toBeLessThanOrEqual(report.overviewLeft);
expect(report.rubricLeft).toBeGreaterThanOrEqual(report.overviewLeft);
expect(report.worksheetLeft).toBeGreaterThanOrEqual(report.overviewLeft);
expect(report.columnCount, "desktop learner review should use a 3-column workbench").toBe(3);
expect(report.overviewRight).toBeLessThanOrEqual(report.transcriptLeft);
expect(report.transcriptRight).toBeLessThanOrEqual(report.rubricLeft);
expect(report.worksheetLeft).toBeLessThan(report.transcriptLeft);
expect(report.worksheetRight).toBeLessThanOrEqual(report.prepostLeft);
}
}
@ -310,6 +323,13 @@ test.describe("layout visual gate @single-run", () => {
await page.goto("/learn");
await gateScreen(page, "learner-home", async () => {
await expect(page.locator(".lh-root")).toBeVisible({ timeout: 15_000 });
await expect(page.locator(".lh-dashboard-status .lh-metric-card").first()).toBeVisible({
timeout: 15_000,
});
await expect(page.locator(".lh-work-cluster")).toBeVisible({ timeout: 15_000 });
await expect(page.locator(".lh-compact-list li").first()).toBeVisible({
timeout: 15_000,
});
});
});
@ -343,7 +363,7 @@ test.describe("layout visual gate @single-run", () => {
await gateScreen(page, "session-review", async () => {
await expect(page.locator(".sr-overview")).toBeVisible({ timeout: 15_000 });
await expect(page.getByText("사례개념화 워크시트")).toBeVisible();
await expectFilledReviewLearnerTwoColumn(page);
await expectFilledReviewLearnerWorkbench(page);
});
});