음성 재생과 운영 배포 정리

This commit is contained in:
Yun Chan 2026-06-28 12:18:20 +09:00
parent 8ed185ce6c
commit ac7db95542
1020 changed files with 46863 additions and 2175 deletions

View file

@ -10,6 +10,7 @@ async function expectSessionPageHeightToMatchViewport(page: Page) {
const metrics = await page.evaluate(() => {
const sessionPage = document.querySelector<HTMLElement>(".sx-page--active");
const topbar = document.querySelector<HTMLElement>(".vg-topbar");
const sessionbar = document.querySelector<HTMLElement>(".sx-sessionbar");
if (!sessionPage) {
return null;
@ -23,11 +24,13 @@ async function expectSessionPageHeightToMatchViewport(page: Page) {
expectedHeight: Math.round(expectedHeight),
delta: Math.abs(pageHeight - expectedHeight),
hasTopbar: Boolean(topbar),
hasSessionbar: Boolean(sessionbar),
};
});
expect(metrics, "Expected active session page to be present").not.toBeNull();
expect(metrics!.hasTopbar, "Active session should hide the global topbar").toBe(false);
expect(metrics!.hasSessionbar, "Active session should show the in-session navigation bar").toBe(true);
expect(
metrics!.delta,
`Expected .sx-page height ${metrics!.pageHeight}px to match viewport ${metrics!.expectedHeight}px`,
@ -76,6 +79,7 @@ async function expectSessionControlsInsideViewport(page: Page) {
".sx-transcript",
".sx-transcript__scroll",
".sx-compose",
".sx-sessionbar",
".sx-controlbar",
];
const result = await page.evaluate((items) => {
@ -421,7 +425,10 @@ test.describe("learner session full-screen layout", () => {
await page.getByRole("button", { name: "회기 시작" }).click();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
await expect(page).toHaveURL(/\/learn\/session\/[0-9a-f-]+$/i);
await expect(page.locator(".sx-sessionbar")).toBeVisible();
await expect(page.getByRole("button", { name: "기록으로" })).toBeVisible();
await expect(page.locator(".sx-grid")).toBeVisible();
await expect(page.locator(".vg-topbar")).toHaveCount(0);
await expect(page.locator(".vg-nav")).toHaveCount(0);
@ -437,6 +444,12 @@ test.describe("learner session full-screen layout", () => {
await expectNoVisibleSessionPanelOverlap(page);
await expectMainControlsUnclipped(page);
await expectRightPanelDoesNotIntersectSessionCore(page);
await page.reload();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
await expect(page.locator(".sx-sessionbar")).toBeVisible();
await expect(page.getByRole("button", { name: "회기 시작" })).toHaveCount(0);
await expect(page).toHaveURL(/\/learn\/session\/[0-9a-f-]+$/i);
});
test("keeps critical session controls visible across dense viewport sizes", async ({ page }) => {
@ -461,13 +474,13 @@ test.describe("learner session full-screen layout", () => {
await page.setViewportSize(viewports[0]);
await page.goto(`/learn/session/${persona.code}`);
await page.getByRole("button", { name: "회기 시작" }).click();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
for (const viewport of viewports) {
await page.setViewportSize(viewport);
await page.evaluate(() => new Promise(requestAnimationFrame));
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
await expectNoDocumentOverflow(page);
await expectNoHorizontalOverflow(page);
await expectNoLocalStageDemoControl(page);
@ -498,7 +511,7 @@ test.describe("learner session full-screen layout", () => {
const persona = await fetchAvailablePersona(page, 1);
await page.goto(`/learn/session/${persona.code}`);
await page.getByRole("button", { name: "회기 시작" }).click();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
await page.route("**/api/sessions/*/stream", async (route) => {
await route.fulfill({
@ -525,7 +538,7 @@ test.describe("learner session full-screen layout", () => {
const persona = await fetchAvailablePersona(page, 1);
await page.goto(`/learn/session/${persona.code}`);
await page.getByRole("button", { name: "회기 시작" }).click();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible();
await expect(page.locator(".sx-page.sx-page--active")).toBeVisible({ timeout: 15_000 });
await page.route("**/api/sessions/*/stream", async (route) => {
await route.fulfill({