import { readFile } from 'node:fs/promises' import assert from 'node:assert/strict' import { build } from 'esbuild' const config = JSON.parse(await readFile('public/announcement.json', 'utf8')) const locales = ['zh-CN', 'zh-TW', 'en', 'ja', 'ko', 'ru', 'fr', 'de', 'pt-BR', 'es'] if (typeof config.enabled !== 'boolean') throw new Error('announcement.enabled must be boolean') if (!Number.isFinite(config.scrollDurationSeconds) || config.scrollDurationSeconds < 8 || config.scrollDurationSeconds > 120) { throw new Error('announcement.scrollDurationSeconds must be between 8 and 120') } if (!config.messages || typeof config.messages !== 'object' || Array.isArray(config.messages)) { throw new Error('announcement.messages must be an object') } for (const locale of locales) { const text = config.messages[locale] if (typeof text !== 'string' || !text.trim()) throw new Error(`announcement.messages.${locale} is empty`) if (/[\r\n]/.test(text)) throw new Error(`announcement.messages.${locale} must be a single line`) } const bundled = await build({ bundle: true, entryPoints: ['src/editor/announcement.ts'], format: 'esm', platform: 'node', write: false, }) const announcement = await import( `data:text/javascript;base64,${Buffer.from(bundled.outputFiles[0].contents).toString('base64')}` ) assert.equal(announcement.ANNOUNCEMENT_REFRESH_MS, 30_000, '公告内容应每 30 秒刷新') const normalized = announcement.normalizeAnnouncementConfig(config) assert.ok(normalized, '公告配置应通过规范化') const now = 1_000_000 const first = announcement.prepareAnnouncement(normalized, null, now) assert.equal(first.shouldShow, true, '没有缓存时应在首次打开显示') assert.equal(first.cache.lastShownAt, now) const unchanged = announcement.prepareAnnouncement(normalized, first.cache, now + 60_000) assert.equal(unchanged.shouldShow, false, '72 小时内内容未变化时不应重复显示') const changedConfig = { ...normalized, messages: { ...normalized.messages, en: `${normalized.messages.en} Updated` }, } const changed = announcement.prepareAnnouncement(changedConfig, unchanged.cache, now + 120_000) assert.equal(changed.shouldShow, true, '公告内容变化时应立即显示') assert.equal(changed.cache.lastShownAt, now + 120_000) const expired = announcement.prepareAnnouncement(normalized, changed.cache, now + announcement.ANNOUNCEMENT_WINDOW_MS + 120_000) assert.equal(expired.shouldShow, true, '超过 72 小时后首次打开应再次显示') const disabled = announcement.prepareAnnouncement({ ...normalized, enabled: false }, expired.cache, now + 200_000) assert.equal(disabled.shouldShow, false, '公告关闭时不应显示') console.log(`公告栏校验通过:${locales.length} 种语言、三次滚动、72 小时展示窗口、内容变更和 30 秒刷新逻辑`)