const assert = require('node:assert/strict'); const { chromium } = require('playwright'); const phone = process.env.YOUTHOME_TEST_PHONE; const captcha = process.env.YOUTHOME_TEST_CAPTCHA; if (!phone || !captcha) { console.error('Set YOUTHOME_TEST_PHONE and YOUTHOME_TEST_CAPTCHA to run this live account smoke test.'); process.exit(1); } (async () => { const browser = await chromium.launch({ channel: 'msedge', headless: true }); const page = await browser.newPage({ viewport: { width: 1440, height: 900 }, locale: 'zh-CN' }); const errors = []; page.on('pageerror', (error) => errors.push(error.message)); const base = 'http://127.0.0.1:4173/pages'; try { await page.goto(`${base}/login.html?demo=0`); await page.evaluate(() => { window.YouthomeApi.clearSession(); localStorage.setItem('youthome:web:dataSource', 'api'); }); await page.locator('[data-tab="code"]').click(); await page.locator('#panel-code input[type="tel"]').fill(phone); await page.locator('#panel-code input[placeholder*="验证码"]').fill(captcha); await page.locator('#panel-code .btn-primary').click(); await page.waitForURL('**/feed.html', { timeout: 30000 }); await page.locator('.feed-list .web-live-card').first().waitFor({ timeout: 30000 }); assert.equal((await page.locator('.web-user-name').innerText()).trim(), phone); assert.equal(await page.locator('.feed-list .feed-card:not([data-moment-id])').count(), 0); assert.equal(await page.locator('.topic-list .topic-item').count() > 0, true); await page.waitForFunction(() => document.querySelector('.user-list .user-item, .user-list .web-live-empty'), null, { timeout: 30000 }); assert.equal(await page.locator('.user-list .user-item').count() > 0, true, await page.locator('.user-list').innerText()); const recommended = await page.evaluate(async () => (await window.YouthomeApi.get('/friendships/recommend?limit=1')).list[0]); await page.locator('.feed-tab', { hasText: '热门' }).click(); await page.locator('.feed-list .web-live-card').first().waitFor({ timeout: 30000 }); assert.equal(await page.locator('.feed-list .feed-card:not([data-moment-id])').count(), 0); const historyResponse = page.waitForResponse((response) => response.url().includes('/api/campus/chat/history/group/') && response.request().method() === 'GET', { timeout: 30000 }); await page.goto(`${base}/chat.html`); await page.locator('.conv-list .conv-item').first().waitFor({ timeout: 30000 }); const history = (await (await historyResponse).json()).data?.items || []; await page.waitForFunction((count) => document.querySelectorAll('.chat-messages .msg-row').length === count, history.length, { timeout: 30000 }); assert.equal(await page.locator('.conv-list .conv-item').count() > 0, true); assert.equal(await page.locator('.conv-name', { hasText: '林小夏' }).count(), 0); assert.equal(await page.locator('.info-panel').count(), 0); assert.equal(await page.locator('.conv-section').count(), 0); assert.equal(await page.locator('.chat-messages .msg-row').count(), history.length); const liveConversations = await page.evaluate(() => window.YouthomeApi.get('/campus/chat/conversations')); assert.equal((await page.locator('.chat-header-info .name').innerText()).trim(), liveConversations[0].groupName || liveConversations[0].peerName); let sent; await page.route('**/api/campus/chat/messages/group/**', async (route) => { sent = { url: route.request().url(), body: route.request().postDataJSON() }; await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ code: 200, data: { id: 'mock-message' } }) }); }); await page.locator('.chat-textarea').fill('网页端发送回归验证'); await page.locator('.send-btn').click(); await page.waitForFunction(() => document.querySelector('.chat-textarea')?.value === '', null, { timeout: 30000 }); assert.ok(sent.url.endsWith('/api/campus/chat/messages/group/' + liveConversations[0].peerId)); assert.deepEqual(sent.body, { content: '网页端发送回归验证' }); await page.unroute('**/api/campus/chat/messages/group/**'); for (const [path, apiPath, container, sample] of [ ['video.html', '/api/campus/moments/youth', '.video-grid', '宿舍改造vlog | 花500块'], ['activities.html', '/api/campus/activities/search', '.activity-list', '校园十佳歌手大赛 · 冬季总决赛'], ['notification.html', '/api/campus/notifications?page=', '.message-list', '你的活动报名已通过审核'] ]) { const response = page.waitForResponse((item) => item.url().includes(apiPath), { timeout: 30000 }); await page.goto(`${base}/${path}`); await response; assert.equal((await page.locator(container).innerText()).includes(sample), false, `${path} retained sample content`); } await page.goto(`${base}/me.html`); await page.locator('.profile-name').waitFor(); await page.waitForFunction((expected) => document.querySelector('.profile-name')?.textContent.trim() === expected, phone, { timeout: 30000 }); assert.equal(await page.locator('.content-grid .post-card:not(.web-live-card)').count(), 0); const userVideos = page.waitForResponse((item) => item.url().includes('/api/campus/moments/youth?userId='), { timeout: 30000 }); await page.goto(`${base}/user.html?id=${encodeURIComponent(recommended.id)}`); await userVideos; await page.waitForFunction((name) => document.querySelector('.profile-name')?.textContent.trim() === name, recommended.nickname, { timeout: 30000 }); assert.equal((await page.locator('.post-list').innerText()).includes('林小夏'), false); assert.equal(await page.locator('.profile-stats .stat-num').first().innerText() === '356', false); await page.locator('.profile-tab', { hasText: '视频' }).click(); assert.equal((await page.locator('.video-grid-3').innerText()).includes('校园十佳歌手大赛现场精彩回顾'), false); await page.locator('.btn-message').click(); await page.waitForURL('**/chat.html?peer=*'); await page.waitForFunction((name) => document.querySelector('.chat-header-info .name')?.textContent.trim() === name, recommended.nickname, { timeout: 30000 }); assert.deepEqual(errors, []); console.log('Live account feed, video, activities, notifications, chat and profiles smoke checks passed.'); } finally { await browser.close(); } })().catch((error) => { console.error(error); process.exitCode = 1; });