All checks were successful
ERP-Deploy-Demo / deploy-demo (push) Successful in 55s
128 lines
5.7 KiB
TypeScript
128 lines
5.7 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
import { login } from './helpers/auth';
|
|
import * as fs from 'fs';
|
|
|
|
/**
|
|
* 採購模組端到端測試
|
|
* 驗證「批量寫入」(多筆明細 bulk insert) 與「併發鎖定」(狀態變更 lockForUpdate)
|
|
*/
|
|
test.describe('採購管理 - 採購單建立', () => {
|
|
// 登入 + 導航 + 表單操作需要較長時間
|
|
test.use({ actionTimeout: 15000 });
|
|
|
|
test.beforeEach(async ({ page }) => {
|
|
await login(page);
|
|
});
|
|
|
|
test('應能成功建立含多筆明細的採購單', async ({ page }) => {
|
|
// 整體測試逾時設定為 90 秒(含多次選單互動)
|
|
test.setTimeout(90000);
|
|
|
|
// 1. 前往採購單列表
|
|
await page.goto('/purchase-orders');
|
|
await expect(page.getByRole('heading', { name: '採購單管理' })).toBeVisible();
|
|
|
|
// 2. 點擊「建立採購單」按鈕
|
|
await page.getByRole('button', { name: /建立採購單/ }).click();
|
|
await expect(page.getByRole('heading', { name: '建立採購單' })).toBeVisible({ timeout: 10000 });
|
|
|
|
// 3. 選擇倉庫 (使用 SearchableSelect combobox)
|
|
const warehouseCombobox = page.locator('label:has-text("預計入庫倉庫")').locator('..').getByRole('combobox');
|
|
await warehouseCombobox.click();
|
|
await page.getByRole('option', { name: '中央倉庫' }).click();
|
|
|
|
// 4. 選擇供應商
|
|
const supplierCombobox = page.locator('label:has-text("供應商")').locator('..').getByRole('combobox');
|
|
await supplierCombobox.click();
|
|
await page.getByRole('option', { name: '台積電' }).click();
|
|
|
|
// 5. 填寫下單日期(應該已有預設值,但確保有值)
|
|
const orderDateInput = page.locator('label:has-text("下單日期")').locator('..').locator('input[type="date"]');
|
|
const currentDate = await orderDateInput.inputValue();
|
|
if (!currentDate) {
|
|
const today = new Date().toISOString().split('T')[0];
|
|
await orderDateInput.fill(today);
|
|
}
|
|
|
|
// 6. 填寫備註
|
|
await page.getByPlaceholder('備註這筆採購單的特殊需求...').fill('E2E 自動化測試 - 批量寫入驗證');
|
|
|
|
// 7. 新增第一個品項
|
|
await page.getByRole('button', { name: '新增一個品項' }).click();
|
|
|
|
// 選擇商品(第一行)
|
|
const firstRow = page.locator('table tbody tr').first();
|
|
const firstProductCombobox = firstRow.getByRole('combobox').first();
|
|
await firstProductCombobox.click();
|
|
await page.getByRole('option', { name: '紅糖' }).click();
|
|
|
|
// 填寫數量
|
|
const firstQtyInput = firstRow.locator('input[type="number"]').first();
|
|
await firstQtyInput.clear();
|
|
await firstQtyInput.fill('5');
|
|
|
|
// 填寫小計(主要金額欄位)
|
|
const firstSubtotalInput = firstRow.locator('input[type="number"]').nth(1);
|
|
await firstSubtotalInput.fill('500');
|
|
|
|
// 8. 新增第二個品項(驗證批量寫入)
|
|
await page.getByRole('button', { name: '新增一個品項' }).click();
|
|
|
|
const secondRow = page.locator('table tbody tr').nth(1);
|
|
const secondProductCombobox = secondRow.getByRole('combobox').first();
|
|
await secondProductCombobox.click();
|
|
await page.getByRole('option', { name: '粗吸管' }).click();
|
|
|
|
const secondQtyInput = secondRow.locator('input[type="number"]').first();
|
|
await secondQtyInput.clear();
|
|
await secondQtyInput.fill('10');
|
|
|
|
const secondSubtotalInput = secondRow.locator('input[type="number"]').nth(1);
|
|
await secondSubtotalInput.fill('200');
|
|
|
|
// 9. 點擊「確認發布採購單」
|
|
await page.getByRole('button', { name: '確認發布採購單' }).click();
|
|
|
|
// 10. 驗證結果 — 應跳轉回列表頁或顯示詳情頁
|
|
// Inertia.js 的 onSuccess 會觸發頁面導航
|
|
await expect(
|
|
page.getByRole('heading', { name: '採購單管理' }).or(page.getByRole('heading', { name: /PO-/ }))
|
|
).toBeVisible({ timeout: 15000 });
|
|
|
|
// 11. 截圖留存
|
|
if (!fs.existsSync('e2e/screenshots')) fs.mkdirSync('e2e/screenshots', { recursive: true });
|
|
await page.screenshot({ path: 'e2e/screenshots/procurement-po-create-success.png', fullPage: true });
|
|
});
|
|
|
|
test('應能成功編輯採購單', async ({ page }) => {
|
|
test.setTimeout(60000);
|
|
|
|
// 1. 前往採購單列表
|
|
await page.goto('/purchase-orders');
|
|
await expect(page.getByRole('heading', { name: '採購單管理' })).toBeVisible();
|
|
|
|
// 2. 找到並點擊第一個可編輯的採購單 (草稿或待審核狀態)
|
|
const editLink = page.locator('button[title="編輯"], a[title="編輯"]').first();
|
|
await expect(editLink).toBeVisible({ timeout: 10000 });
|
|
await editLink.click();
|
|
|
|
// 3. 驗證已進入編輯頁
|
|
await expect(page.getByRole('heading', { name: '編輯採購單' })).toBeVisible({ timeout: 15000 });
|
|
|
|
// 4. 修改備註
|
|
await page.getByPlaceholder('備註這筆採購單的特殊需求...').fill('E2E 自動化測試 - 已被編輯過');
|
|
|
|
// 5. 點擊「更新採購單」
|
|
await page.getByRole('button', { name: '更新採購單' }).click();
|
|
|
|
// 6. 驗證結果 — 返回列表或詳情頁
|
|
await expect(
|
|
page.getByRole('heading', { name: '採購單管理' }).or(page.getByRole('heading', { name: /PO-/ }))
|
|
).toBeVisible({ timeout: 15000 });
|
|
|
|
// 7. 截圖留存
|
|
if (!fs.existsSync('e2e/screenshots')) fs.mkdirSync('e2e/screenshots', { recursive: true });
|
|
await page.screenshot({ path: 'e2e/screenshots/procurement-po-edit-success.png', fullPage: true });
|
|
});
|
|
});
|