mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2026-05-15 13:04:29 +00:00
206 lines
6.3 KiB
TypeScript
206 lines
6.3 KiB
TypeScript
/*
|
||
* Tencent is pleased to support the open source community by making TMagicEditor available.
|
||
*
|
||
* Copyright (C) 2025 Tencent.
|
||
*/
|
||
import { describe, expect, test, vi } from 'vitest';
|
||
import { ref } from 'vue';
|
||
|
||
import { NodeType } from '@tmagic/core';
|
||
|
||
import { useCopyMenu, useDeleteMenu, useMoveToMenu, usePasteMenu } from '@editor/utils/content-menu';
|
||
|
||
describe('content-menu utils', () => {
|
||
test('useDeleteMenu - 普通节点 display=true 并触发 remove', () => {
|
||
const remove = vi.fn();
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'node') return { type: 'text' };
|
||
if (k === 'nodes') return [{ id: 1 }];
|
||
return undefined;
|
||
},
|
||
remove,
|
||
};
|
||
const m = useDeleteMenu();
|
||
expect(m.text).toBe('删除');
|
||
expect((m as any).display({ editorService })).toBe(true);
|
||
(m as any).handler({ editorService });
|
||
expect(remove).toHaveBeenCalled();
|
||
});
|
||
|
||
test('useDeleteMenu - 页面/根节点 display=false', () => {
|
||
const editorService: any = {
|
||
get: () => ({ type: NodeType.ROOT }),
|
||
remove: vi.fn(),
|
||
};
|
||
const m = useDeleteMenu();
|
||
expect((m as any).display({ editorService })).toBe(false);
|
||
|
||
editorService.get = () => ({ type: NodeType.PAGE });
|
||
expect((m as any).display({ editorService })).toBe(false);
|
||
});
|
||
|
||
test('useCopyMenu 触发 editorService.copy', () => {
|
||
const copy = vi.fn();
|
||
const editorService: any = {
|
||
get: () => [{ id: 1 }],
|
||
copy,
|
||
};
|
||
const m = useCopyMenu();
|
||
(m as any).handler({ editorService });
|
||
expect(copy).toHaveBeenCalled();
|
||
});
|
||
|
||
test('usePasteMenu - storage 有数据时 display=true,无数据 false', () => {
|
||
const m = usePasteMenu();
|
||
expect(
|
||
(m as any).display({
|
||
storageService: { getItem: () => '{"a":1}' },
|
||
}),
|
||
).toBe(true);
|
||
expect(
|
||
(m as any).display({
|
||
storageService: { getItem: () => null },
|
||
}),
|
||
).toBe(false);
|
||
});
|
||
|
||
test('usePasteMenu - 当节点为空时不调用 paste', () => {
|
||
const paste = vi.fn();
|
||
const editorService: any = {
|
||
get: (k: string) => (k === 'nodes' ? [] : null),
|
||
paste,
|
||
};
|
||
const m = usePasteMenu();
|
||
(m as any).handler({ editorService, uiService: { get: () => 1 } });
|
||
expect(paste).not.toHaveBeenCalled();
|
||
});
|
||
|
||
test('usePasteMenu - 普通粘贴', () => {
|
||
const paste = vi.fn();
|
||
const editorService: any = {
|
||
get: (k: string) => (k === 'nodes' ? [{ id: 1 }] : null),
|
||
paste,
|
||
};
|
||
const m = usePasteMenu();
|
||
(m as any).handler({ editorService, uiService: { get: () => 1 } });
|
||
expect(paste).toHaveBeenCalled();
|
||
});
|
||
|
||
test('usePasteMenu - 通过 menu.$el 计算定位 paste', () => {
|
||
const paste = vi.fn();
|
||
const stage = {
|
||
container: { getBoundingClientRect: () => ({ left: 5, top: 8 }) },
|
||
renderer: { getDocument: () => document },
|
||
};
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'nodes') return [{ id: 1 }];
|
||
if (k === 'stage') return stage;
|
||
return null;
|
||
},
|
||
paste,
|
||
};
|
||
const menuEl = document.createElement('div');
|
||
menuEl.getBoundingClientRect = () => ({
|
||
left: 30,
|
||
top: 40,
|
||
right: 30,
|
||
bottom: 40,
|
||
width: 0,
|
||
height: 0,
|
||
x: 30,
|
||
y: 40,
|
||
toJSON: () => ({}),
|
||
});
|
||
const menu = ref<any>({ $el: menuEl });
|
||
const m = usePasteMenu(menu);
|
||
(m as any).handler({ editorService, uiService: { get: () => 2 } });
|
||
expect(paste).toHaveBeenCalledWith(expect.objectContaining({ left: expect.any(Number), top: expect.any(Number) }));
|
||
});
|
||
|
||
test('useMoveToMenu - display 行为校验', () => {
|
||
const root = ref({ items: [{ id: 'p1', name: 'P1' }] });
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'root') return root.value;
|
||
if (k === 'page') return { id: 'p1' };
|
||
if (k === 'pageLength') return 2;
|
||
if (k === 'node') return { id: 'btn' };
|
||
return undefined;
|
||
},
|
||
add: vi.fn(),
|
||
remove: vi.fn(),
|
||
getNodeById: () => null,
|
||
};
|
||
const m = useMoveToMenu({ editorService } as any);
|
||
expect((m as any).display({ editorService })).toBe(true);
|
||
editorService.get = (k: string) => {
|
||
if (k === 'pageLength') return 1;
|
||
if (k === 'node') return { type: NodeType.PAGE };
|
||
return undefined;
|
||
};
|
||
expect((m as any).display({ editorService })).toBe(false);
|
||
});
|
||
|
||
test('useMoveToMenu - 没有 parent 时直接 return', () => {
|
||
const root = ref({ items: [{ id: 'p1', name: 'P1' }] });
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'root') return root.value;
|
||
if (k === 'page') return { id: 'p2' };
|
||
if (k === 'pageLength') return 2;
|
||
if (k === 'node') return { id: 'btn' };
|
||
if (k === 'nodes') return [{ id: 'btn' }];
|
||
return undefined;
|
||
},
|
||
add: vi.fn(),
|
||
remove: vi.fn(),
|
||
getNodeById: () => null,
|
||
};
|
||
const m = useMoveToMenu({ editorService } as any);
|
||
(m as any).items[0].handler({ editorService });
|
||
expect(editorService.add).not.toHaveBeenCalled();
|
||
});
|
||
|
||
test('useMoveToMenu - root 为空时 items 为空数组', () => {
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'root') return null;
|
||
if (k === 'page') return { id: 'x' };
|
||
return undefined;
|
||
},
|
||
};
|
||
const m = useMoveToMenu({ editorService } as any);
|
||
expect((m as any).items).toEqual([]);
|
||
});
|
||
|
||
test('useMoveToMenu - 列出非当前页 page,并执行 moveTo', () => {
|
||
const root = ref({
|
||
items: [
|
||
{ id: 'p1', name: 'P1' },
|
||
{ id: 'p2', name: 'P2' },
|
||
],
|
||
});
|
||
const editorService: any = {
|
||
get: (k: string) => {
|
||
if (k === 'root') return root.value;
|
||
if (k === 'page') return { id: 'p1' };
|
||
if (k === 'pageLength') return 2;
|
||
if (k === 'node') return { id: 'btn' };
|
||
if (k === 'nodes') return [{ id: 'btn' }];
|
||
return undefined;
|
||
},
|
||
add: vi.fn(),
|
||
remove: vi.fn(),
|
||
getNodeById: (id: string) => ({ id, items: [] }),
|
||
};
|
||
const m = useMoveToMenu({ editorService } as any);
|
||
expect((m as any).items).toHaveLength(1);
|
||
expect((m as any).items[0].text).toContain('P2');
|
||
(m as any).items[0].handler({ editorService });
|
||
expect(editorService.add).toHaveBeenCalled();
|
||
expect(editorService.remove).toHaveBeenCalled();
|
||
});
|
||
});
|