Files
mcn-short-video/project/短视频脚本创作/V1.0/mcn-work-shop/cdp-verify-titlebar.mjs
T

87 lines
4.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* cdp-verify-titlebar.mjs — 验证:toolbar 显示视频标题名称;信息卡首行「视频地址」+可点击链接(09-01) */
const CDP = 'http://127.0.0.1:9223';
async function getWs(targetId) {
const tabs = await (await fetch(CDP + '/json')).json();
const t = tabs.find((x) => x.id === targetId);
if (!t) throw new Error('target not found: ' + targetId);
return t.webSocketDebuggerUrl;
}
function cdp(ws, method, params = {}) {
return new Promise((resolve, reject) => {
const id = ++cdp._id;
const w = new WebSocket(ws);
const timer = setTimeout(() => { try { w.close(); } catch (e) {} reject(new Error('timeout: ' + method)); }, 30000);
w.onopen = () => w.send(JSON.stringify({ id, method, params }));
w.onmessage = (ev) => {
const m = JSON.parse(ev.data);
if (m.id !== id) return;
clearTimeout(timer);
try { w.close(); } catch (e) {}
m.error ? reject(new Error(method + ': ' + JSON.stringify(m.error))) : resolve(m.result);
};
w.onerror = () => { clearTimeout(timer); reject(new Error('ws error: ' + method)); };
});
}
cdp._id = 0;
async function evalJs(ws, expr) {
const r = await cdp(ws, 'Runtime.evaluate', { expression: expr, awaitPromise: true, returnByValue: true });
if (r.exceptionDetails) throw new Error('eval err: ' + JSON.stringify(r.exceptionDetails).slice(0, 300));
return r.result && r.result.value;
}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
const waitFor = async (ws, expr, timeout = 15000, label = '') => {
const t0 = Date.now();
while (Date.now() - t0 < timeout) {
if (await evalJs(ws, expr)) return true;
await sleep(300);
}
throw new Error('waitFor timeout: ' + label);
};
async function main() {
const tabs = await (await fetch(CDP + '/json')).json();
const tab = tabs.find((x) => x.url.includes('localhost:8900')) || tabs.find((x) => x.type === 'page');
if (!tab) throw new Error('no 8900 tab found');
const ws = await getWs(tab.id);
await cdp(ws, 'Page.enable');
await cdp(ws, 'Runtime.enable');
let pass = 0, fail = 0;
const check = (name, cond, extra = '') => { cond ? pass++ : fail++; console.log((cond ? 'PASS' : 'FAIL') + ' | ' + name + (cond ? '' : ' ← ' + extra)); };
await cdp(ws, 'Page.navigate', { url: 'http://localhost:8900/?v=titlebar#/video/680' });
await waitFor(ws, `!!document.querySelector('.video-info')`, 15000, '视频详情渲染');
const r = await evalJs(ws, `(() => {
const card = document.querySelector('.video-info');
const rows = card ? [...card.querySelectorAll('.info-row')] : [];
const toolbarTitle = document.querySelector('.page-toolbar .page-title');
const r0 = rows[0];
const firstLabel = r0 ? r0.querySelector('.info-label').textContent.trim() : '';
const firstLink = r0 ? r0.querySelector('a') : null;
const rowLabels = rows.slice(1).map((row) => [...row.querySelectorAll('.info-label')].map((l) => l.textContent.trim()));
return {
toolbarTitle: toolbarTitle ? toolbarTitle.textContent.trim() : '',
rowCount: rows.length,
firstLabel,
firstHref: firstLink ? (firstLink.getAttribute('data-ext') || firstLink.getAttribute('href')) : null,
firstText: r0 ? r0.textContent.trim().slice(0, 60) : '',
rowLabels,
hasRenderErr: document.body.textContent.includes('渲染失败') || document.body.textContent.includes('not defined')
};
})()`);
check('toolbar 显示视频标题名称(非静态"视频详情"): ' + r.toolbarTitle, !!r.toolbarTitle && r.toolbarTitle !== '视频详情' && r.toolbarTitle.length > 2, r.toolbarTitle);
check('信息卡共 4 组行', r.rowCount === 4);
check('首行标签=「视频地址」: ' + r.firstLabel, r.firstLabel === '视频地址', r.firstLabel);
check('首行含可点击链接(https): ' + (r.firstHref || '').slice(0, 40), !!r.firstHref && /^https?:/.test(r.firstHref), r.firstHref || '');
check('第2行=账号/视频ID/时长/发布时间', JSON.stringify(r.rowLabels[0]) === JSON.stringify(['账号', '视频ID', '时长', '发布时间']), JSON.stringify(r.rowLabels[0]));
check('第3行=点赞/评论/分享/收藏', JSON.stringify(r.rowLabels[1]) === JSON.stringify(['点赞', '评论', '分享', '收藏']), JSON.stringify(r.rowLabels[1]));
check('第4行=标签', JSON.stringify(r.rowLabels[2]) === JSON.stringify(['标签']), JSON.stringify(r.rowLabels[2]));
check('无渲染失败', !r.hasRenderErr);
console.log(`\n结果: ${pass} PASS / ${fail} FAIL`);
process.exit(fail ? 1 : 0);
}
main().catch((e) => { console.error('ERROR:', e.message); process.exit(1); });