Production readiness hardening and ops tooling
This commit is contained in:
60
scripts/ui-qa-check.mjs
Normal file
60
scripts/ui-qa-check.mjs
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env node
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const pages = [
|
||||
"ui/admin-reconciliation-management/index.html",
|
||||
"ui/admin-system-audit-logs/index.html",
|
||||
"ui/settlement-batch-management/index.html",
|
||||
"ui/merchant-settlement-history/index.html",
|
||||
"ui/device-technical-detail/index.html"
|
||||
];
|
||||
|
||||
const checks = [];
|
||||
const warnings = [];
|
||||
const errors = [];
|
||||
const scriptRe = new RegExp("<script(?:\\s[^>]*)?>([\\s\\S]*?)</script>", "gi");
|
||||
|
||||
function check(condition, message) {
|
||||
checks.push({ ok: Boolean(condition), message });
|
||||
if (!condition) {
|
||||
errors.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
function warn(condition, message) {
|
||||
if (!condition) {
|
||||
warnings.push(message);
|
||||
}
|
||||
}
|
||||
|
||||
for (const page of pages) {
|
||||
const filePath = path.resolve(process.cwd(), page);
|
||||
const html = fs.readFileSync(filePath, "utf8");
|
||||
const scripts = [...html.matchAll(scriptRe)].map((match) => match[1].trim()).filter(Boolean);
|
||||
for (const [index, script] of scripts.entries()) {
|
||||
try {
|
||||
new Function(script);
|
||||
check(true, `${page} script ${index + 1} parses`);
|
||||
} catch (error) {
|
||||
check(false, `${page} script ${index + 1} parse failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
warn(!/href="#"/.test(html), `${page} still has placeholder # links for manual navigation QA`);
|
||||
}
|
||||
|
||||
const reconciliation = fs.readFileSync("ui/admin-reconciliation-management/index.html", "utf8");
|
||||
check(reconciliation.includes("adjustment-export-history"), "reconciliation export history is present");
|
||||
check(!reconciliation.includes("/admin/settlement-adjustments/export.csv?"), "reconciliation uses async export instead of sync CSV URL");
|
||||
|
||||
const settlement = fs.readFileSync("ui/settlement-batch-management/index.html", "utf8");
|
||||
check(settlement.includes('data-admin-permission="settlement:export"'), "settlement export button is permission-aware");
|
||||
check(settlement.includes('data-admin-permission="settlement:pay"'), "settlement pay action is permission-aware");
|
||||
|
||||
const auditLogs = fs.readFileSync("ui/admin-system-audit-logs/index.html", "utf8");
|
||||
check(auditLogs.includes("audit-action-filter"), "audit logs page has action filter");
|
||||
check(auditLogs.includes("admin.login.failed"), "audit logs page supports admin login failed filter");
|
||||
check(auditLogs.includes("merchant.login.failed"), "audit logs page supports merchant login failed filter");
|
||||
|
||||
console.log(JSON.stringify({ ok: errors.length === 0, checks, warnings, errors }, null, 2));
|
||||
process.exit(errors.length ? 1 : 0);
|
||||
Reference in New Issue
Block a user