동의 게이트와 런타임 안정화

This commit is contained in:
Yun Chan 2026-06-27 17:22:38 +09:00
parent 0eb7d925ed
commit 0ec266a761
34 changed files with 1186 additions and 158 deletions

View file

@ -203,6 +203,9 @@ test.describe("layout visual gate @single-run", () => {
display_name: "이름이 아주 길게 표시되는 학습자 케이스 검증용 계정",
},
});
await page.request.post("/api/auth/consent", {
data: { accepted: true },
});
// Seed dense history: one active + two ended sessions.
const persona = await fetchAvailablePersona(page);
const made: string[] = [];

View file

@ -267,6 +267,7 @@ async function expectPracticalSettingsLayout(page: Page, mode: "desktop" | "mobi
template === "none" ? 0 : template.split(" ").filter(Boolean).length;
const root = document.querySelector<HTMLElement>(".vg-set");
const forms = document.querySelector<HTMLElement>(".vg-set__forms");
const railTitle = document.querySelector<HTMLElement>(".vg-set__rail-title");
const railCard = document.querySelector<HTMLElement>(".vg-set__rail-card");
const nav = document.querySelector<HTMLElement>(".vg-set__nav");
const account = document.querySelector<HTMLElement>("#set-account");
@ -274,12 +275,24 @@ async function expectPracticalSettingsLayout(page: Page, mode: "desktop" | "mobi
const notify = document.querySelector<HTMLElement>("#set-notify");
const voice = document.querySelector<HTMLElement>("#set-voice");
if (!root || !forms || !railCard || !nav || !account || !appearance || !notify || !voice) {
if (
!root ||
!forms ||
!railTitle ||
!railCard ||
!nav ||
!account ||
!appearance ||
!notify ||
!voice
) {
return { ready: false };
}
const rootStyle = getComputedStyle(root);
const rootColumns = countColumns(getComputedStyle(root).gridTemplateColumns);
const formColumns = countColumns(getComputedStyle(forms).gridTemplateColumns);
const railTitleRect = railTitle.getBoundingClientRect();
const railCardRect = railCard.getBoundingClientRect();
const navRect = nav.getBoundingClientRect();
const accountStyle = getComputedStyle(account);
@ -290,20 +303,17 @@ async function expectPracticalSettingsLayout(page: Page, mode: "desktop" | "mobi
if (layoutMode === "desktop") {
return {
ready: true,
rootColumns,
rootIsTwoColumnGrid: rootStyle.display === "grid" && rootColumns === 2,
formColumns,
railCardVisible: railCardRect.height > 24,
shortPanelsShareRow:
Math.abs(appearanceRect.top - notifyRect.top) <= 4 &&
appearanceRect.left < notifyRect.left,
voiceBelowShortPanels:
voiceRect.top > appearanceRect.top && voiceRect.top > notifyRect.top,
railTitleVisible: railTitleRect.height > 28,
railCardHidden: railCardRect.height === 0,
voiceBeforeNotify: voiceRect.top < notifyRect.top,
};
}
return {
ready: true,
rootColumns,
rootSingleColumn: rootStyle.display !== "grid",
formColumns,
railCardHidden: railCardRect.height === 0,
navSingleLine: navRect.height <= 54,
@ -315,15 +325,15 @@ async function expectPracticalSettingsLayout(page: Page, mode: "desktop" | "mobi
mode === "desktop"
? {
ready: true,
rootColumns: 2,
formColumns: 2,
railCardVisible: true,
shortPanelsShareRow: true,
voiceBelowShortPanels: true,
rootIsTwoColumnGrid: true,
formColumns: 1,
railTitleVisible: true,
railCardHidden: true,
voiceBeforeNotify: true,
}
: {
ready: true,
rootColumns: 1,
rootSingleColumn: true,
formColumns: 1,
railCardHidden: true,
navSingleLine: true,

View file

@ -69,6 +69,10 @@ export async function signInAsLearner(page: Page) {
},
});
expect(res.ok(), await res.text()).toBeTruthy();
const consent = await page.request.post("/api/auth/consent", {
data: { accepted: true },
});
expect(consent.ok(), await consent.text()).toBeTruthy();
}
export async function signInAsTeacher(page: Page) {