Google 로그인을 단일 버튼으로 정리
This commit is contained in:
parent
7994175a3d
commit
471eb9621a
15 changed files with 78 additions and 85 deletions
|
|
@ -67,13 +67,17 @@ test.describe("auth domain policy", () => {
|
|||
await page.goto("/login");
|
||||
|
||||
const googleButtons = page.locator(".lg-obtn");
|
||||
await expect(googleButtons).toHaveCount(2);
|
||||
await expect(googleButtons).toHaveCount(1);
|
||||
await expect(page.getByRole("button", { name: /^Google 계정으로 로그인/ })).toHaveCount(1);
|
||||
await expect(page.getByRole("button", { name: /다른 Google 계정 선택/ })).toHaveCount(0);
|
||||
expect(config.allowed_email_domains).toEqual([]);
|
||||
await expect(page.locator(".lg-policy b")).toHaveText("모든 Google 계정");
|
||||
const redirectHost = new URL(config.redirect_uri).hostname;
|
||||
const devOAuthUnavailable =
|
||||
config.dev_login_enabled &&
|
||||
!isLocalHostname(redirectHost);
|
||||
await expect(page.locator(".lg-policy b")).toHaveText(
|
||||
config.google_oauth_configured && !devOAuthUnavailable ? "모든 Google 계정" : "설정 필요",
|
||||
);
|
||||
if (config.dev_login_enabled) {
|
||||
await expect(page.locator(".lg-dev")).toBeVisible();
|
||||
} else {
|
||||
|
|
@ -85,7 +89,6 @@ test.describe("auth domain policy", () => {
|
|||
await expect(page.locator(".lg-config")).toHaveCount(0);
|
||||
} else {
|
||||
await expect(googleButtons.first()).toBeDisabled();
|
||||
await expect(googleButtons.nth(1)).toBeDisabled();
|
||||
await expect(page.locator(".lg-config")).toBeVisible();
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.locator("body")).not.toContainText("Google OAuth is not configured");
|
||||
|
|
@ -239,7 +242,9 @@ test.describe("auth domain policy", () => {
|
|||
await page.goto(`${publicBase}/login`, { waitUntil: "domcontentloaded" });
|
||||
await page.waitForLoadState("networkidle", { timeout: 15_000 }).catch(() => undefined);
|
||||
|
||||
await expect(page.locator(".lg-obtn")).toHaveCount(2);
|
||||
await expect(page.locator(".lg-obtn")).toHaveCount(1);
|
||||
await expect(page.getByRole("button", { name: /^Google 계정으로 로그인/ })).toHaveCount(1);
|
||||
await expect(page.getByRole("button", { name: /다른 Google 계정 선택/ })).toHaveCount(0);
|
||||
await expect(page.locator(".lg-dev")).toHaveCount(0);
|
||||
await expect(page.getByText("로컬 테스트")).toHaveCount(0);
|
||||
await expect(page.getByText("로컬 테스트 계정으로 계속")).toHaveCount(0);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import { completeOnboarding, expectNoHorizontalOverflow, useRealApi } from "./su
|
|||
const CONFIG_PATTERN = "**/api/auth/config";
|
||||
const ME_PATTERN = "**/api/auth/me";
|
||||
|
||||
/** 로컬 redirect_uri라서 두 OAuth 버튼이 모두 활성화되는 구성 fixture. */
|
||||
/** 로컬 redirect_uri라서 단일 Google OAuth 버튼이 활성화되는 구성 fixture. */
|
||||
const READY_AUTH_CONFIG = {
|
||||
google_oauth_configured: true,
|
||||
saml_configured: false,
|
||||
|
|
@ -153,7 +153,7 @@ test.describe("full sweep auth", () => {
|
|||
});
|
||||
|
||||
// 검증 checklist: auth-login-generic-google-button
|
||||
test("both Google buttons advertise unrestricted accounts and start the same OAuth flow", async ({
|
||||
test("single Google button advertises unrestricted accounts and starts the account chooser flow", async ({
|
||||
page,
|
||||
}) => {
|
||||
await mockUnauthenticatedMe(page);
|
||||
|
|
@ -173,16 +173,16 @@ test.describe("full sweep auth", () => {
|
|||
});
|
||||
await expectNoHorizontalOverflow(page);
|
||||
|
||||
const secondary = page.locator(".lg-obtn.secondary");
|
||||
await expect(secondary).toBeEnabled();
|
||||
await expect(secondary).toContainText("다른 Google 계정 선택");
|
||||
await expect(secondary.locator(".sub")).toHaveText("이메일 확인 후 바로 시작");
|
||||
await expect(page.locator(".lg-obtn.primary .sub")).toHaveText("모든 Google 계정");
|
||||
const googleLogin = page.getByRole("button", { name: /^Google 계정으로 로그인/ });
|
||||
await expect(googleLogin).toHaveCount(1);
|
||||
await expect(googleLogin).toBeEnabled();
|
||||
await expect(googleLogin.locator(".sub")).toHaveText("모든 Google 계정");
|
||||
await expect(page.getByRole("button", { name: /다른 Google 계정 선택/ })).toHaveCount(0);
|
||||
|
||||
// 클릭 시 primary와 동일한 provider=google 시작 URL로 이동한다.
|
||||
// 단일 CTA가 provider=google OAuth 시작 URL로 이동한다.
|
||||
await Promise.all([
|
||||
page.waitForURL(/\/api\/auth\/login\?provider=google&next=%2F/),
|
||||
secondary.click(),
|
||||
googleLogin.click(),
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
await page.getByRole("button", { name: "로그아웃" }).click();
|
||||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
|
||||
// 서버 세션도 무효화되었는지 실 API로 확인
|
||||
const me = await page.request.get("/api/auth/me");
|
||||
|
|
@ -112,7 +112,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
await page.getByRole("button", { name: "로그아웃" }).click();
|
||||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
expect(logoutCalled).toBeTruthy();
|
||||
});
|
||||
|
||||
|
|
@ -239,7 +239,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
releaseMe();
|
||||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
});
|
||||
|
||||
// checklist: shell-suspense-fallback
|
||||
|
|
@ -269,7 +269,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
|
||||
releaseChunk();
|
||||
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible({
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible({
|
||||
timeout: 10_000,
|
||||
});
|
||||
await expect(page.getByText(BOOT_SCREEN_TEXT)).toHaveCount(0);
|
||||
|
|
@ -287,7 +287,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
});
|
||||
|
||||
await page.goto("/login");
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
expect(documentRequests).toBe(1);
|
||||
|
||||
const firstPrevented = await page.evaluate(() => {
|
||||
|
|
@ -300,7 +300,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
expect(firstPrevented).toBeTruthy();
|
||||
|
||||
await expect.poll(() => documentRequests).toBe(2);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
await expect
|
||||
.poll(() =>
|
||||
page.evaluate(() => sessionStorage.getItem("vignette:chunk-recovery:/login")),
|
||||
|
|
@ -358,7 +358,7 @@ test.describe("full sweep — shared shell, GNB, and routing guards", () => {
|
|||
test("redirects unknown routes to the role-aware root destination", async ({ page }) => {
|
||||
await page.goto("/definitely/not-a-route");
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
|
||||
await signInAsLearner(page);
|
||||
await page.goto("/no-such-page");
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ test.describe("learner app shell and session launcher", () => {
|
|||
await page.goto("/learn/practice");
|
||||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
expect(await page.evaluate(() => window.localStorage.getItem("vignette.dev-auth"))).toBeNull();
|
||||
});
|
||||
|
||||
|
|
@ -182,7 +182,7 @@ test.describe("learner app shell and session launcher", () => {
|
|||
await page.goto("/learn/practice");
|
||||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(page.getByRole("button", { name: /학교 Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /Google 계정으로 로그인/ })).toBeVisible();
|
||||
await expect(page.getByText("내담자 목록을 불러오지 못했습니다.")).toHaveCount(0);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -905,7 +905,7 @@ async function openLogin(page: Page) {
|
|||
await routeLoginScreen(page);
|
||||
await page.goto("/login");
|
||||
await expect(page.locator(".lg-root, .lg-enter").first()).toBeVisible({ timeout: 15_000 });
|
||||
await expect(page.getByRole("button", { name: /^Google 계정으로 계속/ })).toBeVisible();
|
||||
await expect(page.getByRole("button", { name: /^Google 계정으로 로그인/ })).toBeVisible();
|
||||
}
|
||||
|
||||
async function openLearnerHome(page: Page) {
|
||||
|
|
@ -970,16 +970,41 @@ test.describe("uc a11y-mobile — 주요 6화면 접근성·모바일 감사", (
|
|||
// usecase: 키보드 사용자가 Tab 으로 로그인 버튼에 도달하고 포커스 위치를 눈으로 확인한다
|
||||
test("로그인 화면에서 Tab 순회 시 포커스 표시가 눈에 보인다", async ({ page }) => {
|
||||
await openLogin(page);
|
||||
await expectFocusVisibleOnTab(page, "login", 5);
|
||||
const googleLogin = page.getByRole("button", { name: /^Google 계정으로 로그인/ });
|
||||
await expect(googleLogin).toHaveCount(1);
|
||||
await page.keyboard.press("Tab");
|
||||
await expect(googleLogin).toBeFocused();
|
||||
const focusReport = await googleLogin.evaluate((element) => {
|
||||
const target = element as HTMLElement;
|
||||
const snapshot = () => {
|
||||
const style = window.getComputedStyle(target);
|
||||
return [
|
||||
style.outlineStyle,
|
||||
style.outlineWidth,
|
||||
style.outlineColor,
|
||||
style.boxShadow,
|
||||
style.borderColor,
|
||||
style.backgroundColor,
|
||||
].join("|");
|
||||
};
|
||||
const focusVisible = target.matches(":focus-visible");
|
||||
const focusedStyle = snapshot();
|
||||
target.blur();
|
||||
const blurredStyle = snapshot();
|
||||
target.focus();
|
||||
return { focusVisible, styleChanged: focusedStyle !== blurredStyle };
|
||||
});
|
||||
expect(focusReport.focusVisible).toBeTruthy();
|
||||
expect(focusReport.styleChanged).toBeTruthy();
|
||||
});
|
||||
|
||||
// usecase: 저시력 사용자가 주 로그인 버튼의 문구를 읽는다
|
||||
test("로그인 주 CTA(Google 계정으로 계속)의 색 대비가 4.5:1 이상이다", async ({ page }) => {
|
||||
test("로그인 주 CTA(Google 계정으로 로그인)의 색 대비가 4.5:1 이상이다", async ({ page }) => {
|
||||
await openLogin(page);
|
||||
await expectCtaContrast(
|
||||
page.getByRole("button", { name: /^Google 계정으로 계속/ }),
|
||||
page.getByRole("button", { name: /^Google 계정으로 로그인/ }),
|
||||
"login",
|
||||
"Google 계정으로 계속",
|
||||
"Google 계정으로 로그인",
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -500,7 +500,7 @@ test.describe("uc error-resilience-shell", () => {
|
|||
|
||||
await expect(page).toHaveURL(/\/login$/);
|
||||
await expect(
|
||||
page.getByRole("button", { name: /Google 계정으로 계속/ }),
|
||||
page.getByRole("button", { name: /Google 계정으로 로그인/ }),
|
||||
).toBeVisible();
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue