chore: Playwright 테스트 파일을 관제탑(My-agent)으로 이관
테스트 파일은 ERP-node 프로젝트가 아닌 My-agent에서 관리한다. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2da1532e65
commit
b677840952
|
|
@ -1,30 +0,0 @@
|
|||
import { defineConfig, devices } from "@playwright/test";
|
||||
|
||||
export default defineConfig({
|
||||
testDir: "./tests/e2e",
|
||||
fullyParallel: false,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: 0,
|
||||
workers: 1,
|
||||
reporter: "html",
|
||||
timeout: 60_000,
|
||||
expect: { timeout: 10_000 },
|
||||
|
||||
use: {
|
||||
baseURL: "http://localhost:9771",
|
||||
trace: "on-first-retry",
|
||||
screenshot: "only-on-failure",
|
||||
video: "on-first-retry",
|
||||
actionTimeout: 15_000,
|
||||
},
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: "chromium",
|
||||
use: {
|
||||
...devices["Desktop Chrome"],
|
||||
viewport: { width: 1024, height: 800 },
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
|
@ -1,541 +0,0 @@
|
|||
import { test, expect, Page } from "@playwright/test";
|
||||
|
||||
// ============================================
|
||||
// 판매출고 POP 화면 (4578) 브라우저 테스트
|
||||
// ============================================
|
||||
//
|
||||
// 테스트 흐름:
|
||||
// 1. 로그인 -> POP 화면 접속
|
||||
// 2. 화면 렌더링 확인
|
||||
// 3. 거래처 검색(모달) -> 거래처 선택 -> 카드 로드
|
||||
// 4. 카드 컴포넌트 표시 확인
|
||||
// 5. 수량 입력 + 담기 동작
|
||||
// 6. 장바구니 취소 동작
|
||||
// ============================================
|
||||
|
||||
const TEST_CONFIG = {
|
||||
screenId: 4578,
|
||||
loginUrl: "/login",
|
||||
screenUrl: "/pop/screens/4578",
|
||||
credentials: {
|
||||
userId: "topseal_admin",
|
||||
password: "qlalfqjsgh11",
|
||||
},
|
||||
// 테스트 거래처 (DB에 미리 삽입됨)
|
||||
testCustomer: {
|
||||
code: "T-CUST-001",
|
||||
name: "(T)테스트거래처",
|
||||
},
|
||||
};
|
||||
|
||||
// 로그인 헬퍼
|
||||
async function login(page: Page) {
|
||||
await page.goto(TEST_CONFIG.loginUrl);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// 로그인 폼 입력
|
||||
await page.locator("#userId").fill(TEST_CONFIG.credentials.userId);
|
||||
await page.locator("#password").fill(TEST_CONFIG.credentials.password);
|
||||
await page.locator('button[type="submit"]').click();
|
||||
|
||||
// 로그인 성공 대기 (리다이렉트)
|
||||
await page.waitForURL((url) => !url.pathname.includes("/login"), {
|
||||
timeout: 15_000,
|
||||
});
|
||||
}
|
||||
|
||||
// POP 화면 이동 헬퍼
|
||||
async function navigateToPopScreen(page: Page) {
|
||||
await page.goto(TEST_CONFIG.screenUrl);
|
||||
await page.waitForLoadState("networkidle");
|
||||
|
||||
// 로딩 스피너가 사라질 때까지 대기
|
||||
await page
|
||||
.locator(".animate-spin")
|
||||
.waitFor({ state: "hidden", timeout: 15_000 })
|
||||
.catch(() => {
|
||||
/* 이미 로드 완료 */
|
||||
});
|
||||
}
|
||||
|
||||
// 거래처 선택 헬퍼: 모달 검색으로 테스트 거래처 선택
|
||||
async function selectTestCustomer(page: Page) {
|
||||
// comp_4 (pop-search modal) - 거래처 검색 클릭
|
||||
// 모달형 검색은 role="button"인 div, placeholder="거래처 검색" 텍스트 포함
|
||||
const searchTrigger = page.locator(
|
||||
'[role="button"]:has-text("거래처 검색"), [role="button"]:has-text("선택...")'
|
||||
).first();
|
||||
|
||||
const isTriggerVisible = await searchTrigger
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (!isTriggerVisible) {
|
||||
// 대안: placeholder를 포함하는 input/button 찾기
|
||||
const altTrigger = page
|
||||
.locator('text="거래처 검색"')
|
||||
.first();
|
||||
if (await altTrigger.isVisible().catch(() => false)) {
|
||||
await altTrigger.click();
|
||||
} else {
|
||||
console.log("WARN: 거래처 검색 트리거를 찾을 수 없음");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
await searchTrigger.click();
|
||||
}
|
||||
|
||||
// 모달 다이얼로그가 열릴 때까지 대기
|
||||
const dialog = page.locator('[role="dialog"]');
|
||||
await dialog.waitFor({ state: "visible", timeout: 10_000 });
|
||||
|
||||
// 필터 탭("가나다" 등)이 활성화되어 있으면 비활성화
|
||||
// "(T)테스트거래처"는 "("로 시작하므로 한글 초성 필터에서 제외됨
|
||||
const filterTabButton = dialog.locator('button:has-text("가나다")');
|
||||
if (await filterTabButton.isVisible({ timeout: 2_000 }).catch(() => false)) {
|
||||
// 활성 상태(variant=default) 확인 후 클릭해서 토글 off
|
||||
await filterTabButton.click();
|
||||
await page.waitForTimeout(300);
|
||||
}
|
||||
|
||||
// 모달에서 테스트 거래처 검색
|
||||
const modalSearchInput = dialog.locator('input[type="text"]').first();
|
||||
if (await modalSearchInput.isVisible({ timeout: 3_000 }).catch(() => false)) {
|
||||
await modalSearchInput.fill("테스트거래처");
|
||||
await page.waitForTimeout(800); // 디바운스 대기
|
||||
}
|
||||
|
||||
// "(T)테스트거래처" 항목 클릭 - 아이콘 뷰에서는 truncated text 내 span
|
||||
const customerItem = dialog
|
||||
.locator(`text=${TEST_CONFIG.testCustomer.name}`)
|
||||
.first();
|
||||
let found = await customerItem
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
// 아이콘 뷰에서 truncate 때문에 정확한 텍스트 매칭 실패 시 role=button으로 시도
|
||||
if (!found) {
|
||||
// 부분 텍스트 매칭 시도
|
||||
const partialMatch = dialog.locator('text=테스트거래처').first();
|
||||
found = await partialMatch.isVisible({ timeout: 2_000 }).catch(() => false);
|
||||
if (found) {
|
||||
await partialMatch.click();
|
||||
await dialog.waitFor({ state: "hidden", timeout: 5_000 }).catch(() => {});
|
||||
await page.waitForTimeout(1_500);
|
||||
return true;
|
||||
}
|
||||
|
||||
// role=button 중 텍스트 포함된 것 시도
|
||||
const iconBtn = dialog.locator('[role="button"]').filter({ hasText: /테스트/ }).first();
|
||||
found = await iconBtn.isVisible({ timeout: 2_000 }).catch(() => false);
|
||||
if (found) {
|
||||
await iconBtn.click();
|
||||
await dialog.waitFor({ state: "hidden", timeout: 5_000 }).catch(() => {});
|
||||
await page.waitForTimeout(1_500);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
await customerItem.click();
|
||||
// 모달 닫힘 + 데이터 로딩 대기
|
||||
await dialog
|
||||
.waitFor({ state: "hidden", timeout: 5_000 })
|
||||
.catch(() => {});
|
||||
await page.waitForTimeout(1_500); // API 응답 + 렌더링 대기
|
||||
return true;
|
||||
}
|
||||
|
||||
console.log("WARN: 테스트 거래처를 모달에서 찾을 수 없음");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ============================================
|
||||
// 테스트 시작
|
||||
// ============================================
|
||||
|
||||
test.describe("판매출고 POP 화면 (pop-cart-outbound)", () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page);
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 1: 화면 접속 + 렌더링 확인
|
||||
// -------------------------------------------
|
||||
test("화면 접속 시 POP 화면이 정상 렌더링된다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 에러 화면이 아닌지 확인
|
||||
const errorText = page.getByText("화면을 찾을 수 없습니다");
|
||||
await expect(errorText).not.toBeVisible();
|
||||
|
||||
// 빈 화면이 아닌지 확인
|
||||
const emptyText = page.getByText("화면이 비어있습니다");
|
||||
await expect(emptyText).not.toBeVisible();
|
||||
|
||||
// 페이지가 정상 로드됨
|
||||
await expect(page).toHaveURL(/\/pop\/screens\/4578/);
|
||||
|
||||
// 스크린샷
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/01-screen-loaded.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 2: 카트 아웃바운드 컴포넌트 확인
|
||||
// -------------------------------------------
|
||||
test("pop-cart-outbound 컴포넌트가 화면에 표시된다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// requireFilter 설정으로 "거래처를 선택하면" 메시지 표시됨
|
||||
const hasEmptyState = await page
|
||||
.locator("text=거래처를 선택하면")
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
const hasHeader = await page
|
||||
.locator("text=출고 대상 품목")
|
||||
.first()
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
const hasCards = await page
|
||||
.locator("div.rounded-xl.border")
|
||||
.first()
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
// 셋 중 하나는 있어야 함 (컴포넌트가 렌더링됨)
|
||||
expect(hasHeader || hasEmptyState || hasCards).toBeTruthy();
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/02-cart-outbound-visible.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 3: 검색 컴포넌트 확인
|
||||
// -------------------------------------------
|
||||
test("검색/스캔 컴포넌트가 화면에 표시된다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// input 또는 검색 관련 요소가 있는지 확인
|
||||
const searchInputs = page.locator(
|
||||
'input[type="text"], input[placeholder*="검색"], input[placeholder*="스캔"], [role="button"]:has-text("거래처"), [role="button"]:has-text("선택")'
|
||||
);
|
||||
const searchCount = await searchInputs.count();
|
||||
|
||||
// 최소 1개 이상의 검색/입력 요소가 있어야 함
|
||||
expect(searchCount).toBeGreaterThanOrEqual(1);
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/03-search-components.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 4: 거래처 선택 -> 카드 로드
|
||||
// -------------------------------------------
|
||||
test("거래처 선택 시 출고 대상 품목 카드가 표시된다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 거래처 선택 전: 빈 상태 메시지 확인
|
||||
const emptyMsg = page.locator("text=거래처를 선택하면");
|
||||
const hasEmptyMsg = await emptyMsg
|
||||
.isVisible({ timeout: 3_000 })
|
||||
.catch(() => false);
|
||||
if (hasEmptyMsg) {
|
||||
console.log("INFO: requireFilter 동작 확인 - 거래처 미선택 시 빈 상태 메시지 표시");
|
||||
}
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/04a-before-customer-select.png",
|
||||
fullPage: true,
|
||||
});
|
||||
|
||||
// 거래처 선택
|
||||
const selected = await selectTestCustomer(page);
|
||||
if (!selected) {
|
||||
test.skip(true, "테스트 거래처를 선택할 수 없음");
|
||||
return;
|
||||
}
|
||||
|
||||
// 카드가 로딩되는지 확인
|
||||
// 테스트 데이터: "(T)테스트 알루미늄 프로파일", "(T)테스트 스틸바 SB-200"
|
||||
const card = page
|
||||
.locator("text=테스트 알루미늄, text=테스트 스틸바, text=T-ITEM")
|
||||
.first();
|
||||
const hasCards = await card
|
||||
.isVisible({ timeout: 8_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (hasCards) {
|
||||
console.log("SUCCESS: 거래처 선택 후 품목 카드 로딩됨");
|
||||
} else {
|
||||
// 카드가 안 보일 수 있음 - 스크린샷으로 디버그
|
||||
console.log("WARN: 거래처 선택 후 카드가 즉시 보이지 않음 - 스크린샷 확인 필요");
|
||||
}
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/04b-after-customer-select.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 5: 카드에 담기 버튼 존재 확인
|
||||
// -------------------------------------------
|
||||
test("품목 카드에 담기 버튼이 있다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 먼저 거래처 선택으로 카드 로드
|
||||
const selected = await selectTestCustomer(page);
|
||||
if (!selected) {
|
||||
test.skip(true, "테스트 거래처를 선택할 수 없음 - 담기 버튼 테스트 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
// 담기 버튼 확인
|
||||
const addButton = page.getByRole("button", { name: /담기/ }).first();
|
||||
const hasData = await addButton
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (hasData) {
|
||||
await expect(addButton).toBeVisible();
|
||||
await expect(addButton).toBeEnabled();
|
||||
console.log("SUCCESS: 담기 버튼 확인됨");
|
||||
} else {
|
||||
console.log("INFO: 품목 데이터 없음 - 빈 상태 확인");
|
||||
test.skip(true, "테스트 데이터 없음 - 담기 버튼 테스트 스킵");
|
||||
}
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/05-add-button.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 6: 수량 입력 모달 열기
|
||||
// -------------------------------------------
|
||||
test("수량 버튼 클릭 시 숫자 입력 모달이 열린다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 거래처 선택
|
||||
const selected = await selectTestCustomer(page);
|
||||
if (!selected) {
|
||||
test.skip(true, "테스트 거래처를 선택할 수 없음");
|
||||
return;
|
||||
}
|
||||
|
||||
// 수량 버튼 찾기 (숫자 + 단위 표시된 버튼)
|
||||
const qtyButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: /\d+.*?(EA|kg|개|톤|m|L)/i })
|
||||
.first();
|
||||
const hasQtyButton = await qtyButton
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (!hasQtyButton) {
|
||||
test.skip(true, "수량 버튼을 찾을 수 없음");
|
||||
return;
|
||||
}
|
||||
|
||||
// 수량 버튼 클릭
|
||||
await qtyButton.click();
|
||||
|
||||
// 모달이 열렸는지 확인 (숫자 키패드 또는 확인 버튼)
|
||||
const confirmButton = page.getByRole("button", { name: /확인/ });
|
||||
await expect(confirmButton).toBeVisible({ timeout: 5_000 });
|
||||
|
||||
// 키패드 숫자 버튼이 있는지
|
||||
const numberButton = page
|
||||
.getByRole("button", { name: /^[0-9]$/ })
|
||||
.first();
|
||||
await expect(numberButton).toBeVisible();
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/06-number-modal.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 7: 수량 입력 후 담기 전체 흐름
|
||||
// -------------------------------------------
|
||||
test("수량 입력 -> 담기 -> 장바구니 저장 흐름이 동작한다", async ({
|
||||
page,
|
||||
}) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 거래처 선택
|
||||
const selected = await selectTestCustomer(page);
|
||||
if (!selected) {
|
||||
test.skip(true, "테스트 거래처를 선택할 수 없음");
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. 담기 버튼이 있는지 확인
|
||||
const addButton = page.getByRole("button", { name: /담기/ }).first();
|
||||
const hasData = await addButton
|
||||
.isVisible({ timeout: 5_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (!hasData) {
|
||||
test.skip(true, "테스트 데이터 없음 - 담기 흐름 테스트 스킵");
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 수량 버튼 클릭 -> 모달 열기
|
||||
const qtyButton = page
|
||||
.locator("button")
|
||||
.filter({ hasText: /\d+.*?(EA|kg|개|톤|m|L)/i })
|
||||
.first();
|
||||
if (await qtyButton.isVisible()) {
|
||||
await qtyButton.click();
|
||||
|
||||
// 3. 숫자 입력 (1, 0 -> 10)
|
||||
const numBtn1 = page.getByRole("button", { name: "1" });
|
||||
const numBtn0 = page.getByRole("button", { name: "0" });
|
||||
if (await numBtn1.isVisible({ timeout: 3_000 }).catch(() => false)) {
|
||||
await numBtn1.click();
|
||||
await numBtn0.click();
|
||||
}
|
||||
|
||||
// 4. 확인 클릭
|
||||
const confirmBtn = page.getByRole("button", { name: /확인/ });
|
||||
if (await confirmBtn.isVisible()) {
|
||||
await confirmBtn.click();
|
||||
// 모달 닫힘 대기
|
||||
await confirmBtn
|
||||
.waitFor({ state: "hidden", timeout: 5_000 })
|
||||
.catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 담기 버튼 클릭
|
||||
await addButton.click();
|
||||
|
||||
// 6. 담기 후 상태 변화 확인 (버튼이 "취소"로 바뀌거나 카드 스타일 변경)
|
||||
await page.waitForTimeout(1_000); // API 호출 대기
|
||||
|
||||
const cancelButton = page.getByRole("button", { name: /취소/ }).first();
|
||||
const hasCancelButton = await cancelButton
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
// 담기 성공: 취소 버튼이 나타남
|
||||
if (hasCancelButton) {
|
||||
console.log("SUCCESS: 담기 성공 - 취소 버튼 표시됨");
|
||||
} else {
|
||||
console.log(
|
||||
"INFO: 취소 버튼이 안 보임 - 담기 결과 추가 확인 필요"
|
||||
);
|
||||
}
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/07-after-add-to-cart.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 8: 장바구니 취소 동작
|
||||
// -------------------------------------------
|
||||
test("담기 후 취소 버튼으로 장바구니에서 제거된다", async ({ page }) => {
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
// 거래처 선택
|
||||
const selected = await selectTestCustomer(page);
|
||||
if (!selected) {
|
||||
test.skip(true, "테스트 거래처를 선택할 수 없음");
|
||||
return;
|
||||
}
|
||||
|
||||
// 이미 담긴 항목이 있는지 확인 (취소 버튼 존재 여부)
|
||||
const cancelButton = page.getByRole("button", { name: /취소/ }).first();
|
||||
const hasCancelButton = await cancelButton
|
||||
.isVisible({ timeout: 3_000 })
|
||||
.catch(() => false);
|
||||
|
||||
if (!hasCancelButton) {
|
||||
// 먼저 담기를 수행
|
||||
const addButton = page.getByRole("button", { name: /담기/ }).first();
|
||||
const hasAddButton = await addButton
|
||||
.isVisible({ timeout: 3_000 })
|
||||
.catch(() => false);
|
||||
if (!hasAddButton) {
|
||||
test.skip(true, "테스트 데이터 없음 - 취소 테스트 스킵");
|
||||
return;
|
||||
}
|
||||
await addButton.click();
|
||||
await page.waitForTimeout(1_000);
|
||||
}
|
||||
|
||||
// 취소 버튼 클릭
|
||||
const cancelBtn = page.getByRole("button", { name: /취소/ }).first();
|
||||
if (await cancelBtn.isVisible()) {
|
||||
await cancelBtn.click();
|
||||
await page.waitForTimeout(1_000);
|
||||
|
||||
// 취소 후: 담기 버튼이 다시 나타남
|
||||
const addButtonAfter = page
|
||||
.getByRole("button", { name: /담기/ })
|
||||
.first();
|
||||
const hasAddAfterCancel = await addButtonAfter
|
||||
.isVisible()
|
||||
.catch(() => false);
|
||||
|
||||
if (hasAddAfterCancel) {
|
||||
console.log("SUCCESS: 취소 성공 - 담기 버튼 다시 표시됨");
|
||||
}
|
||||
}
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/08-after-cancel.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 9: 반응형 모드 확인 (태블릿 가로)
|
||||
// -------------------------------------------
|
||||
test("태블릿 가로 모드에서 정상 렌더링된다", async ({ page }) => {
|
||||
// 태블릿 가로 (1024x800)
|
||||
await page.setViewportSize({ width: 1024, height: 800 });
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
await page.waitForTimeout(1_000);
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/09-tablet-landscape.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------------------
|
||||
// 시나리오 10: 반응형 모드 확인 (모바일 세로)
|
||||
// -------------------------------------------
|
||||
test("모바일 세로 모드에서 정상 렌더링된다", async ({ page }) => {
|
||||
// 모바일 세로 (375x667)
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await navigateToPopScreen(page);
|
||||
|
||||
await page.waitForTimeout(1_000);
|
||||
|
||||
// 화면이 깨지지 않고 렌더링되는지 확인
|
||||
const errorText = page.getByText("화면을 찾을 수 없습니다");
|
||||
await expect(errorText).not.toBeVisible();
|
||||
|
||||
await page.screenshot({
|
||||
path: "tests/e2e/screenshots/10-mobile-portrait.png",
|
||||
fullPage: true,
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue