import { describe, expect, it } from 'vitest' import zhMessages from '@/locales/langs/zh.json' import enMessages from '@/locales/langs/en.json' import { bindChangeKind, buildEmbedSnippet, buildSettingsPayload, buildSlotEditPayload, clampIntervalMs, DEFAULT_EMBED_SETTINGS, EMBED_ORIGIN_FALLBACK, embedOriginFromEnv, type EmbedSettingsDraft } from './embedSlots' /** 契约形状的既有条目(编辑载荷断言基准) */ const CURRENT_ITEM: Api.EmbedSlot.Item = { id: 'slot-1', publicToken: 'tok0000000000000000000', name: '官网首页悬浮位', enabled: true, albumId: null, albumTitle: null, configVersion: 1, settings: { ...DEFAULT_EMBED_SETTINGS }, updatedAt: '2026-09-20T10:00:00.000Z' } describe('buildSettingsPayload 表单 → settings 载荷', () => { it('缺省草稿 → 契约缺省值全集(整体提交:字段齐全)', () => { expect(buildSettingsPayload({ ...DEFAULT_EMBED_SETTINGS })).toEqual({ position: 'right', size: 'md', intervalMs: 5000, lang: 'auto', collapsedDefault: false }) }) it('intervalMs 越界/非有限值 → 夹取到契约区间(键盘输入兜底)', () => { expect(clampIntervalMs(1)).toBe(3000) expect(clampIntervalMs(2999.6)).toBe(3000) expect(clampIntervalMs(100000)).toBe(30000) expect(clampIntervalMs(Number.NaN)).toBe(5000) expect(clampIntervalMs(Number.POSITIVE_INFINITY)).toBe(5000) const draft: EmbedSettingsDraft = { ...DEFAULT_EMBED_SETTINGS, intervalMs: 2000 } expect(buildSettingsPayload(draft).intervalMs).toBe(3000) }) }) describe('buildSlotEditPayload 编辑载荷收敛', () => { it('name 与 settings 均未变化 → 空载荷(不制造服务端 no-op)', () => { expect( buildSlotEditPayload(CURRENT_ITEM, CURRENT_ITEM.name, { ...DEFAULT_EMBED_SETTINGS }) ).toEqual({}) }) it('仅 name 变化 → 只送 name;settings 变化 → 送完整 settings(整体替换)', () => { expect( buildSlotEditPayload(CURRENT_ITEM, ' 活动页左侧位 ', { ...DEFAULT_EMBED_SETTINGS }) ).toEqual({ name: '活动页左侧位' }) const changed: EmbedSettingsDraft = { ...DEFAULT_EMBED_SETTINGS, position: 'left', size: 'sm', intervalMs: 8000, lang: 'zh-CN', collapsedDefault: true } expect(buildSlotEditPayload(CURRENT_ITEM, CURRENT_ITEM.name, changed)).toEqual({ settings: changed }) }) }) describe('buildEmbedSnippet 嵌入代码拼接', () => { it('EMBED_ORIGIN + token → /embed/v1/loader.js 引用(尾斜杠容忍)', () => { expect(buildEmbedSnippet('https://view.example.com', 'abc123def456ghi789jklmno')).toBe( '' ) expect(buildEmbedSnippet('http://127.0.0.1:5175//', 'tok')).toBe( '' ) }) it('环境基址:VITE_EMBED_ORIGIN 缺省/空白兜底本机 dev', () => { expect(embedOriginFromEnv({})).toBe(EMBED_ORIGIN_FALLBACK) expect(embedOriginFromEnv({ VITE_EMBED_ORIGIN: ' ' })).toBe(EMBED_ORIGIN_FALLBACK) expect(embedOriginFromEnv({ VITE_EMBED_ORIGIN: ' https://cdn.example.com/ ' })).toBe( 'https://cdn.example.com' ) }) }) describe('bindChangeKind 绑定变更分类', () => { it('null→id 绑定 / id→id 换绑 / id→null 解绑 / 值不变 none', () => { expect(bindChangeKind(null, 'album-1')).toBe('bind') expect(bindChangeKind('album-1', 'album-2')).toBe('rebind') expect(bindChangeKind('album-1', null)).toBe('unbind') expect(bindChangeKind('album-1', 'album-1')).toBe('none') expect(bindChangeKind(null, null)).toBe('none') }) }) describe('绑定变更确认文案(A22:configVersion 将递增,官网无需改动)', () => { const zh = zhMessages.embedSlotsManage as Record const en = enMessages.embedSlotsManage as Record const zhBind = zh.bind as Record const enBind = en.bind as Record it('zh/en 键集合一致(embedSlotsManage 子树)', () => { const keysOf = (obj: Record, prefix = ''): string[] => Object.entries(obj).flatMap(([key, value]) => typeof value === 'object' && value !== null ? keysOf(value as Record, `${prefix}${key}.`) : [`${prefix}${key}`] ) expect(keysOf(en)).toEqual(keysOf(zh)) }) it('三类确认文案均携带 A22 短语(换绑不改官网:loader 只认 token)', () => { for (const key of ['confirmBind', 'confirmRebind', 'confirmUnbind']) { expect(zhBind[key]).toContain('configVersion 将递增') expect(zhBind[key]).toContain('官网无需改动') expect(enBind[key]).toContain('configVersion will increase') expect(enBind[key]).toContain('no change is needed on the host site') } }) })