사이트 메뉴 /bag/* 10개 페이지 구현 + E2E 테스트 timeout 보강
- Bag 컨트롤러 신규 (기본정보/발주입고/불출/재고/판매/판매현황/수불/통계/창/도움말) - 사이트 공통 레이아웃 bag/layout/main.php 추출 - /bag/* 라우트 10개 등록 (Routes.php) - bag-site.spec.js E2E 테스트 11개 추가 - Playwright timeout 30s→60s, waitForURL 15s→30s - P4 지자체관리자 접근 테스트 3개로 분리 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,7 +63,7 @@ test.describe('관리자 패널 — Super Admin', () => {
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// 선택 후 관리자 대시보드로 이동
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
await page.goto('/admin');
|
||||
await expect(page).not.toHaveURL(/\/select-local-government/);
|
||||
});
|
||||
@@ -74,7 +74,7 @@ test.describe('관리자 패널 — Super Admin', () => {
|
||||
const radio = page.locator('input[name="lg_idx"]').first();
|
||||
await radio.check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
|
||||
await page.goto('/admin/local-governments');
|
||||
await expect(page).toHaveURL(/\/admin\/local-governments/);
|
||||
|
||||
@@ -49,7 +49,7 @@ test.describe('인증 시스템', () => {
|
||||
test('로그아웃', async ({ page }) => {
|
||||
await login(page, 'local');
|
||||
await page.goto('/logout');
|
||||
await page.waitForURL(/\/login/, { timeout: 10000 });
|
||||
await page.waitForURL(/\/login/, { timeout: 30000 });
|
||||
await expect(page).toHaveURL(/\/login/);
|
||||
// 로그아웃 후 관리자 접근 불가 확인
|
||||
await page.goto('/admin');
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P2-03/04: 봉투 단가 관리', () => {
|
||||
|
||||
80
e2e/bag-site.spec.js
Normal file
80
e2e/bag-site.spec.js
Normal file
@@ -0,0 +1,80 @@
|
||||
// @ts-check
|
||||
const { test, expect } = require('@playwright/test');
|
||||
const { login } = require('./helpers/auth');
|
||||
|
||||
test.describe('사이트 메뉴 (/bag/*) 페이지 접근', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page, 'local');
|
||||
});
|
||||
|
||||
test('기본정보관리', async ({ page }) => {
|
||||
await page.goto('/bag/basic-info');
|
||||
await expect(page).toHaveURL(/\/bag\/basic-info/);
|
||||
await expect(page.locator('text=기본코드 종류')).toBeVisible();
|
||||
});
|
||||
|
||||
test('발주 입고 관리', async ({ page }) => {
|
||||
await page.goto('/bag/purchase-inbound');
|
||||
await expect(page).toHaveURL(/\/bag\/purchase-inbound/);
|
||||
await expect(page.locator('text=발주 현황')).toBeVisible();
|
||||
});
|
||||
|
||||
test('불출 관리', async ({ page }) => {
|
||||
await page.goto('/bag/issue');
|
||||
await expect(page).toHaveURL(/\/bag\/issue/);
|
||||
await expect(page.locator('th:has-text("불출일")')).toBeVisible();
|
||||
});
|
||||
|
||||
test('재고 관리', async ({ page }) => {
|
||||
await page.goto('/bag/inventory');
|
||||
await expect(page).toHaveURL(/\/bag\/inventory/);
|
||||
await expect(page.locator('th:has-text("현재재고")')).toBeVisible();
|
||||
});
|
||||
|
||||
test('판매 관리', async ({ page }) => {
|
||||
await page.goto('/bag/sales');
|
||||
await expect(page).toHaveURL(/\/bag\/sales/);
|
||||
await expect(page.locator('text=주문 접수')).toBeVisible();
|
||||
});
|
||||
|
||||
test('판매 현황', async ({ page }) => {
|
||||
await page.goto('/bag/sales-stats');
|
||||
await expect(page).toHaveURL(/\/bag\/sales-stats/);
|
||||
await expect(page.locator('th:has-text("봉투코드")')).toBeVisible();
|
||||
});
|
||||
|
||||
test('봉투 수불 관리', async ({ page }) => {
|
||||
await page.goto('/bag/flow');
|
||||
await expect(page).toHaveURL(/\/bag\/flow/);
|
||||
await expect(page.locator('th:has-text("현재재고")')).toBeVisible();
|
||||
});
|
||||
|
||||
test('통계 분석 관리', async ({ page }) => {
|
||||
await page.goto('/bag/analytics');
|
||||
await expect(page).toHaveURL(/\/bag\/analytics/);
|
||||
await expect(page.locator('main >> text=Phase 6에서 구현 예정')).toBeVisible();
|
||||
});
|
||||
|
||||
test('창', async ({ page }) => {
|
||||
await page.goto('/bag/window');
|
||||
await expect(page).toHaveURL(/\/bag\/window/);
|
||||
await expect(page.locator('text=창 관리')).toBeVisible();
|
||||
});
|
||||
|
||||
test('도움말', async ({ page }) => {
|
||||
await page.goto('/bag/help');
|
||||
await expect(page).toHaveURL(/\/bag\/help/);
|
||||
await expect(page.locator('text=시스템 개요')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('홈페이지 네비게이션 메뉴 링크', () => {
|
||||
test('메뉴 클릭으로 각 페이지 이동', async ({ page }) => {
|
||||
await login(page, 'local');
|
||||
await page.goto('/');
|
||||
|
||||
// 발주 입고 관리 메뉴 클릭
|
||||
await page.click('a:has-text("발주 입고 관리")');
|
||||
await expect(page).toHaveURL(/\/bag\/purchase-inbound/);
|
||||
});
|
||||
});
|
||||
@@ -8,7 +8,7 @@ async function loginAsAdmin(page) {
|
||||
const radio = page.locator('input[name="lg_idx"]').first();
|
||||
await radio.check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P2-01: 기본코드 종류 관리', () => {
|
||||
|
||||
@@ -15,10 +15,10 @@ async function run() {
|
||||
await page.fill('input[name="login_id"]', 'tester_admin');
|
||||
await page.fill('input[name="password"]', 'test1234!');
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('/login'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('/login'), { timeout: 30000 });
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
|
||||
const pages = [
|
||||
// Phase 2
|
||||
|
||||
@@ -20,7 +20,7 @@ async function login(page, account) {
|
||||
await page.fill('input[name="login_id"]', account.id);
|
||||
await page.fill('input[name="password"]', account.password);
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('/login'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('/login'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
async function screenshot(page, name, url) {
|
||||
@@ -52,7 +52,7 @@ async function run() {
|
||||
const radio = page.locator('input[name="lg_idx"]').first();
|
||||
await radio.check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
|
||||
console.log('\n=== 관리자 패널 (Super Admin) ===');
|
||||
await screenshot(page, '05_admin_dashboard', `${BASE_URL}/admin`);
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P2-05/06: 포장 단위 관리', () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
async function loginAsLocal(page) {
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P2-19: 지자체 수정/삭제', () => {
|
||||
@@ -42,7 +42,7 @@ test.describe('P2-21: 로그인 실패 lock', () => {
|
||||
await page.fill('input[name="login_id"]', 'tester_user');
|
||||
await page.fill('input[name="password"]', 'wrong_password');
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(/\/login/, { timeout: 15000 });
|
||||
await page.waitForURL(/\/login/, { timeout: 30000 });
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
// 3회 이후 실패 카운트 표시 확인
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P3: 발주 관리', () => {
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P4: 주문 접수 관리', () => {
|
||||
@@ -49,12 +49,18 @@ test.describe('P4: 무료용 불출 관리', () => {
|
||||
});
|
||||
|
||||
test.describe('P4: 지자체관리자 접근', () => {
|
||||
test('주문/판매/불출 접근 가능', async ({ page }) => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await login(page, 'local');
|
||||
});
|
||||
test('주문 접수 접근 가능', async ({ page }) => {
|
||||
await page.goto('/admin/shop-orders');
|
||||
await expect(page).toHaveURL(/\/admin\/shop-orders/);
|
||||
});
|
||||
test('판매 접근 가능', async ({ page }) => {
|
||||
await page.goto('/admin/bag-sales');
|
||||
await expect(page).toHaveURL(/\/admin\/bag-sales/);
|
||||
});
|
||||
test('불출 접근 가능', async ({ page }) => {
|
||||
await page.goto('/admin/bag-issues');
|
||||
await expect(page).toHaveURL(/\/admin\/bag-issues/);
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ async function loginAsAdmin(page) {
|
||||
await login(page, 'admin');
|
||||
await page.locator('input[name="lg_idx"]').first().check();
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 15000 });
|
||||
await page.waitForURL(url => !url.pathname.includes('select-local-government'), { timeout: 30000 });
|
||||
}
|
||||
|
||||
test.describe('P5: 판매 대장', () => {
|
||||
|
||||
Reference in New Issue
Block a user