import { test, expect } from '@playwright/test' const taskId = '00000000-0000-0000-0000-000000000101' function task(stage: string, version: number, pickedQty = 0) { const completed = stage === 'completed' return { taskId, taskNo: 'PICK-20260808-001', stage, status: completed ? 'COMPLETED' : stage === 'ready' ? 'READY' : 'IN_PROGRESS', completedLines: completed ? 1 : 0, totalLines: 1, completedQty: completed ? 2 : pickedQty, totalQty: 2, version, currentLine: completed ? null : { lineId: '00000000-0000-0000-0000-000000000201', lineNo: 1, locationCode: 'A-03-02', itemId: '00000000-0000-0000-0000-000000000301', itemCode: 'ABC001', itemName: '운동화', itemOption: 'BLACK / 270', barcode: '8801234567890', requiredQty: 2, pickedQty, remainingQty: 2 - pickedQty, }, } } test.describe('WMS-PICK-001 피킹 Golden Screen', () => { test('위치 → 상품 스캔을 확인 modal 없이 연속 처리한다', async ({ page }) => { let current = task('ready', 1) await page.route(`**/api/wms/picking/tasks/${taskId}`, route => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) })) await page.route(`**/api/wms/picking/tasks/${taskId}/start`, route => { current = task('await-location', 2) return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) }) }) await page.route(`**/api/wms/picking/tasks/${taskId}/scan`, async route => { const body = route.request().postDataJSON() if (body.barcode === 'LOC-A-03-02') { current = task('await-item', 3) return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ accepted: true, duplicate: false, task: current, feedback: 'success', message: '위치를 확인했습니다. 상품을 스캔하세요.', }) }) } current = task('await-item', 4, 1) return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ accepted: true, duplicate: false, task: current, feedback: 'success', message: '1개 피킹했습니다.', }) }) }) await page.goto(`/wms/picking/${taskId}`) await expect(page.locator('[data-screen-id="WMS-PICK-001"]')).toBeVisible() await page.getByRole('button', { name: '작업 시작' }).click() await expect(page.getByText('위치를 스캔하세요.')).toBeVisible() // Keyboard-wedge scanners typically emit fast characters followed by Enter. await page.keyboard.type('LOC-A-03-02', { delay: 10 }) await page.keyboard.press('Enter') await expect(page.getByText('상품을 스캔하세요.')).toBeVisible() await page.keyboard.type('8801234567890', { delay: 10 }) await page.keyboard.press('Enter') await expect(page.getByText('1개 피킹했습니다.')).toBeVisible() await expect(page.getByText('남음').locator('..').getByText('1')).toBeVisible() }) test('잘못된 위치는 retry queue 대상이 아닌 업무 오류로 즉시 안내한다', async ({ page }) => { let current = task('await-location', 2) await page.route(`**/api/wms/picking/tasks/${taskId}`, route => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(current) })) await page.route(`**/api/wms/picking/tasks/${taskId}/scan`, route => route.fulfill({ status: 422, contentType: 'application/json', body: JSON.stringify({ accepted: false, duplicate: false, task: current, feedback: 'error', message: '잘못된 위치입니다. A-03-02 위치로 이동하세요.', }) })) await page.goto(`/wms/picking/${taskId}`) await page.keyboard.type('WRONG-LOC', { delay: 10 }) await page.keyboard.press('Enter') await expect(page.getByText('잘못된 위치입니다. A-03-02 위치로 이동하세요.')).toBeVisible() await expect(page.getByText('전송 대기')).toHaveCount(0) }) test('오프라인이면 다음 authoritative scan을 받지 않는다', async ({ page, context }) => { await page.route(`**/api/wms/picking/tasks/${taskId}`, route => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(task('await-item', 3)) })) await page.goto(`/wms/picking/${taskId}`) await context.setOffline(true) await page.evaluate(() => window.dispatchEvent(new Event('offline'))) await expect(page.getByText(/오프라인/)).toBeVisible() await expect(page.getByText('SCAN PAUSED')).toBeVisible() }) })