const { chromium } = require('playwright'); const htmlPath = 'C:\\Users\\然然小可爱\\Desktop\\数学乐园\\index.html'; (async () => { const browser = await chromium.launch({ headless: true }); const page = await browser.newPage({ viewport: { width: 800, height: 900 } }); const errors = []; page.on('pageerror', e => errors.push(e.message)); let p = 0, f = 0; function chk(name, cond, note) { if (cond) { p++; console.log(' ✅', name); } else { f++; console.log(' ❌', name, note||''); } } await page.goto('file:///' + htmlPath.replace(/\\/g, '/')); await page.waitForTimeout(1000); // ===== 1. 主页 ===== console.log('【1. 主页】'); chk('标题', await page.title() === 'MV1 赛道数学'); chk('CP数', (await page.$$('.cp')).length === 4); chk('HUD', await page.$eval('#hStage', e => e.textContent) === '1/4'); // ===== 2. 进入Ch1推进 ===== console.log('\n【2. 学习推进】'); const cp = await page.$('.cp[data-idx="0"]'); const b = await cp.boundingBox(); await page.mouse.click(b.x + b.width/2, b.y + b.height/2); await page.waitForTimeout(500); // 推进函数 async function adv() { const act = await page.$('.act.show'); if (act) { await act.click(); await page.waitForTimeout(350); return true; } return false; } await adv(); chk('KP1正负数', (await page.$eval('#cGl', e => e.textContent)).includes('正数')); await adv(); chk('KP2数轴', (await page.$eval('#cGl', e => e.textContent)).includes('数轴')); await adv(); chk('KP3相反数', (await page.$eval('#cGl', e => e.textContent)).includes('相反')); // EG分步 for (let i = 0; i < 5; i++) { const eb = await page.$('#egBtn'); if (!eb) break; await eb.click(); await page.waitForTimeout(100); } await adv(); chk('KP4运算', (await page.$eval('#cGl', e => e.textContent)).includes('运算')); await adv(); chk('KP5乘方', (await page.$eval('#cGl', e => e.textContent)).includes('乘方')); await adv(); chk('分站赛入口', await page.$('#stgStart') !== null); // ===== 3. 答题 ===== console.log('\n【3. 答题】'); await page.click('#stgStart'); await page.waitForTimeout(300); chk('题目显示', await page.$('.qt') !== null); chk('4选项', (await page.$$('.opt')).length === 4); // 答对 const c1 = await page.evaluate(() => SS[0].segs[8].correct); await (await page.$$('.opt'))[c1].click(); await page.waitForTimeout(300); chk('答对反馈', await page.$('.qfb.pass') !== null); await page.click('.act.show'); await page.waitForTimeout(200); // 答错 const c2 = await page.evaluate(() => SS[0].segs[9].correct); await (await page.$$('.opt'))[c2 === 0 ? 1 : 0].click(); await page.waitForTimeout(300); chk('答错反馈', await page.$('.qfb.fail') !== null); chk('错题角标', await page.$eval('#hintBadge', e => parseInt(e.textContent) > 0)); // ===== 4. 答题地图 ===== console.log('\n【4. 答题地图】'); await page.click('.act.show'); await page.waitForTimeout(200); const mk = await page.$('#bkMapBtn'); if (mk && (await mk.isVisible())) { await mk.click(); await page.waitForTimeout(300); chk('地图显示', await page.$('#mGrid') !== null); const cells = await page.$$('.qCell'); chk('题目格', cells.length > 0, cells.length + '个'); chk('正确标记', await page.$('.qCell.correct') !== null); chk('错误标记', await page.$('.qCell.wrong') !== null); if (cells.length > 0) { await cells[3].click(); await page.waitForTimeout(300); chk('跳转', await page.$('.qt') !== null); } } // ===== 5. 错题集 ===== console.log('\n【5. 错题集】'); // 先回章节页再回主页 const bm = await page.$('#bkChapM'); if (bm && (await bm.isVisible())) { await bm.click(); await page.waitForTimeout(200); } await page.click('#bkMap'); await page.waitForTimeout(200); chk('回到主页', (await page.evaluate(() => document.querySelector('.pg.act')?.id)) === 'pH'); await page.click('#wrongBtn'); await page.waitForTimeout(300); chk('错题集显示', (await page.evaluate(() => document.querySelector('.pg.act')?.id)) === 'pW'); chk('重做按钮', await page.$('.wrDo') !== null); chk('移除按钮', await page.$('.wrRm') !== null); // ===== 6. 内容完整性 ===== console.log('\n【6. 内容覆盖】'); const txt = await page.evaluate(() => document.body.innerText); const items = [ ['有理数','有理数'],['正负数','正数'],['数轴','数轴'],['相反数','相反数'], ['绝对值','绝对值'],['倒数','倒数'],['乘方','乘方'],['科学记数法','科学记数法'], ['单项式','单项式'],['多项式','多项式'],['同类项','同类项'],['去括号','去括号'], ['降幂','降幂'],['升幂','升幂'],['等式性质','等式性质'],['去分母','去分母'], ['配套','螺栓'],['相遇','相向'],['追及','追及'],['比赛积分','积分'], ['利率','利率'],['展开图','一四一'],['中点模型','中点'],['角平分线','平分'], ['分类讨论','分类讨论'],['有效数字','有效数字'],['方程','方程'], ]; items.forEach(i => chk(i[0], txt.includes(i[1]))); console.log(`\n通过: ${p}/${p+f} JS错误: ${errors.length}`); errors.forEach(e => console.log(' Error:', e)); await browser.close(); })().catch(e => { console.log('异常:', e.message); process.exit(1); });