mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-05-15 21:13:35 +00:00
169 lines
6.3 KiB
TypeScript
169 lines
6.3 KiB
TypeScript
/*
|
|
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
|
*
|
|
* Copyright (C) 2025 Tencent.
|
|
*/
|
|
import { afterEach, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
|
|
import codeBlockService from '@editor/services/codeBlock';
|
|
import storageService, { Protocol } from '@editor/services/storage';
|
|
import { CODE_DRAFT_STORAGE_KEY } from '@editor/type';
|
|
import { setEditorConfig } from '@editor/utils/config';
|
|
import { COPY_CODE_STORAGE_KEY } from '@editor/utils/editor';
|
|
|
|
vi.mock('@editor/services/editor', () => ({
|
|
default: {
|
|
getNodeById: vi.fn((id: string) => ({ id, code: 'code1' })),
|
|
},
|
|
}));
|
|
|
|
beforeAll(() => {
|
|
setEditorConfig({
|
|
// eslint-disable-next-line no-new-func
|
|
parseDSL: ((str: string) => new Function(`return ${str}`)()) as any,
|
|
} as any);
|
|
});
|
|
|
|
beforeEach(() => {
|
|
codeBlockService.resetState();
|
|
globalThis.localStorage.clear();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('CodeBlockService - 基础', () => {
|
|
test('setCodeDsl / getCodeDsl 保存并触发事件', async () => {
|
|
const fn = vi.fn();
|
|
codeBlockService.on('code-dsl-change', fn);
|
|
await codeBlockService.setCodeDsl({ a: { name: 'a', content: 'x' } } as any);
|
|
expect(codeBlockService.getCodeDsl()).toEqual({ a: { name: 'a', content: 'x' } });
|
|
expect(fn).toHaveBeenCalled();
|
|
codeBlockService.off('code-dsl-change', fn);
|
|
});
|
|
|
|
test('getCodeContentById - 没有 dsl 或 id 返回 null', () => {
|
|
expect(codeBlockService.getCodeContentById('')).toBeNull();
|
|
expect(codeBlockService.getCodeContentById('any')).toBeNull();
|
|
});
|
|
|
|
test('getCodeContentById - 取得现有内容', async () => {
|
|
await codeBlockService.setCodeDsl({ x: { name: 'X' } } as any);
|
|
expect(codeBlockService.getCodeContentById('x')).toEqual({ name: 'X' });
|
|
expect(codeBlockService.getCodeContentById('y')).toBeNull();
|
|
});
|
|
|
|
test('setCodeDslByIdSync - 没有 dsl 时抛错', () => {
|
|
expect(() => codeBlockService.setCodeDslByIdSync('id', {} as any)).toThrow('dsl中没有codeBlocks');
|
|
});
|
|
|
|
test('setCodeDslByIdSync - 已存在且 force=false 时跳过', async () => {
|
|
await codeBlockService.setCodeDsl({ a: { name: 'A' } } as any);
|
|
codeBlockService.setCodeDslByIdSync('a', { name: 'NEW' } as any, false);
|
|
expect(codeBlockService.getCodeContentById('a')?.name).toBe('A');
|
|
});
|
|
|
|
test('setCodeDslByIdSync - content 为字符串时被 parseDSL 转换', async () => {
|
|
await codeBlockService.setCodeDsl({} as any);
|
|
codeBlockService.setCodeDslByIdSync('a', { name: 'A', content: '() => 42' } as any);
|
|
const item = codeBlockService.getCodeContentById('a') as any;
|
|
expect(typeof item.content).toBe('function');
|
|
expect(item.content()).toBe(42);
|
|
});
|
|
|
|
test('setCodeDslByIdSync - 触发 addOrUpdate 事件', async () => {
|
|
await codeBlockService.setCodeDsl({} as any);
|
|
const fn = vi.fn();
|
|
codeBlockService.on('addOrUpdate', fn);
|
|
codeBlockService.setCodeDslByIdSync('id', { name: 'a' } as any);
|
|
expect(fn).toHaveBeenCalledWith('id', expect.any(Object));
|
|
codeBlockService.off('addOrUpdate', fn);
|
|
});
|
|
|
|
test('getCodeDslByIds 仅返回指定 ids', async () => {
|
|
await codeBlockService.setCodeDsl({ a: { name: 'a' }, b: { name: 'b' } } as any);
|
|
expect(codeBlockService.getCodeDslByIds(['a'])).toEqual({ a: { name: 'a' } });
|
|
});
|
|
|
|
test('编辑状态 / combineIds / undeletableList', async () => {
|
|
expect(codeBlockService.getEditStatus()).toBe(true);
|
|
await codeBlockService.setEditStatus(false);
|
|
expect(codeBlockService.getEditStatus()).toBe(false);
|
|
|
|
await codeBlockService.setCombineIds(['a', 'b']);
|
|
expect(codeBlockService.getCombineIds()).toEqual(['a', 'b']);
|
|
|
|
await codeBlockService.setUndeleteableList(['x']);
|
|
expect(codeBlockService.getUndeletableList()).toEqual(['x']);
|
|
});
|
|
|
|
test('代码草稿 set/get/remove', () => {
|
|
codeBlockService.setCodeDraft('id', 'draft');
|
|
expect(globalThis.localStorage.getItem(`${CODE_DRAFT_STORAGE_KEY}_id`)).toBe('draft');
|
|
expect(codeBlockService.getCodeDraft('id')).toBe('draft');
|
|
codeBlockService.removeCodeDraft('id');
|
|
expect(codeBlockService.getCodeDraft('id')).toBeNull();
|
|
});
|
|
|
|
test('deleteCodeDslByIds 删除并触发 remove 事件', async () => {
|
|
await codeBlockService.setCodeDsl({ a: { name: 'a' }, b: { name: 'b' } } as any);
|
|
const fn = vi.fn();
|
|
codeBlockService.on('remove', fn);
|
|
await codeBlockService.deleteCodeDslByIds(['a', 'b']);
|
|
expect(codeBlockService.getCodeDsl()).toEqual({});
|
|
expect(fn).toHaveBeenCalledTimes(2);
|
|
codeBlockService.off('remove', fn);
|
|
});
|
|
|
|
test('deleteCodeDslByIds - dsl 为空时直接返回', async () => {
|
|
await expect(codeBlockService.deleteCodeDslByIds(['x'])).resolves.toBeUndefined();
|
|
});
|
|
|
|
test('paramsColConfig set/get', () => {
|
|
const cfg = { type: 'row', items: [] } as any;
|
|
codeBlockService.setParamsColConfig(cfg);
|
|
expect(codeBlockService.getParamsColConfig()).toEqual(cfg);
|
|
});
|
|
|
|
test('getUniqueId 在重复时再次取', async () => {
|
|
let count = 0;
|
|
const random = vi.spyOn(Math, 'random').mockImplementation(() => {
|
|
count += 1;
|
|
return count === 1 ? 0.111111111 : 0.222222222;
|
|
});
|
|
await codeBlockService.setCodeDsl({ code_1111: { name: 'x' } } as any);
|
|
const id = await codeBlockService.getUniqueId();
|
|
expect(id.startsWith('code_')).toBe(true);
|
|
expect(id).not.toBe('code_1111');
|
|
random.mockRestore();
|
|
});
|
|
|
|
test('paste - 不覆盖现有 id', async () => {
|
|
await codeBlockService.setCodeDsl({ a: { name: 'A' } } as any);
|
|
storageService.setItem(
|
|
COPY_CODE_STORAGE_KEY,
|
|
{ a: { name: 'OTHER' }, b: { name: 'B' } },
|
|
{ protocol: Protocol.OBJECT },
|
|
);
|
|
|
|
codeBlockService.paste();
|
|
expect(codeBlockService.getCodeContentById('a')?.name).toBe('A');
|
|
expect(codeBlockService.getCodeContentById('b')?.name).toBe('B');
|
|
});
|
|
|
|
test('copyWithRelated - 没有 collectorOptions 时仅写空对象', () => {
|
|
codeBlockService.copyWithRelated([]);
|
|
const stored = storageService.getItem(COPY_CODE_STORAGE_KEY, { protocol: Protocol.OBJECT });
|
|
expect(stored).toEqual({});
|
|
});
|
|
|
|
test('destroy 清空 listeners 与 plugin', () => {
|
|
const fn = vi.fn();
|
|
codeBlockService.on('addOrUpdate', fn);
|
|
codeBlockService.destroy();
|
|
codeBlockService.emit('addOrUpdate', 'a');
|
|
expect(fn).not.toHaveBeenCalled();
|
|
});
|
|
});
|