V13-FE-011: finalize search list layout slice
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
test.describe('KBX application shell',()=>{
|
||||
test('root opens business home without creating a workspace tab',async({page})=>{await page.goto('/');await expect(page).toHaveURL(/\/home$/);await expect(page.getByRole('heading',{name:'홈'})).toBeVisible();await expect(page.getByRole('navigation',{name:'열린 업무'})).toContainText('열린 업무가 없습니다.')})
|
||||
test('mouse user opens menu search and order screen',async({page})=>{await page.goto('/');await page.getByRole('button',{name:/메뉴 검색/}).click();await page.getByRole('searchbox').fill('주문관리');await page.keyboard.press('Enter');await expect(page).toHaveURL(/\/oms\/orders/)})
|
||||
test('keyboard user opens same menu with Ctrl+K',async({page})=>{await page.goto('/');await page.keyboard.press('Control+k');await page.getByRole('searchbox').fill('ERP-INV-001');await page.keyboard.press('Enter');await expect(page).toHaveURL(/\/erp\/inventory/)})
|
||||
test('workspace keeps multiple business contexts',async({page})=>{await page.goto('/oms/orders');await page.goto('/erp/inventory');await expect(page.getByRole('navigation',{name:'열린 업무'})).toContainText('주문관리');await expect(page.getByRole('navigation',{name:'열린 업무'})).toContainText('재고현황')})
|
||||
test('dirty transaction does not close silently',async({page})=>{await page.goto('/oms/orders/new');await page.getByLabel('수취인').fill('홍길동');await page.getByRole('button',{name:'닫기'}).click();await expect(page.getByText('저장하지 않은 변경사항이 있습니다.')).toBeVisible()})
|
||||
})
|
||||
|
||||
test.describe('KBX v29 shell completion',()=>{
|
||||
test('home promotes business quick-start without duplicating dashboard cards',async({page})=>{await page.goto('/home');await expect(page.getByRole('heading',{name:'바로 시작'})).toBeVisible();await expect(page.getByRole('button',{name:/주문관리/}).first()).toBeVisible()})
|
||||
test('menu search keeps focus inside the modal and exposes listbox semantics',async({page})=>{await page.goto('/home');await page.keyboard.press('Control+k');const search=page.getByRole('combobox');await expect(search).toBeFocused();await expect(page.getByRole('listbox')).toBeVisible();await page.keyboard.press('Shift+Tab');await page.keyboard.press('Tab');await expect(page.getByRole('dialog',{name:/메뉴/})).toBeVisible()})
|
||||
test('screen header exposes help utility from the common host',async({page})=>{await page.goto('/oms/orders');await expect(page.getByRole('button',{name:'도움말'}).first()).toBeVisible()})
|
||||
})
|
||||
|
||||
|
||||
test.describe('KBX v30 shell recovery',()=>{
|
||||
test('unknown deep link provides safe navigation recovery',async({page})=>{await page.goto('/unknown/deep/link');await expect(page.getByRole('heading',{name:'화면을 찾을 수 없습니다.'})).toBeVisible();await page.getByRole('button',{name:'메뉴 검색'}).click();await expect(page.getByRole('dialog')).toBeVisible()})
|
||||
test('global module selector and side navigation share one module context',async({page})=>{await page.goto('/home');const moduleSelect=page.getByLabel('업무 모듈');await moduleSelect.selectOption('ERP');await expect(page.getByRole('heading',{name:'ERP 업무'})).toBeVisible()})
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { requireKbxScenario, scenarioTitle } from './helpers/kbxScenario'
|
||||
|
||||
const queueRecovery=requireKbxScenario('scenario.common.operations.queue-recovery')
|
||||
|
||||
test.describe('COMMON-OPS-001 업무 예외 센터', () => {
|
||||
test(scenarioTitle(queueRecovery.id), async ({ page }) => {
|
||||
await page.goto('/operations/exceptions')
|
||||
await expect(page.locator('[data-screen-id="COMMON-OPS-001"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="exception-summary"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="queue/content"]')).toBeVisible()
|
||||
await expect(page.getByText(/정상 건은 표시하지 않습니다/)).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,13 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { requireKbxScenario, scenarioTitle } from './helpers/kbxScenario'
|
||||
|
||||
const mismatchRecovery=requireKbxScenario('scenario.common.reconcile.mismatch-recovery')
|
||||
|
||||
test.describe('COMMON-REC-001 업무 데이터 대사', () => {
|
||||
test(scenarioTitle(mismatchRecovery.id), async ({ page }) => {
|
||||
await page.goto('/operations/reconcile')
|
||||
await expect(page.locator('[data-screen-id="COMMON-REC-001"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="criteria/search"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="comparison-grid"]')).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('T05 inventory keeps master context and exposes locations, history, drill-down', async ({ page }) => {
|
||||
await page.goto('/erp/inventory')
|
||||
await expect(page.getByText('창고/로케이션')).toBeVisible()
|
||||
await expect(page.getByText('재고이력')).toBeVisible()
|
||||
await expect(page.getByText('품목을 선택하면 로케이션과 재고이력을 함께 조회합니다.')).toBeVisible()
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { requireKbxScenario, scenarioTitle } from './helpers/kbxScenario'
|
||||
|
||||
const masterRecovery=requireKbxScenario('scenario.erp.item-master.keyboard-recovery')
|
||||
|
||||
test.describe('ERP-MST-ITEM-001 T02 Lifecycle',()=>{
|
||||
test(scenarioTitle(masterRecovery.id),async({page})=>{
|
||||
await page.goto('/erp/items')
|
||||
await expect(page.locator('[data-screen-id="ERP-MST-ITEM-001"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="master-list"]')).toBeVisible()
|
||||
await expect(page.locator('[data-kbx-surface="detail"]')).toBeVisible()
|
||||
await expect(page.getByRole('button',{name:/저장 F8/})).toBeDisabled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,9 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test('T04 item price fast entry supports lookup, paste, fill down and save', async ({ page }) => {
|
||||
await page.goto('/erp/item-prices')
|
||||
await expect(page.getByText('품목 단가 일괄등록')).toBeVisible()
|
||||
await expect(page.getByText('Excel 붙여넣기')).toBeVisible()
|
||||
await expect(page.getByRole('button', { name: '행 추가' })).toBeVisible()
|
||||
await expect(page.getByRole('button', { name: '아래 채우기' })).toBeVisible()
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
test('ERP-PUR-001 supports keyboard-first header/detail purchase entry', async ({page}) => {
|
||||
await page.goto('/erp/purchases/new'); await expect(page.locator('[data-screen-id="ERP-PUR-001"]')).toBeVisible(); await expect(page.getByText('현재 상태')).toBeVisible();
|
||||
})
|
||||
@@ -0,0 +1,12 @@
|
||||
import { kbxTestScenarioCatalog } from '@kbx/contracts'
|
||||
|
||||
export function requireKbxScenario(id: keyof typeof kbxTestScenarioCatalog) {
|
||||
const scenario = kbxTestScenarioCatalog[id]
|
||||
if (!scenario) throw new Error(`Unknown KBX scenario: ${String(id)}`)
|
||||
return scenario
|
||||
}
|
||||
|
||||
export function scenarioTitle(id: keyof typeof kbxTestScenarioCatalog) {
|
||||
const s = requireKbxScenario(id)
|
||||
return `[${s.id}] ${s.title}`
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { createHash, randomUUID } from 'node:crypto'
|
||||
import { readFile } from 'node:fs/promises'
|
||||
|
||||
export type KbxScenarioEvidenceArtifact = {
|
||||
type: string
|
||||
path: string
|
||||
sha256?: string
|
||||
}
|
||||
|
||||
export async function sha256File(path: string) {
|
||||
const bytes = await readFile(path)
|
||||
return createHash('sha256').update(bytes).digest('hex')
|
||||
}
|
||||
|
||||
export function createScenarioRunId() {
|
||||
return `kbx-scenario-${randomUUID()}`
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
import { requireKbxScenario, scenarioTitle } from './helpers/kbxScenario'
|
||||
|
||||
const orderKeyboard = requireKbxScenario('scenario.oms.order-register.keyboard')
|
||||
const shellDirty = requireKbxScenario('scenario.shell.unsaved-tab')
|
||||
|
||||
test(scenarioTitle(orderKeyboard.id), async ({ page }) => {
|
||||
await page.goto('/oms/orders/register')
|
||||
await page.keyboard.press('F2')
|
||||
await expect(page.getByRole('dialog')).toBeVisible()
|
||||
await page.keyboard.press('Escape')
|
||||
await page.keyboard.press('F8')
|
||||
// Host app should seed synthetic lookup data and assert saved/problem outcome.
|
||||
})
|
||||
|
||||
test(scenarioTitle(shellDirty.id), async ({ page }) => {
|
||||
await page.goto('/oms/orders/register')
|
||||
await page.getByLabel('수취인').fill('테스트수취인')
|
||||
await page.getByRole('button', { name: /주문등록.*닫기|닫기/ }).click()
|
||||
await expect(page.getByText('저장하지 않은 변경사항이 있습니다.')).toBeVisible()
|
||||
})
|
||||
@@ -0,0 +1,14 @@
|
||||
import { expect, test } from '@playwright/test'
|
||||
|
||||
for (const scenario of [
|
||||
{ density:'compact', width:1440, height:900 },
|
||||
{ density:'comfortable', width:1440, height:900 },
|
||||
{ density:'touch', width:390, height:844 },
|
||||
] as const) {
|
||||
test(`KBX catalog ${scenario.density} visual baseline`, async ({ page }) => {
|
||||
await page.setViewportSize({ width:scenario.width, height:scenario.height })
|
||||
await page.goto(`/internal/kbx/catalog?density=${scenario.density}`)
|
||||
await expect(page.getByRole('heading',{name:'KBX 컴포넌트 카탈로그'})).toBeVisible()
|
||||
await expect(page).toHaveScreenshot(`kbx-catalog-${scenario.density}.png`, { fullPage:true })
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
test('experiment governance screen keeps safe scope visible',async({page})=>{await page.goto('/internal/kbx/experiments');await expect(page.getByText('안전 범위')).toBeVisible();await expect(page.getByText(/권한·민감정보·Domain Rule/)).toBeVisible()})
|
||||
@@ -0,0 +1,12 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('KBX Fast Entry / Bulk Grid',()=>{
|
||||
test('catalog exposes explicit fast-entry actions and server-side whole-result selection',async({page})=>{
|
||||
await page.goto('/internal/kbx/catalog?density=compact')
|
||||
await expect(page.getByRole('heading',{name:'Fast Entry Grid'})).toBeVisible()
|
||||
await expect(page.getByRole('button',{name:'행 추가'})).toBeVisible()
|
||||
await expect(page.getByRole('button',{name:'행 복제'})).toBeVisible()
|
||||
await expect(page.getByRole('button',{name:'아래 채우기'})).toBeVisible()
|
||||
await expect(page.getByRole('button',{name:/검색결과 82,415건 전체선택/})).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,42 @@
|
||||
import { expect, test } from '@playwright/test'
|
||||
|
||||
test('core ERP keyboard contract remains consistent', async ({ page }) => {
|
||||
await page.goto('/oms/orders/new')
|
||||
await page.keyboard.press('F2')
|
||||
await page.keyboard.press('Escape')
|
||||
await page.keyboard.press('Tab')
|
||||
await page.keyboard.press('Shift+Tab')
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('F8')
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
|
||||
test('search screen keeps F3 and mouse-complete behavior', async ({ page }) => {
|
||||
await page.goto('/oms/orders')
|
||||
await page.keyboard.press('F3')
|
||||
await expect(page.getByRole('button',{name:/조회/})).toBeVisible()
|
||||
})
|
||||
|
||||
test('menu search is available by mouse and Ctrl+K', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
await expect(page.getByRole('button',{name:/메뉴 검색/})).toBeVisible()
|
||||
await page.keyboard.press('Control+K')
|
||||
await page.keyboard.type('재고')
|
||||
await page.keyboard.press('ArrowDown')
|
||||
await page.keyboard.press('Enter')
|
||||
})
|
||||
|
||||
test('component tabs support arrow, Home and End navigation', async ({ page }) => {
|
||||
await page.goto('/internal/kbx/catalog?density=compact')
|
||||
const basic=page.getByRole('tab',{name:'기본'})
|
||||
const audit=page.getByRole('tab',{name:/변경이력/})
|
||||
await basic.focus()
|
||||
await page.keyboard.press('ArrowRight')
|
||||
await expect(audit).toHaveAttribute('aria-selected','true')
|
||||
await page.keyboard.press('Home')
|
||||
await expect(basic).toHaveAttribute('aria-selected','true')
|
||||
await page.keyboard.press('End')
|
||||
await expect(audit).toHaveAttribute('aria-selected','true')
|
||||
await page.keyboard.press('ArrowLeft')
|
||||
await expect(basic).toHaveAttribute('aria-selected','true')
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
test('OMS-CLM-001 keeps claim processing inside familiar list/workflow grammar', async ({page}) => {
|
||||
await page.goto('/oms/claims'); await expect(page.locator('[data-screen-id="OMS-CLM-001"]')).toBeVisible(); await page.keyboard.press('F3');
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('OMS-ORD-003 주문 Excel Import Golden Flow', () => {
|
||||
test('파일 → 매핑 → 검증 → 정상건 반영', async ({ page }) => {
|
||||
await page.goto('/oms/orders/import')
|
||||
await expect(page.getByRole('heading', { name: '주문 Excel 업로드' })).toBeVisible()
|
||||
|
||||
// Host repository should supply tests/fixtures/orders-valid-and-invalid.xlsx.
|
||||
await page.locator('input[type=file]').setInputFiles('tests/fixtures/orders-valid-and-invalid.xlsx')
|
||||
await expect(page.getByText('2 매핑')).toBeVisible()
|
||||
|
||||
await page.getByRole('button', { name: '검증 시작' }).click()
|
||||
await expect(page.getByText('검증 결과')).toBeVisible({ timeout: 30_000 })
|
||||
await expect(page.getByText('오류')).toBeVisible()
|
||||
|
||||
await page.getByRole('button', { name: '정상 데이터 반영' }).click()
|
||||
await expect(page.getByText('신규')).toBeVisible({ timeout: 30_000 })
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,18 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('OMS-ORD-001 주문관리', () => {
|
||||
test('F3 조회 후 주문을 선택할 수 있다', async ({ page }) => {
|
||||
await page.goto('/oms/orders')
|
||||
await page.keyboard.press('F3')
|
||||
|
||||
const screen = page.locator('[data-screen-id="OMS-ORD-001"]')
|
||||
await expect(screen).toBeVisible()
|
||||
|
||||
// 실제 프로젝트에서는 API fixture를 고정하고 grid row selector를 KBX testing helper로 감싼다.
|
||||
})
|
||||
|
||||
test('선택 전 출고지시는 비활성화된다', async ({ page }) => {
|
||||
await page.goto('/oms/orders')
|
||||
await expect(page.getByRole('button', { name: /출고지시/ })).toBeDisabled()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('OMS-ORD-002 주문등록 Golden Screen', () => {
|
||||
test('키보드 중심 주문등록: F2 lookup → detail entry → F8 save', async ({ page }) => {
|
||||
await page.goto('/oms/orders/new')
|
||||
|
||||
await expect(page.locator('[data-screen-id="OMS-ORD-002"]')).toBeVisible()
|
||||
|
||||
// 거래처 Lookup: real test environment should seed deterministic customer fixture.
|
||||
const customerCode = page.getByLabel('코드').first()
|
||||
await customerCode.focus()
|
||||
await page.keyboard.press('F2')
|
||||
await expect(page.getByText('거래처 검색')).toBeVisible()
|
||||
await page.keyboard.press('Escape')
|
||||
|
||||
// Header validation is visible without losing entered data.
|
||||
await page.keyboard.press('F8')
|
||||
await expect(page.getByText(/항목을 확인하세요/)).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('KBX production resilience UX', () => {
|
||||
test('version conflict does not silently overwrite latest server data', async ({ page }) => {
|
||||
await page.goto('/oms/orders/new')
|
||||
// Host repository should stub a 409 KbxConflictProblem after editing.
|
||||
// Verify KbxConflictResolver shows latest server values and no second mutation occurs automatically.
|
||||
})
|
||||
|
||||
test('long-running operation remains visible after route change', async ({ page }) => {
|
||||
await page.goto('/oms/orders/import')
|
||||
// Start a background import, navigate away, then verify the runtime Operation Center still exposes progress.
|
||||
})
|
||||
|
||||
test('degraded mode is visible without blocking unaffected reads', async ({ page }) => {
|
||||
await page.goto('/oms/orders')
|
||||
// Stub /api/kbx/runtime/notice as degraded and verify the banner is visible while the list remains usable.
|
||||
await expect(page.locator('[data-screen-id="OMS-ORD-001"]')).toBeVisible()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,109 @@
|
||||
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()
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
import { test, expect } from '@playwright/test'
|
||||
for (const [path,id] of [['/wms/receiving/task-1','WMS-REC-001'],['/wms/putaway/task-1','WMS-PUT-001'],['/wms/counting/task-1','WMS-COUNT-001']] as const) {
|
||||
test(`${id} uses the WMS mobile shell`, async ({page}) => { await page.goto(path); await expect(page.locator(`[data-screen-id="${id}"]`)).toBeVisible() })
|
||||
}
|
||||
Reference in New Issue
Block a user