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

147 lines
6.9 KiB
JavaScript
Raw Normal View History

// 验证「账号设定」卡片版/文字版切换(账号详情页 persona tab)
// 用例1:旧梦留声机(1629) 有卡片 → 默认卡片版 + 可切换文字版
// 用例2:王微斯(1627) 无卡片 → 直接文字版,无切换控件
const list = await fetch('http://localhost:9223/json').then((r) => r.json());
let page = list.find((t) => t.type === 'page' && t.url.includes('localhost:8899'));
if (!page) { console.log('ERR: no workbuddy page open'); process.exit(1); }
const ws = new WebSocket(page.webSocketDebuggerUrl);
let id = 0; const pending = new Map();
const send = (method, params = {}) => new Promise((res, rej) => { const i = ++id; pending.set(i, { res, rej }); ws.send(JSON.stringify({ id: i, method, params })); });
ws.onmessage = (e) => { const m = JSON.parse(e.data); if (m.id && pending.has(m.id)) { const p = pending.get(m.id); pending.delete(m.id); m.error ? p.rej(new Error(m.error.message)) : p.res(m.result); } };
await new Promise((r) => (ws.onopen = r));
const ev = async (expr) => { const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); if (r.exceptionDetails) return { __err: (r.exceptionDetails.exception?.description || r.exceptionDetails.text).slice(0, 300) }; return r.result.value; };
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
await send('Page.enable'); await send('Runtime.enable');
const shot = async (name) => {
try {
const r = await send('Page.captureScreenshot', { format: 'png' });
const fs = await import('node:fs');
fs.writeFileSync('shot-' + name + '.png', Buffer.from(r.data, 'base64'));
console.log('截图:', name);
} catch (e) { console.log('截图失败(跳过):', e.message); }
};
const goto = async (url) => {
await send('Page.navigate', { url });
await sleep(2500);
await send('Page.reload', { ignoreCache: true }); // hash 路由 navigate 不重载文档,强制刷新加载最新 JS
await sleep(3000);
};
// ---- 用例1:旧梦留声机(有卡片)----
console.log('=== 用例1 旧梦留声机 1629 ===');
await goto('http://localhost:8899/#/account/1629');
// 点击「账号设定」tab
const tabClick = await ev(`(() => {
const b = document.querySelector('[data-tab="persona"]');
if (!b) return { err: 'no persona tab' };
b.click();
return 'clicked persona tab';
})()`);
console.log('切tab:', JSON.stringify(tabClick));
await sleep(1800); // 等 loadPersona 两个 fetch 完成
const s1 = await ev(`(() => {
const sw = document.querySelector('.persona-vs-icons');
const card = document.querySelector('.card-view');
const md = document.querySelector('.persona-text');
const img = card && card.querySelector('img');
const btns = sw ? [...sw.querySelectorAll('.vi-btn')] : [];
const active = btns.find((x) => x.classList.contains('vi-active'));
const cardIcon = btns[0] && btns[0].querySelector('svg path');
return {
hasIcons: !!sw,
btnTitles: btns.map((x) => x.title),
activeTitle: active ? active.title : null,
cardIconIsImage: cardIcon ? cardIcon.getAttribute('d').includes('m21 15-3.086') : null,
cardHidden: card ? card.classList.contains('vs-hidden') : null,
cardImgSrc: img ? img.getAttribute('src').slice(0, 60) : null,
mdHidden: md ? md.classList.contains('vs-hidden') : null,
mdLen: md ? md.textContent.length : 0,
};
})()`);
console.log('默认卡片版状态:', JSON.stringify(s1));
// 切到文字版
await ev(`(() => { const b = document.querySelector('[data-vs="text"]'); if (b) b.click(); return 1; })()`);
await sleep(400);
const s2 = await ev(`(() => {
const sw = document.querySelector('.persona-vs-icons');
const card = document.querySelector('.card-view');
const md = document.querySelector('.persona-text');
const active = sw && [...sw.querySelectorAll('.vi-btn')].find((x) => x.classList.contains('vi-active'));
return {
activeTitle: active ? active.title : null,
activeCount: sw ? [...sw.querySelectorAll('.vi-btn.vi-active')].length : null,
cardHidden: card ? card.classList.contains('vs-hidden') : null,
mdHidden: md ? md.classList.contains('vs-hidden') : null,
};
})()`);
console.log('切文字版后:', JSON.stringify(s2));
// 切回卡片版
await ev(`(() => { const b = document.querySelector('[data-vs="card"]'); if (b) b.click(); return 1; })()`);
await sleep(400);
const s3 = await ev(`(() => {
const card = document.querySelector('.card-view');
const md = document.querySelector('.persona-text');
const active = document.querySelector('.vi-btn.vi-active');
return {
activeTitle: active ? active.title : null,
activeCount: document.querySelectorAll('.vi-btn.vi-active').length,
cardHidden: card ? card.classList.contains('vs-hidden') : null,
mdHidden: md ? md.classList.contains('vs-hidden') : null,
};
})()`);
console.log('切回卡片版后:', JSON.stringify(s3));
// ---- 用例2:王微斯(无卡片)----
console.log('=== 用例2 王微斯 1627(无卡片)===');
await goto('http://localhost:8899/#/account/1627');
await ev(`(() => { const b = document.querySelector('[data-tab="persona"]'); if (b) b.click(); return 1; })()`);
await sleep(1800);
const s4 = await ev(`(() => {
const sw = document.querySelector('.persona-vs-icons');
const md = document.querySelector('.persona-text');
return {
hasIcons: !!sw,
mdExists: !!md,
mdHidden: md ? md.classList.contains('vs-hidden') : null,
mdLen: md ? md.textContent.length : 0,
};
})()`);
console.log('无卡片账号状态:', JSON.stringify(s4));
// 回到用例1 页面截图卡片版效果(最后统一截图,失败不中断)
await goto('http://localhost:8899/#/account/1629');
await ev(`(() => { const b = document.querySelector('[data-tab="persona"]'); if (b) b.click(); return 1; })()`);
await sleep(1800);
// 多视口宽度自检:验证图片是否随内容区自适应(不应超出 viewport 引发横向滚动)
for (const vw of [1280, 1024, 900, 1920, 2560]) {
await send('Emulation.setDeviceMetricsOverride', { width: vw, height: 800, deviceScaleFactor: 1, mobile: false });
await sleep(500);
const info = await ev(`(() => {
const img = document.querySelector('.card-view img');
const body = document.querySelector('.detail-body');
const wrap = document.querySelector('.persona-wrap');
const page = document.querySelector('.page-detail');
return {
viewport: ${vw},
docScrollW: document.documentElement.scrollWidth,
bodyW: body ? Math.round(body.getBoundingClientRect().width) : null,
wrapW: wrap ? Math.round(wrap.getBoundingClientRect().width) : null,
imgW: img ? Math.round(img.getBoundingClientRect().width) : null,
pageW: page ? Math.round(page.getBoundingClientRect().width) : null,
bodyOverflow: body ? getComputedStyle(body).overflowX : null,
};
})()`);
console.log('视口', vw, ':', JSON.stringify(info));
}
await send('Emulation.clearDeviceMetricsOverride');
await sleep(300);
await shot('persona-card-final');
console.log('DONE');
ws.close();
process.exit(0);