const assert = require('node:assert/strict'); const { chromium } = require('playwright'); const base = process.env.YOUTHOME_WEB_URL || 'http://127.0.0.1:4173/pages'; const png = Buffer.from('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIHWP4z8DwHwAFgAI/ScL/nwAAAABJRU5ErkJggg==', 'base64'); (async () => { const browser = await chromium.launch({ channel: 'msedge', headless: true }); const page = await browser.newPage({ viewport: { width: 1280, height: 900 } }); const errors = []; const calls = []; const comments = []; page.on('pageerror', (error) => errors.push(error.message)); await page.addInitScript(() => { localStorage.setItem('youthome:web:dataSource', 'api'); sessionStorage.setItem('youthome:web:accessToken', 'mock-token'); sessionStorage.setItem('youthome:web:authUser', JSON.stringify({ id: 'u1', nickname: '演示用户' })); }); await page.route('**/api/**', async (route) => { const request = route.request(); const path = new URL(request.url()).pathname; const body = request.headers()['content-type']?.includes('application/json') ? request.postDataJSON() : null; calls.push({ path, method: request.method(), body }); let data = null; if (path === '/api/campus/moments/detail') data = { id: 'video-1', content: '后端视频标题\n后端视频简介', userId: 'u1', userName: '演示用户', allowComment: true, playUrl: '', commentCount: comments.length }; if (path === '/api/campus/moments/comments' && request.method() === 'GET') data = { items: comments, total: comments.length }; if (path === '/api/campus/moments/comments' && request.method() === 'POST') { const comment = { id: `c${comments.length + 1}`, userId: 'u1', userName: '演示用户', content: body.content, createdAt: '2026-10-22 12:00:00', replies: [] }; comments.push(comment); data = comment; } if (path === '/api/file/upload/image') data = { url: 'https://example.com/cover.png' }; if (path === '/api/campus/activities' && request.method() === 'POST') data = { id: 'activity-1' }; if (path === '/api/campus/activities/detail') data = { id: 'activity-1', title: '后端演示活动', description: '接口活动介绍', coverImage: 'https://example.com/cover.png', location: '演示体育馆', startTime: '2026-10-25 18:00:00', endTime: '2026-10-25 19:00:00', registrationDeadline: '2026-10-24 18:00:00' }; await route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify({ code: 200, data }) }); }); await page.route('https://nominatim.openstreetmap.org/search?**', (route) => route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify([{ lat: '31.299', lon: '121.504', name: '演示体育馆', display_name: '演示体育馆, 上海市杨浦区' }]) })); try { await page.goto(`${base}/video-detail.html?id=video-1`); await page.waitForFunction(() => document.querySelector('.video-title')?.textContent === '后端视频标题'); assert.ok((await page.locator('.video-desc').innerText()).includes('后端视频简介')); await page.locator('.comment-textarea').fill('接口视频评论'); await page.locator('.comment-submit-btn').click(); await page.locator('.comment-list .comment-item').filter({ hasText: '接口视频评论' }).waitFor(); assert.deepEqual(calls.find((call) => call.path === '/api/campus/moments/comments' && call.method === 'POST').body, { momentId: 'video-1', content: '接口视频评论', parentId: null }); await page.goto(`${base}/activity-create.html`); await page.locator('.location-locate-btn').click(); await page.locator('.web-map-dialog input[type="search"]').fill('演示体育馆'); await page.locator('.web-map-dialog').getByRole('button', { name: '搜索' }).click(); await page.locator('.web-map-dialog .primary:enabled').waitFor(); await page.locator('.web-map-dialog .primary').click(); assert.equal(await page.locator('#location-name').inputValue(), '演示体育馆'); await page.locator('#activity-title').fill('后端演示活动'); await page.locator('#activity-desc').fill('接口活动介绍'); await page.locator('#activity-type').selectOption('sports'); await page.locator('.web-activity-cover-input').setInputFiles({ name: 'cover.png', mimeType: 'image/png', buffer: png }); await page.evaluate(() => { const date = new Date(Date.now() + 3 * 86400000); const pad = (value) => String(value).padStart(2, '0'); const day = `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`; document.getElementById('start-time').value = `${day}T18:00`; document.getElementById('end-time').value = `${day}T19:00`; document.getElementById('registration-deadline').value = `${day}T17:00`; }); await page.locator('.btn-next').click(); await page.waitForURL('**/activity-detail.html?id=activity-1'); const activity = calls.find((call) => call.path === '/api/campus/activities' && call.method === 'POST'); assert.equal(activity.body.location, '演示体育馆 上海市杨浦区'); assert.equal(activity.body.coverImage, 'https://example.com/cover.png'); assert.equal(activity.body.latitude, 31.299); assert.equal(activity.body.longitude, 121.504); assert.ok(activity.body.startTime.endsWith(':00')); assert.deepEqual(errors, []); console.log('mock API video comments, description, map selection, activity publish passed'); } finally { await browser.close(); } })().catch((error) => { console.error(error); process.exitCode = 1; });