운영 화면과 회기 리뷰 UI 갱신
This commit is contained in:
parent
e7ebb38177
commit
3a9f70a97b
18 changed files with 2210 additions and 137 deletions
|
|
@ -1,7 +1,13 @@
|
|||
import { promises as fs } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { expect, test, type Page } from "@playwright/test";
|
||||
import { FILLED_REVIEW_SESSION_ID, routeFilledSessionReview } from "./session-review-fixture";
|
||||
import {
|
||||
EMPTY_REVIEW_SESSION_ID,
|
||||
FILLED_REVIEW_SESSION_ID,
|
||||
routeEmptySessionReview,
|
||||
routeFilledSessionReview,
|
||||
routePrepostMeasures,
|
||||
} from "./session-review-fixture";
|
||||
import {
|
||||
completeOnboarding,
|
||||
expectNoHorizontalOverflow,
|
||||
|
|
@ -190,6 +196,81 @@ async function gateScreen(
|
|||
}
|
||||
}
|
||||
|
||||
async function expectEmptyReviewNoDeadThirdColumn(page: Page) {
|
||||
const report = await page.evaluate(() => {
|
||||
const root = document.querySelector<HTMLElement>(".sr-root--empty");
|
||||
const cols = document.querySelector<HTMLElement>(".sr-root--empty .sr-cols");
|
||||
const transcript = document.querySelector<HTMLElement>(".sr-card--transcript");
|
||||
if (!root || !cols || !transcript) {
|
||||
return {
|
||||
present: false,
|
||||
columnCount: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const gridTemplate = getComputedStyle(cols).gridTemplateColumns;
|
||||
const columnCount = gridTemplate.split(" ").filter(Boolean).length;
|
||||
const transcriptRect = transcript.getBoundingClientRect();
|
||||
|
||||
return {
|
||||
present: true,
|
||||
columnCount,
|
||||
transcriptWidth: Math.round(transcriptRect.width),
|
||||
mainColumnWidth: Math.round(cols.getBoundingClientRect().width),
|
||||
};
|
||||
});
|
||||
|
||||
expect(report.present, "empty review layout should be mounted").toBe(true);
|
||||
expect(
|
||||
report.columnCount,
|
||||
"empty review should collapse the desktop masonry layout instead of leaving a sparse third column",
|
||||
).toBeLessThanOrEqual(2);
|
||||
}
|
||||
|
||||
async function expectFilledReviewLearnerTwoColumn(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) {
|
||||
return {
|
||||
present: false,
|
||||
viewportWidth: window.innerWidth,
|
||||
columnCount: 0,
|
||||
transcriptRight: 0,
|
||||
overviewLeft: 0,
|
||||
rubricLeft: 0,
|
||||
worksheetLeft: 0,
|
||||
};
|
||||
}
|
||||
|
||||
const columnCount = getComputedStyle(cols).gridTemplateColumns.split(" ").filter(Boolean).length;
|
||||
const transcriptRect = transcript.getBoundingClientRect();
|
||||
const overviewRect = overview.getBoundingClientRect();
|
||||
const rubricRect = rubric.getBoundingClientRect();
|
||||
const worksheetRect = worksheet.getBoundingClientRect();
|
||||
return {
|
||||
present: true,
|
||||
viewportWidth: window.innerWidth,
|
||||
columnCount,
|
||||
transcriptRight: Math.ceil(transcriptRect.right),
|
||||
overviewLeft: Math.floor(overviewRect.left),
|
||||
rubricLeft: Math.floor(rubricRect.left),
|
||||
worksheetLeft: Math.floor(worksheetRect.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);
|
||||
}
|
||||
}
|
||||
|
||||
test.describe("layout visual gate @single-run", () => {
|
||||
test.describe.configure({ mode: "serial" });
|
||||
|
||||
|
|
@ -257,10 +338,25 @@ test.describe("layout visual gate @single-run", () => {
|
|||
test("session review stays contained across all widths", async ({ page }) => {
|
||||
await signInAsLearner(page);
|
||||
await routeFilledSessionReview(page);
|
||||
await routePrepostMeasures(page);
|
||||
await page.goto(`/learn/session/${FILLED_REVIEW_SESSION_ID}/review`);
|
||||
await gateScreen(page, "session-review", async () => {
|
||||
await expect(page.locator(".sr-overview")).toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByText("사례개념화 워크시트")).toBeVisible();
|
||||
await expectFilledReviewLearnerTwoColumn(page);
|
||||
});
|
||||
});
|
||||
|
||||
test("empty session review avoids sparse column gaps across all widths", async ({ page }) => {
|
||||
await signInAsLearner(page);
|
||||
await routeEmptySessionReview(page);
|
||||
await routePrepostMeasures(page);
|
||||
await page.goto(`/learn/session/${EMPTY_REVIEW_SESSION_ID}/review`);
|
||||
await gateScreen(page, "session-review-empty", async () => {
|
||||
await expect(page.locator(".sr-root--empty")).toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByText("축어록 저장 후 생성")).toBeVisible();
|
||||
await expect(page.getByText("감정 타임라인 대기")).toBeVisible();
|
||||
await expectEmptyReviewNoDeadThirdColumn(page);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue