121 行
3.4 KiB
TypeScript
121 行
3.4 KiB
TypeScript
import { expect, type Page } from "@playwright/test";
|
|
|
|
import { TEST_IDS } from "../testIds";
|
|
|
|
export class ReimbursementDetailPageObject {
|
|
readonly page: Page;
|
|
|
|
constructor(page: Page) {
|
|
this.page = page;
|
|
}
|
|
|
|
get overview() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.overview);
|
|
}
|
|
|
|
get summary() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.summary);
|
|
}
|
|
|
|
get itemsTable() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.items);
|
|
}
|
|
|
|
get addItemBtn() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.itemAdd);
|
|
}
|
|
|
|
get budgetHint() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.budgetHint);
|
|
}
|
|
|
|
get workflowProgress() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.workflowProgress);
|
|
}
|
|
|
|
get invoices() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.invoices);
|
|
}
|
|
|
|
get invoiceAddBtn() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.invoiceAdd);
|
|
}
|
|
|
|
get invoiceDialog() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.invoiceDialog);
|
|
}
|
|
|
|
get invoiceUploadFile() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.invoiceUploadFile);
|
|
}
|
|
|
|
get invoiceUploadSubmit() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.invoiceUploadSubmit);
|
|
}
|
|
|
|
get erpExport() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.erpExport);
|
|
}
|
|
|
|
get submitBtn() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.submit);
|
|
}
|
|
|
|
get withdrawBtn() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.withdraw);
|
|
}
|
|
|
|
get payBtn() {
|
|
return this.page.getByTestId(TEST_IDS.reimbursement.pay);
|
|
}
|
|
|
|
async assertLoaded() {
|
|
await expect(this.overview).toBeVisible({ timeout: 15_000 });
|
|
await expect(this.summary).toBeVisible({ timeout: 15_000 });
|
|
}
|
|
|
|
async assertStatus(statusText: string) {
|
|
await expect(this.summary).toContainText(statusText);
|
|
}
|
|
|
|
async uploadInvoicePdf(fileName: string, buffer: Buffer) {
|
|
await this.invoiceAddBtn.click();
|
|
await expect(this.invoiceDialog).toBeVisible();
|
|
|
|
const uploadResponsePromise = this.page.waitForResponse((response) => {
|
|
const url = new URL(response.url());
|
|
return response.request().method() === "POST" && url.pathname === "/api/invoice-pool/upload" && response.ok();
|
|
});
|
|
|
|
await this.invoiceUploadFile.setInputFiles({
|
|
name: fileName,
|
|
mimeType: "application/pdf",
|
|
buffer,
|
|
});
|
|
await this.invoiceUploadSubmit.scrollIntoViewIfNeeded();
|
|
await this.invoiceUploadSubmit.click();
|
|
|
|
const uploadPayload = (await (await uploadResponsePromise).json()) as { data?: { invoicePoolId?: string | null } };
|
|
const invoiceId = uploadPayload.data?.invoicePoolId;
|
|
if (!invoiceId) {
|
|
throw new Error(`上传发票后未返回票据 ID: ${JSON.stringify(uploadPayload)}`);
|
|
}
|
|
|
|
await expect(this.invoices).toContainText(fileName, { timeout: 90_000 });
|
|
await this.page.keyboard.press("Escape");
|
|
await expect(this.invoiceDialog).toHaveCount(0);
|
|
|
|
return invoiceId;
|
|
}
|
|
|
|
// 当前 seed 保证 precheck 不触发 warn/manual_review;若 seed 变更,此处需相应调整。
|
|
async submitReimbursement(acceptConfirm = true) {
|
|
const dialogPromise = acceptConfirm
|
|
? this.page.waitForEvent("dialog", { timeout: 2_000 }).then((dialog) => dialog.accept()).catch(() => undefined)
|
|
: Promise.resolve();
|
|
|
|
await this.submitBtn.click();
|
|
await dialogPromise;
|
|
}
|
|
}
|