70 lines
6.0 KiB
JavaScript
70 lines
6.0 KiB
JavaScript
/*
|
|
* Captures the current native MuMu rendering of every app route. It uses the
|
|
* installed app's WebView and ADB; no browser emulation, fixture, or mock data.
|
|
*
|
|
* Usage:
|
|
* $env:ADB_PATH='...\\adb.exe'; node tests/mumu-page-visual-audit.js
|
|
*/
|
|
const { execFileSync } = require("node:child_process");
|
|
const { mkdirSync } = require("node:fs");
|
|
const { join } = require("node:path");
|
|
|
|
const adb = process.env.ADB_PATH || "adb";
|
|
const device = process.env.MUMU_DEVICE || "emulator-5554";
|
|
const outputDir = process.env.MUMU_AUDIT_DIR || join(process.cwd(), "tmp", "mumu-visual-audit");
|
|
const genealogyId = process.env.MUMU_GENEALOGY_ID || "2081191846772518914";
|
|
const start = Number(process.env.MUMU_AUDIT_START || 0);
|
|
const end = Number(process.env.MUMU_AUDIT_END || 52);
|
|
const routes = [
|
|
["a01", "/pages/auth/a01-entry"], ["a04", "/pages/auth/a04-register"], ["a05", "/pages/auth/a05-reset-password"],
|
|
["g01", "/pages/genealogy/g01-my-genealogies"], ["g03", "/pages/genealogy/g03-create-genealogy"], ["g05", `/pages/genealogy/g05-genealogy-overview?genealogyId=${genealogyId}`], ["g06", "/pages/genealogy/g06-search-genealogies"], ["g08", `/pages/genealogy/g08-join-application?genealogyId=${genealogyId}`], ["g09", "/pages/genealogy/g09-my-applications"], ["g10", `/pages/genealogy/g10-application-review?genealogyId=${genealogyId}`], ["g11", `/pages/genealogy/g11-genealogy-settings?genealogyId=${genealogyId}`], ["g12", `/pages/genealogy/g12-generation-poems?genealogyId=${genealogyId}`],
|
|
["t01", `/pages/tree/t01-tree-overview?genealogyId=${genealogyId}`], ["t03", `/pages/tree/t03-member-profile?genealogyId=${genealogyId}`], ["t04", `/pages/tree/t04-add-relative?genealogyId=${genealogyId}`], ["t05", `/pages/tree/t05-edit-member?genealogyId=${genealogyId}`], ["t06", `/pages/tree/t06-edit-relationship?genealogyId=${genealogyId}`], ["t07", `/pages/tree/t07-member-directory?genealogyId=${genealogyId}`], ["t08", `/pages/tree/t08-member-states?genealogyId=${genealogyId}`],
|
|
["f01", `/pages/family/f01-family-feed?genealogyId=${genealogyId}`], ["f02", `/pages/family/f02-publish-feed?genealogyId=${genealogyId}`], ["f03", `/pages/family/f03-feed-detail?genealogyId=${genealogyId}&feedId=2081197770778128385`], ["f04", `/pages/family/f04-article-list?genealogyId=${genealogyId}`], ["f05", `/pages/family/f05-article-detail?genealogyId=${genealogyId}&articleId=2081200381052891138`], ["f06", `/pages/family/f06-article-editor?genealogyId=${genealogyId}`], ["f07", `/pages/family/f07-album-list?genealogyId=${genealogyId}`], ["f08", `/pages/family/f08-album-detail?genealogyId=${genealogyId}&albumId=2081202236751392769`], ["f09", `/pages/family/f09-media-upload?genealogyId=${genealogyId}&albumId=2081202236751392769`], ["f10", `/pages/family/f10-video-list?genealogyId=${genealogyId}`],
|
|
["r01", `/pages/records/r01-people-list?genealogyId=${genealogyId}`], ["r02", `/pages/records/r02-person-detail?genealogyId=${genealogyId}`], ["r03", `/pages/records/r03-gift-list?genealogyId=${genealogyId}`], ["r04", `/pages/records/r04-gift-editor?genealogyId=${genealogyId}`], ["r05", `/pages/records/r05-ritual-list?genealogyId=${genealogyId}`], ["r06", `/pages/records/r06-ritual-detail?genealogyId=${genealogyId}`], ["r07", `/pages/records/r07-ritual-editor?genealogyId=${genealogyId}`], ["r08", `/pages/records/r08-growth-journal?genealogyId=${genealogyId}`], ["r09", `/pages/records/r09-life-events?genealogyId=${genealogyId}`], ["r10", `/pages/records/r10-memo-list?genealogyId=${genealogyId}`], ["r11", `/pages/records/r11-merit-records?genealogyId=${genealogyId}`],
|
|
["n01", "/pages/notification/n01-message-center"], ["n02", "/pages/notification/n02-message-detail"],
|
|
["m01", "/pages/profile/m01-profile-home"], ["m02", "/pages/profile/m02-edit-profile"], ["m03", "/pages/profile/m03-security-settings"], ["m04", "/pages/profile/m04-change-password"], ["m05", "/pages/profile/m05-change-phone"], ["m06", "/pages/profile/m06-help-center"], ["m07", "/pages/profile/m07-feedback"], ["m08", "/pages/profile/m08-promotion"], ["m09", "/pages/profile/m09-vip-orders"], ["m10", "/pages/profile/m10-about-settings"],
|
|
];
|
|
|
|
const run = (...args) => execFileSync(adb, ["-s", device, ...args], { encoding: "utf8", stdio: ["ignore", "pipe", "pipe"] });
|
|
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
|
|
async function currentTarget() {
|
|
const targets = await (await fetch("http://127.0.0.1:9223/json/list")).json();
|
|
const pages = targets.filter((item) => item.type === "page" && item.title !== "View");
|
|
if (!pages.length) throw new Error("MuMu 中没有可操作的应用页面 WebView");
|
|
return pages.at(-1);
|
|
}
|
|
|
|
async function evaluate(expression) {
|
|
const target = await currentTarget();
|
|
return new Promise((resolve, reject) => {
|
|
const socket = new WebSocket(target.webSocketDebuggerUrl);
|
|
socket.onopen = () => socket.send(JSON.stringify({ id: 1, method: "Runtime.evaluate", params: { expression, awaitPromise: true, returnByValue: true } }));
|
|
socket.onmessage = (event) => {
|
|
const result = JSON.parse(event.data);
|
|
socket.close();
|
|
if (result.error || result.result?.exceptionDetails) reject(new Error(JSON.stringify(result.error || result.result.exceptionDetails)));
|
|
else resolve(result.result?.result?.value);
|
|
};
|
|
socket.onerror = () => reject(new Error("无法连接 MuMu WebView 调试端口"));
|
|
});
|
|
}
|
|
|
|
async function main() {
|
|
mkdirSync(outputDir, { recursive: true });
|
|
run("forward", "tcp:9223", "localabstract:webview_devtools_remote_2728");
|
|
try {
|
|
for (const [name, route] of routes.slice(start, end)) {
|
|
await evaluate(`uni.reLaunch({ url: ${JSON.stringify(route)} }); true`);
|
|
await delay(1800);
|
|
run("shell", "screencap", "-p", "/sdcard/jiapu-visual-audit.png");
|
|
run("pull", "/sdcard/jiapu-visual-audit.png", join(outputDir, `${name}.png`));
|
|
process.stdout.write(`captured ${name}\n`);
|
|
}
|
|
} finally {
|
|
try { run("forward", "--remove", "tcp:9223"); } catch {}
|
|
}
|
|
}
|
|
|
|
main().catch((error) => { console.error(error.stack || error.message); process.exitCode = 1; });
|