221 lines
8.0 KiB
TypeScript
221 lines
8.0 KiB
TypeScript
import type { Page, Route } from '@playwright/test';
|
|
import { expect, test } from '@playwright/test';
|
|
|
|
const templateId = '01M00000000000000000000210';
|
|
const readonlyTemplateId = '01M00000000000000000000211';
|
|
const documentId = '01M00000000000000000000212';
|
|
|
|
function template(overrides: Record<string, unknown> = {}) {
|
|
return {
|
|
publicId: templateId,
|
|
formType: 'OA-01',
|
|
templateVersion: 1,
|
|
name: '项目立项申请',
|
|
groupCode: 'PROJECT_PREPARATION',
|
|
groupName: '项目准备',
|
|
purpose: '形成项目基础资料',
|
|
initiatorRoles: ['PROJECT_MANAGER'],
|
|
status: 'ACTIVE',
|
|
publishedAt: '2026-08-15T08:00:00Z',
|
|
myDraftCount: 1,
|
|
myPendingCount: 0,
|
|
canCreate: true,
|
|
fields: [],
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function sourceForm() {
|
|
return {
|
|
publicId: documentId,
|
|
businessNo: 'OA01-E2E-001',
|
|
formType: 'OA-01',
|
|
formName: '项目立项申请',
|
|
templateVersion: 1,
|
|
sourceSystem: 'MANUAL',
|
|
sourceNo: 'SRC-OA01-E2E-001',
|
|
sourceVersion: '1',
|
|
company: { publicId: '01M00000000000000000000213', name: '凯迪测试公司' },
|
|
project: { publicId: '01M00000000000000000000214', name: '表单中心验收项目' },
|
|
applicantName: '项目经办人',
|
|
businessDate: '2026-08-15',
|
|
status: 'DRAFT',
|
|
currentNodeCode: null,
|
|
currentNodeName: null,
|
|
version: 0,
|
|
createdByName: '项目经办人',
|
|
createdAt: '2026-08-15T08:00:00Z',
|
|
updatedAt: '2026-08-15T08:00:00Z',
|
|
allowedActions: ['EDIT', 'VALIDATE', 'SUBMIT', 'VOID'],
|
|
};
|
|
}
|
|
|
|
function session() {
|
|
return {
|
|
authenticated: true,
|
|
user: {
|
|
publicId: '01M00000000000000000000215',
|
|
username: 'forms-e2e',
|
|
displayName: '表单验收用户',
|
|
departmentName: '项目部',
|
|
mustChangePassword: false,
|
|
},
|
|
roles: [{ code: 'PROJECT_MANAGER', name: '项目管理人员', workbenchRoute: '/workbench/project' }],
|
|
activeRole: 'PROJECT_MANAGER',
|
|
permissions: ['source:template:view', 'source:form:view', 'source:form:create', 'source:form:validate'],
|
|
};
|
|
}
|
|
|
|
async function installFormCenterFixture(
|
|
page: Page,
|
|
validateRequests: Array<Record<string, unknown>>,
|
|
formQueries: URLSearchParams[] = [],
|
|
) {
|
|
const userSession = session();
|
|
await page.route('**/api/v1/**', async (route: Route) => {
|
|
const request = route.request();
|
|
const pathname = new URL(request.url()).pathname;
|
|
if (pathname === '/api/v1/auth/session') {
|
|
await route.fulfill({ json: { data: userSession, requestId: '01M00000000000000000000216' } });
|
|
return;
|
|
}
|
|
if (pathname === '/api/v1/auth/profile') {
|
|
await route.fulfill({ json: { data: userSession.user, requestId: '01M00000000000000000000217' } });
|
|
return;
|
|
}
|
|
if (pathname === '/api/v1/auth/roles') {
|
|
await route.fulfill({ json: { data: userSession.roles, requestId: '01M00000000000000000000218' } });
|
|
return;
|
|
}
|
|
if (pathname === '/api/v1/auth/csrf') {
|
|
await route.fulfill({
|
|
headers: { 'set-cookie': 'XSRF-TOKEN=forms-e2e-csrf; Path=/' },
|
|
json: { data: { token: 'forms-e2e-csrf' }, requestId: '01M00000000000000000000219' },
|
|
});
|
|
return;
|
|
}
|
|
if (request.method() === 'GET' && pathname === '/api/v1/source/templates') {
|
|
await route.fulfill({
|
|
json: {
|
|
data: [
|
|
template(),
|
|
template({
|
|
publicId: readonlyTemplateId,
|
|
formType: 'OA-02',
|
|
name: '供应商准入申请',
|
|
purpose: '形成供应商准入资料',
|
|
initiatorRoles: ['FINANCE_MANAGER'],
|
|
myDraftCount: 0,
|
|
canCreate: false,
|
|
}),
|
|
template({
|
|
publicId: '01M00000000000000000000224',
|
|
formType: 'OA-05',
|
|
templateVersion: 2,
|
|
name: '收款确认申请',
|
|
groupCode: 'INCOME_EXPENSE',
|
|
groupName: '收支执行',
|
|
}),
|
|
],
|
|
requestId: '01M00000000000000000000220',
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
if (request.method() === 'GET' && pathname === '/api/v1/source/forms') {
|
|
formQueries.push(new URL(request.url()).searchParams);
|
|
await route.fulfill({
|
|
json: {
|
|
data: [sourceForm()],
|
|
meta: { page: 1, size: 20, totalElements: 1, totalPages: 1 },
|
|
requestId: '01M00000000000000000000221',
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
if (request.method() === 'POST' && pathname === `/api/v1/source/forms/${documentId}/validate`) {
|
|
validateRequests.push((request.postDataJSON() || {}) as Record<string, unknown>);
|
|
await route.fulfill({
|
|
json: {
|
|
data: {
|
|
documentId,
|
|
version: 0,
|
|
valid: true,
|
|
canSubmit: true,
|
|
errors: [],
|
|
warnings: [],
|
|
validatedAt: '2026-08-15T08:01:00Z',
|
|
},
|
|
requestId: '01M00000000000000000000222',
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
if (request.method() === 'GET') {
|
|
await route.fulfill({
|
|
json: {
|
|
data: [],
|
|
meta: { page: 1, size: 20, totalElements: 0, totalPages: 0 },
|
|
requestId: '01M00000000000000000000223',
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
await route.fulfill({ status: 204 });
|
|
});
|
|
}
|
|
|
|
test('PAGE-09 shows initiator roles, respects create rights and validates a draft', async ({ page }) => {
|
|
const validateRequests: Array<Record<string, unknown>> = [];
|
|
await installFormCenterFixture(page, validateRequests);
|
|
|
|
await page.goto('/forms');
|
|
await expect(page.getByRole('heading', { name: '表单中心', exact: true })).toBeVisible();
|
|
|
|
const editableCard = page.locator('.t-card').filter({ hasText: 'OA-01' });
|
|
await expect(editableCard.getByText('项目管理人员', { exact: true })).toBeVisible();
|
|
await expect(editableCard.getByRole('button', { name: '在线填写', exact: true })).toBeVisible();
|
|
await expect(editableCard.getByRole('button', { name: '导入', exact: true })).toBeVisible();
|
|
|
|
const readonlyCard = page.locator('.t-card').filter({ hasText: 'OA-02' });
|
|
await expect(readonlyCard.getByText('财务管理人员', { exact: true })).toBeVisible();
|
|
await expect(readonlyCard.getByRole('button', { name: '在线填写', exact: true })).toHaveCount(0);
|
|
await expect(readonlyCard.getByRole('button', { name: '导入', exact: true })).toHaveCount(0);
|
|
|
|
await page.getByText('校验', { exact: true }).click();
|
|
await expect.poll(() => validateRequests.length).toBe(1);
|
|
expect(validateRequests[0]).toEqual({});
|
|
await expect(page.getByText('表单校验通过', { exact: true })).toBeVisible();
|
|
|
|
await editableCard.getByRole('button', { name: '在线填写', exact: true }).click();
|
|
await expect(page).toHaveURL(/\/forms\/OA-01\?mode=online/);
|
|
});
|
|
|
|
test('PAGE-09 sends group, version, creation date and sort filters and keeps them in the URL', async ({ page }) => {
|
|
const formQueries: URLSearchParams[] = [];
|
|
await installFormCenterFixture(page, [], formQueries);
|
|
|
|
await page.goto(
|
|
'/forms?groupCode=INCOME_EXPENSE&formType=OA-05&templateVersion=2' +
|
|
'&createdDateFrom=2026-08-01&createdDateTo=2026-08-15&sort=createdAt%2Casc',
|
|
);
|
|
await expect(page.getByRole('heading', { name: '表单中心', exact: true })).toBeVisible();
|
|
await expect.poll(() => formQueries.length).toBeGreaterThan(0);
|
|
|
|
const initial = formQueries.at(-1)!;
|
|
expect(initial.get('groupCode')).toBe('INCOME_EXPENSE');
|
|
expect(initial.get('formType')).toBe('OA-05');
|
|
expect(initial.get('templateVersion')).toBe('2');
|
|
expect(initial.get('createdDateFrom')).toBe('2026-08-01');
|
|
expect(initial.get('createdDateTo')).toBe('2026-08-15');
|
|
expect(initial.get('sort')).toBe('createdAt,asc');
|
|
await expect(page).toHaveURL(/groupCode=INCOME_EXPENSE/);
|
|
await expect(page).toHaveURL(/templateVersion=2/);
|
|
|
|
const requestCount = formQueries.length;
|
|
await page.getByText('项目准备', { exact: true }).click();
|
|
await expect.poll(() => formQueries.length).toBeGreaterThan(requestCount);
|
|
expect(formQueries.at(-1)!.get('groupCode')).toBe('PROJECT_PREPARATION');
|
|
await expect(page).toHaveURL(/groupCode=PROJECT_PREPARATION/);
|
|
});
|