You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

123 lines
5.3 KiB

const { chromium } = require('playwright');
const baseUrl = process.env.YOUTHOME_WEB_URL || 'http://127.0.0.1:4173/pages';
async function inspectOverflow(page) {
return page.evaluate(() => ({
innerWidth: window.innerWidth,
scrollWidth: document.documentElement.scrollWidth,
bodyScrollWidth: document.body.scrollWidth,
overflow: Math.max(document.documentElement.scrollWidth, document.body.scrollWidth) - window.innerWidth
}));
}
(async () => {
const browser = await chromium.launch({ channel: 'msedge', headless: true });
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.addInitScript(() => localStorage.setItem('youthome:web:dataSource', 'local'));
const browserErrors = [];
page.on('console', (message) => {
if (message.type() === 'error' && !message.text().includes('404 (File not found)')) {
browserErrors.push(`console [${page.url()}]: ${message.text()}`);
}
});
page.on('pageerror', (error) => browserErrors.push(`page [${page.url()}]: ${error.message}`));
page.on('response', (response) => {
if (response.status() >= 400) browserErrors.push(`http ${response.status()}: ${response.url()}`);
});
await page.goto(`${baseUrl}/settings.html`, { waitUntil: 'domcontentloaded' });
await page.locator('[data-settings-section="privacy"]').click();
const settings = {
url: page.url(),
title: await page.locator('.settings-page-heading .page-title').textContent(),
visiblePanels: await page.locator('[data-settings-panel]:visible').count(),
visiblePanel: await page.locator('[data-settings-panel]:visible').getAttribute('data-settings-panel')
};
console.log('settings', JSON.stringify(settings));
await page.goto(`${baseUrl}/feed.html`, { waitUntil: 'domcontentloaded' });
const extrasBefore = await page.locator('.topic-item-extra:visible').count();
await page.locator('.topic-more-button').click();
const extrasAfter = await page.locator('.topic-item-extra:visible').count();
const moreText = (await page.locator('.topic-more-button').innerText()).trim();
const recommendationsBefore = await page.locator('.user-item-name').allTextContents();
await page.locator('.recommendation-refresh').click();
const recommendationsAfter = await page.locator('.user-item-name').allTextContents();
const firstName = recommendationsAfter[0];
await page.locator('.user-item .follow-btn').first().click();
const followText = (await page.locator('.user-item .follow-btn').first().innerText()).trim();
const storedFollow = await page.evaluate(
(name) => localStorage.getItem(`youthome:web:follow:${name}`),
firstName
);
const feed = {
extrasBefore,
extrasAfter,
moreText,
recommendationsChanged: recommendationsBefore.join('|') !== recommendationsAfter.join('|'),
firstName,
followText,
storedFollow
};
console.log('feed', JSON.stringify(feed));
await page.goto(`${baseUrl}/me.html`, { waitUntil: 'domcontentloaded' });
await page.locator('[data-profile-action="more"]').click();
const profile = {
expanded: await page.locator('[data-profile-action="more"]').getAttribute('aria-expanded'),
visibleMenu: await page.locator('.profile-more-menu:visible').count(),
visibleActions: await page.locator('.profile-more-menu button:visible').count()
};
console.log('profile', JSON.stringify(profile));
const mobile = await browser.newPage({ viewport: { width: 390, height: 844 } });
await mobile.addInitScript(() => localStorage.setItem('youthome:web:dataSource', 'local'));
const mobileLayout = {};
for (const name of ['settings', 'me', 'feed']) {
await mobile.goto(`${baseUrl}/${name}.html`, { waitUntil: 'domcontentloaded' });
await mobile.locator('body.web-shell-ready').waitFor();
mobileLayout[name] = await inspectOverflow(mobile);
if (name === 'me') {
mobileLayout[name].moreButton = await mobile.locator('[data-profile-action="more"]').evaluate((element) => {
const rect = element.getBoundingClientRect();
const centerElement = document.elementFromPoint(rect.left + rect.width / 2, rect.top + rect.height / 2);
return {
left: Math.round(rect.left),
top: Math.round(rect.top),
width: Math.round(rect.width),
height: Math.round(rect.height),
clickable: element === centerElement || element.contains(centerElement)
};
});
}
await mobile.screenshot({
path: `C:/Users/lenovo/AppData/Local/Temp/youthome-qa-20260923/${name}-mobile-final.png`,
fullPage: true
});
}
console.log('mobile', JSON.stringify(mobileLayout));
console.log('browserErrors', JSON.stringify(browserErrors));
const failed =
settings.visiblePanel !== 'privacy' ||
settings.visiblePanels !== 1 ||
!settings.url.includes('section=privacy') ||
feed.extrasBefore !== 0 ||
feed.extrasAfter !== 4 ||
!feed.recommendationsChanged ||
feed.followText !== '已关注' ||
feed.storedFollow !== 'true' ||
profile.expanded !== 'true' ||
profile.visibleMenu !== 1 ||
profile.visibleActions !== 2 ||
!mobileLayout.me.moreButton.clickable ||
Object.values(mobileLayout).some((result) => result.overflow > 0) ||
browserErrors.length > 0;
await browser.close();
process.exitCode = failed ? 1 : 0;
})().catch((error) => {
console.error(error);
process.exitCode = 1;
});