Files
leaudit-platform-backend/test-results/leaudit-playwright-entry-module-remaining-acceptance.js
T
2026-05-25 09:50:01 +08:00

168 lines
7.4 KiB
JavaScript

const { chromium, request } = require('/home/wren-dev/Porject/leaudit-platform/legal-platform-frontend/node_modules/playwright');
const FRONTEND = process.env.LEAUDIT_FRONTEND_URL || 'http://172.16.0.59:5173';
const BACKEND = process.env.LEAUDIT_BACKEND_URL || 'http://127.0.0.1:8096';
const runId = `pwr${Date.now()}`;
const results = [];
function record(name, ok, details = {}) {
results.push({ name, ok, details });
console.log(`[${ok ? 'PASS' : 'FAIL'}] ${name}: ${JSON.stringify(details)}`);
if (!ok) throw new Error(`${name}: ${JSON.stringify(details)}`);
}
async function asJson(response) {
try {
return await response.json();
} catch {
return { text: await response.text() };
}
}
function unwrap(payload) {
if (payload && typeof payload === 'object' && Object.prototype.hasOwnProperty.call(payload, 'data')) {
return payload.data;
}
return payload;
}
async function apiFetch(api, method, path, token, options = {}) {
const headers = { ...(options.headers || {}) };
if (token) headers.Authorization = `Bearer ${token}`;
const response = await api.fetch(`${BACKEND}${path}`, { method, ...options, headers });
return { response, body: await asJson(response) };
}
async function loginFrontendContext(browser) {
const context = await browser.newContext({ viewport: { width: 1440, height: 1000 } });
const loginResponse = await context.request.post(`${FRONTEND}/api/auth/password-login`, {
data: { username: '000', password: 'admin06111' },
});
const loginBody = await asJson(loginResponse);
if (!loginResponse.ok() || !loginBody?.access_token) {
throw new Error(`前端登录失败 ${loginResponse.status()} ${JSON.stringify(loginBody)}`);
}
return { context, token: loginBody.access_token };
}
async function createEntryModule(api, token) {
const payload = {
name: `PW验收政务入口-${runId}`,
description: 'playwright remaining acceptance',
path: '/govdoc/audits',
route_path: '/govdoc/audits',
menu_profile: 'govdoc',
features: ['home', 'govdoc_audits', 'govdoc_upload', 'rule_groups'],
tenants: [{ tenant_code: 'PUBLIC', tenant_name: '公共资源域', enabled: true, sort_order: 1 }],
};
const { response, body } = await apiFetch(api, 'POST', '/api/v3/entry-modules', token, { data: payload });
record('创建名字不含公文的 govdoc 入口成功', response.status() === 200, { status: response.status(), body });
const module = unwrap(body);
record('govdoc 入口保存 menu_profile/features', module.menu_profile === 'govdoc' && module.features?.includes('govdoc_audits'), module);
return module;
}
async function createDocType(api, token, moduleId) {
const payload = {
code: `pw.remaining.${runId}`,
name: `PW验收文档类型-${runId}`,
description: 'playwright remaining acceptance',
entryModuleId: Number(moduleId),
isEnabled: true,
sortOrder: 1,
ruleSetIds: [],
};
const { response, body } = await apiFetch(api, 'POST', '/api/document-types', token, { data: payload });
record('为验收入口创建文档类型成功', response.status() === 200, { status: response.status(), body });
return unwrap(body);
}
async function sidebarTexts(page) {
return await page.locator('.sidebar a.sidebar-menu-item').evaluateAll((els) => (
els.map((el) => (el.textContent || '').replace(/\s+/g, ' ').trim()).filter(Boolean)
));
}
async function createCommonUserToken(api, adminToken) {
const sub = `pw-no-image-${runId}`;
const login = await apiFetch(api, 'POST', '/api/auth/login', null, {
data: {
userInfo: {
sub,
username: sub,
nickname: `PW无图标权限-${runId}`,
email: `${sub}@playwright.local`,
phone_number: '13800000000',
ou_id: 'pw-no-image',
ou_name: 'Playwright验收组织',
is_leader: false,
},
area: '公共资源域',
expiresIn: 3600,
},
});
record('创建无图标权限测试用户登录成功', login.response.status() === 200, { status: login.response.status(), body: login.body });
const loginData = unwrap(login.body);
const userId = Number(loginData.user_info?.user_id);
const roles = await apiFetch(api, 'GET', '/api/v3/rbac/roles?page=1&page_size=200', adminToken);
const roleItems = unwrap(roles.body)?.items || [];
const commonRole = roleItems.find((item) => item.role_key === 'common');
record('找到 common 角色用于无权限验收', Boolean(commonRole?.id), { commonRole });
const assign = await apiFetch(api, 'POST', `/api/v3/rbac/users/${userId}/roles`, adminToken, {
data: { role_ids: [Number(commonRole.id)] },
});
record('无图标权限测试用户分配 common 角色成功', assign.response.status() === 200, { status: assign.response.status(), body: assign.body });
return loginData.access_token;
}
async function main() {
const browser = await chromium.launch({ headless: true });
const { context, token } = await loginFrontendContext(browser);
const api = await request.newContext();
const page = await context.newPage();
const module = await createEntryModule(api, token);
await createDocType(api, token, module.id);
await page.goto(`${FRONTEND}/`, { waitUntil: 'domcontentloaded', timeout: 30000 });
await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {});
await page.getByRole('button', { name: module.name, exact: true }).click({ timeout: 15000 });
await page.waitForURL((url) => url.pathname === '/govdoc/audits' && url.searchParams.get('entryModuleId') === String(module.id), { timeout: 15000 });
await page.waitForLoadState('networkidle', { timeout: 20000 }).catch(() => {});
await page.waitForTimeout(1200);
const side = await sidebarTexts(page);
const headingText = await page.locator('.govdoc-audit-scope h2').first().textContent({ timeout: 10000 });
const storage = await page.evaluate(() => JSON.parse(sessionStorage.getItem('selectedEntryModuleContext') || 'null'));
record('公文入口标题使用当前入口模块名称', headingText === `${module.name}文档列表`, { headingText, expected: `${module.name}文档列表` });
record('公文入口上下文保存为 govdoc', storage?.menuProfile === 'govdoc' && Number(storage?.id) === Number(module.id), storage);
record('govdoc 侧栏显示公文列表/公文上传/规则分组', ['公文列表', '公文上传', '规则分组'].every((text) => side.includes(text)), { side });
record('govdoc 侧栏不显示普通文件上传/文档列表', !side.includes('文件上传') && !side.includes('文档列表'), { side });
const commonToken = await createCommonUserToken(api, token);
const image403 = await apiFetch(api, 'POST', `/api/v3/entry-modules/${module.id}/image`, commonToken, {
multipart: {
file: {
name: 'entry-module.png',
mimeType: 'image/png',
buffer: Buffer.from('89504e470d0a1a0a', 'hex'),
},
},
});
record('无 entry_module:image:write 用户上传入口图标返回 403', image403.response.status() === 403, { status: image403.response.status(), body: image403.body });
await api.dispose();
await context.close();
await browser.close();
console.log('\nSUMMARY ' + JSON.stringify({ runId, pass: results.filter((r) => r.ok).length, fail: results.filter((r) => !r.ok).length, results }, null, 2));
}
main().catch((err) => {
console.error('\nERROR', err);
console.log('\nSUMMARY ' + JSON.stringify({ runId, pass: results.filter((r) => r.ok).length, fail: results.filter((r) => !r.ok).length, results }, null, 2));
process.exit(1);
});