import { describe, expect, it } from 'vitest' import { appendManifestEntry, asExtensionEntries, buildManifestEntry, findManifestEntry, nextExtensionId, } from './localExtensions' /** 造一条 manifest 条目(id 与 codeFileId 成对,和 Figma 真实清单一致)。 */ function manifest(id: number, manifestPath: string) { return { id, manifestPath, lastKnownName: `plugin-${id}`, lastKnownPluginId: '', fileMetadata: { type: 'manifest' as const, codeFileId: id + 1, uiFileIds: [] }, } } /** Figma 加载插件后补的 code.js 条目,占的是 manifest 的 codeFileId。 */ function code(id: number, manifestFileId: number, manifestPath: string) { return { id, manifestPath, fileMetadata: { type: 'code' as const, manifestFileId }, } } describe('nextExtensionId', () => { it('空清单从 1 开始', () => { expect(nextExtensionId([])).toBe(1) }) it('取已有条目 id 最大值 +1', () => { expect(nextExtensionId([manifest(1, '/a/manifest.json'), code(2, 1, '/a/code.js')])).toBe(3) }) it('codeFileId 预定的号也要算进去(code 条目还没建出来时)', () => { // id 只到 11,但 11 的 codeFileId 已经把 12 预定了 → 下一个必须是 13 expect(nextExtensionId([ manifest(9, '/a/manifest.json'), code(10, 9, '/a/code.js'), manifest(11, '/b/manifest.json'), ])).toBe(13) }) it('顺序乱了也按最大值算', () => { expect(nextExtensionId([ code(8, 7, '/b/code.js'), manifest(3, '/a/manifest.json'), manifest(7, '/b/manifest.json'), ])).toBe(9) }) }) describe('findManifestEntry', () => { const entries = [manifest(1, '/a/manifest.json'), manifest(3, '/b/manifest.json')] it('按 manifestPath 精确命中', () => { expect(findManifestEntry(entries, '/b/manifest.json')?.id).toBe(3) }) it('路径不同就不算重复(同名不同目录)', () => { expect(findManifestEntry(entries, '/c/manifest.json')).toBeUndefined() }) }) describe('buildManifestEntry', () => { it('codeFileId 紧跟 id,给 Figma 之后建 code 条目占号', () => { expect(buildManifestEntry({ id: 19, manifestPath: '/x/manifest.json', name: 'X Lab' })).toEqual({ id: 19, manifestPath: '/x/manifest.json', lastKnownName: 'X Lab', lastKnownPluginId: '', fileMetadata: { type: 'manifest', codeFileId: 20, uiFileIds: [] }, }) }) }) describe('appendManifestEntry', () => { it('新插件追加到末尾,id 接着往下发', () => { const entries = [manifest(1, '/a/manifest.json'), code(2, 1, '/a/code.js')] const got = appendManifestEntry(entries, { manifestPath: '/b/manifest.json', name: 'B Lab' }) expect(got.added).toBe(true) expect(got.entries).toHaveLength(3) expect(got.entries[2]).toMatchObject({ id: 3, manifestPath: '/b/manifest.json', lastKnownName: 'B Lab' }) // 原数组不被改动 expect(entries).toHaveLength(2) }) it('已导入过 → 不追加,名字用清单里记的那个', () => { const entries = [manifest(1, '/a/manifest.json')] const got = appendManifestEntry(entries, { manifestPath: '/a/manifest.json', name: '新名字' }) expect(got.added).toBe(false) expect(got.entries).toBe(entries) expect(got.name).toBe('plugin-1') }) }) describe('asExtensionEntries', () => { it('不是数组 → 空清单(Figma 没装过插件时该字段可能缺失)', () => { expect(asExtensionEntries(undefined)).toEqual([]) expect(asExtensionEntries({})).toEqual([]) }) it('丢掉缺 id / manifestPath 的脏条目', () => { expect(asExtensionEntries([ manifest(1, '/a/manifest.json'), { id: 'x', manifestPath: '/b/manifest.json' }, { id: 2 }, null, ])).toHaveLength(1) }) })