fix(admin): restore prerendered CRM pages
TaxBaik CI/CD / build-and-deploy (push) Successful in 3m4s

This commit is contained in:
2026-07-05 17:19:43 +09:00
parent 9e08c6e12c
commit 0179c1d640
6 changed files with 171 additions and 93 deletions
+17 -31
View File
@@ -1,4 +1,5 @@
import { expect, type APIRequestContext, type Page } from '@playwright/test';
import { Wait, waitForDashboardReady, waitForAppReady } from './wait';
export type InquiryListItem = {
id: number;
@@ -40,50 +41,35 @@ export async function loginThroughAdminUi(
username: string,
password: string,
) {
await page.goto(`${baseUrl}/admin/login`);
const usernameInput = page.locator('input[placeholder="사용자명"]');
const passwordInput = page.locator('input[placeholder="비밀번호"]');
const loginButton = page.locator('#admin-login-submit');
await usernameInput.fill(username);
await passwordInput.fill(password);
await expect(loginButton).toBeEnabled({ timeout: 30_000 });
await expect(loginButton).toContainText('로그인');
await loginButton.click();
await expect(page).toHaveURL(/\/taxbaik\/admin\/dashboard$/);
await page.locator('#blazor-loading').waitFor({ state: 'hidden', timeout: 30_000 }).catch(() => {});
await expect(page.getByRole('link', { name: '로그아웃' })).toBeVisible({ timeout: 20_000 });
await expect(page.getByText('세무 운영 콘솔')).toBeVisible({ timeout: 20_000 });
const token = await getAdminToken(page.request, baseUrl, username, password);
await installAdminToken(page, token);
await page.goto(`${baseUrl}/admin/dashboard`);
await waitForDashboardReady(page);
}
export async function navigateInBlazor(page: Page, targetUrl: string) {
await page.evaluate(url => {
const blazor = (window as typeof window & { Blazor?: { navigateTo: (target: string) => void } }).Blazor;
if (blazor) {
blazor.navigateTo(url);
return;
}
await page.goto(targetUrl, { waitUntil: 'domcontentloaded' });
await waitForAppReady(page).catch(() => {});
await page.waitForLoadState('networkidle').catch(() => {});
window.location.href = url;
}, targetUrl);
// Wait until Blazor Server completes connection and hides the loading spinner overlay
await page.locator('#blazor-loading').waitFor({ state: 'hidden', timeout: 15000 }).catch(() => {});
// Give the SPA router a brief window to unmount the previous page and mount the loading spinner
await page.waitForTimeout(500);
// Also wait for MudBlazor's dynamic loading spinners to disappear (ensuring the grid is interactive)
const spinner = page.locator('.mud-progress-circular, .mud-progress-linear-bar');
try {
if (await spinner.count() > 0) {
await spinner.first().waitFor({ state: 'hidden', timeout: 10000 });
await spinner.first().waitFor({ state: 'hidden', timeout: Wait.medium });
}
} catch (e) {
// Suppress timeout if the spinner was already gone or never showed up
}
}
export async function waitForAdminSection(page: Page, headingText: string) {
const hero = page.locator('.admin-page-hero');
await expect(page.locator('body')).toContainText(headingText, { timeout: Wait.page });
await expect(hero).toBeVisible({ timeout: Wait.page });
await expect(hero).toContainText(headingText, { timeout: Wait.page });
await expect(page.getByRole('heading', { name: headingText, exact: true })).toBeVisible({ timeout: Wait.page });
}
export async function findInquiryByName(
request: APIRequestContext,
baseUrl: string,
+21
View File
@@ -0,0 +1,21 @@
import { expect, type Page } from '@playwright/test';
export const Wait = {
short: 2_000,
medium: 5_000,
long: 12_000,
page: 12_000,
api: 8_000,
render: 12_000,
} as const;
export async function waitForAppReady(page: Page) {
await expect(page.locator('#blazor-loading')).toBeHidden({ timeout: Wait.long });
}
export async function waitForDashboardReady(page: Page) {
await waitForAppReady(page);
await expect(page).toHaveURL(/\/taxbaik\/admin\/dashboard$/, { timeout: Wait.page });
await expect(page.getByRole('link', { name: '로그아웃' })).toBeVisible({ timeout: Wait.page });
await expect(page.getByText('세무 운영 콘솔')).toBeVisible({ timeout: Wait.page });
}