lowcode-engine/packages/designer/tests/document/node/node.add.test.ts

574 lines
21 KiB
TypeScript
Raw Permalink Normal View History

2022-01-25 15:30:17 +08:00
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import '../../fixtures/window';
import { Project, IProject } from '../../../src/project/project';
import { Node, INode } from '../../../src/document/node/node';
2022-01-25 15:30:17 +08:00
import { Designer } from '../../../src/designer/designer';
import formSchema from '../../fixtures/schema/form';
import { getIdsFromSchema, getNodeFromSchemaById } from '../../utils';
const mockCreateSettingEntry = jest.fn();
jest.mock('../../../src/designer/designer', () => {
return {
Designer: jest.fn().mockImplementation(() => {
return {
getComponentMeta() {
return {
getMetadata() {
return { configure: { advanced: null } };
},
get advanced() {
return {};
},
2022-01-25 15:30:17 +08:00
};
},
transformProps(props) { return props; },
createSettingEntry: mockCreateSettingEntry,
postEvent() {},
};
}),
};
});
let designer = null;
beforeAll(() => {
designer = new Designer({});
});
describe('schema 生成节点模型测试', () => {
describe('block ❌ | component ❌ | slot ❌', () => {
let project: IProject;
2022-01-25 15:30:17 +08:00
beforeEach(() => {
project = new Project(designer, {
componentsTree: [
formSchema,
],
});
project.open();
});
afterEach(() => {
project.unload();
});
it('基本的节点模型初始化,模型导出', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
2022-01-25 15:30:17 +08:00
const ids = getIdsFromSchema(formSchema);
const expectedNodeCnt = ids.length;
expect(nodesMap?.size).toBe(expectedNodeCnt);
2022-01-25 15:30:17 +08:00
ids.forEach(id => {
expect(nodesMap?.get(id)?.componentName).toBe(getNodeFromSchemaById(formSchema, id).componentName);
2022-01-25 15:30:17 +08:00
});
const pageNode = currentDocument?.getNode('page');
expect(pageNode?.getComponentName()).toBe('Page');
expect(pageNode?.getIcon()).toBeUndefined();
const exportSchema = currentDocument?.export(1);
expect(getIdsFromSchema(exportSchema).length).toBe(expectedNodeCnt);
nodesMap.forEach(node => {
// 触发 getter
node.settingEntry;
});
expect(mockCreateSettingEntry).toBeCalledTimes(expectedNodeCnt);
});
it('基本的节点模型初始化,节点深度', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const getNode = currentDocument?.getNode.bind(currentDocument);
const pageNode = getNode?.('page');
const rootHeaderNode = getNode?.('node_k1ow3cba');
const rootContentNode = getNode?.('node_k1ow3cbb');
const rootFooterNode = getNode?.('node_k1ow3cbc');
const formNode = getNode?.('form');
const cardNode = getNode?.('node_k1ow3cbj');
const cardContentNode = getNode?.('node_k1ow3cbk');
const columnsLayoutNode = getNode?.('node_k1ow3cbw');
const columnNode = getNode?.('node_k1ow3cbx');
const textFieldNode = getNode?.('node_k1ow3cbz');
2022-01-25 15:30:17 +08:00
expect(pageNode?.zLevel).toBe(0);
expect(rootHeaderNode?.zLevel).toBe(1);
expect(rootContentNode?.zLevel).toBe(1);
expect(rootFooterNode?.zLevel).toBe(1);
expect(formNode?.zLevel).toBe(2);
expect(cardNode?.zLevel).toBe(3);
expect(cardContentNode?.zLevel).toBe(4);
expect(columnsLayoutNode?.zLevel).toBe(5);
expect(columnNode?.zLevel).toBe(6);
expect(textFieldNode?.zLevel).toBe(7);
expect(textFieldNode?.getZLevelTop(7)).toEqual(textFieldNode);
expect(textFieldNode?.getZLevelTop(6)).toEqual(columnNode);
expect(textFieldNode?.getZLevelTop(5)).toEqual(columnsLayoutNode);
expect(textFieldNode?.getZLevelTop(4)).toEqual(cardContentNode);
expect(textFieldNode?.getZLevelTop(3)).toEqual(cardNode);
expect(textFieldNode?.getZLevelTop(2)).toEqual(formNode);
expect(textFieldNode?.getZLevelTop(1)).toEqual(rootContentNode);
expect(textFieldNode?.getZLevelTop(0)).toEqual(pageNode);
// 异常情况
expect(textFieldNode?.getZLevelTop(8)).toBeNull();
expect(textFieldNode?.getZLevelTop(-1)).toBeNull();
});
it('基本的节点模型初始化,节点父子、兄弟相关方法', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const getNode = currentDocument.getNode.bind(currentDocument);
const pageNode = getNode('page');
const rootHeaderNode = getNode('node_k1ow3cba');
const rootContentNode = getNode('node_k1ow3cbb');
const rootFooterNode = getNode('node_k1ow3cbc');
const formNode = getNode('form');
const cardNode = getNode('node_k1ow3cbj');
const cardContentNode = getNode('node_k1ow3cbk');
const columnsLayoutNode = getNode('node_k1ow3cbw');
const columnNode = getNode('node_k1ow3cbx');
const textFieldNode = getNode('node_k1ow3cbz');
expect(pageNode?.index).toBe(-1);
expect(pageNode?.children?.toString()).toBe('[object Array]');
2022-01-25 15:30:17 +08:00
expect(pageNode?.children?.get(1)).toBe(rootContentNode);
expect(pageNode?.getChildren()?.get(1)).toBe(rootContentNode);
expect(pageNode?.getNode()).toBe(pageNode);
expect(rootFooterNode?.index).toBe(2);
expect(textFieldNode?.getParent()).toBe(columnNode);
expect(columnNode?.getParent()).toBe(columnsLayoutNode);
expect(columnsLayoutNode?.getParent()).toBe(cardContentNode);
expect(cardContentNode?.getParent()).toBe(cardNode);
expect(cardNode?.getParent()).toBe(formNode);
expect(formNode?.getParent()).toBe(rootContentNode);
expect(rootContentNode?.getParent()).toBe(pageNode);
expect(rootContentNode?.prevSibling).toBe(rootHeaderNode);
expect(rootContentNode?.nextSibling).toBe(rootFooterNode);
expect(pageNode?.isRoot()).toBe(true);
expect(pageNode?.contains(textFieldNode)).toBe(true);
expect(textFieldNode?.getRoot()).toBe(pageNode);
expect(columnNode?.getRoot()).toBe(pageNode);
expect(columnsLayoutNode?.getRoot()).toBe(pageNode);
expect(cardContentNode?.getRoot()).toBe(pageNode);
expect(cardNode?.getRoot()).toBe(pageNode);
expect(formNode?.getRoot()).toBe(pageNode);
expect(rootContentNode?.getRoot()).toBe(pageNode);
});
it('基本的节点模型初始化,节点新建、删除等事件', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const getNode = currentDocument?.getNode.bind(currentDocument);
const createNode = currentDocument?.createNode.bind(currentDocument);
2022-01-25 15:30:17 +08:00
const pageNode = getNode?.('page');
2022-01-25 15:30:17 +08:00
const nodeCreateHandler = jest.fn();
const offCreate = currentDocument?.onNodeCreate(nodeCreateHandler);
const node = createNode?.({
2022-01-25 15:30:17 +08:00
componentName: 'TextInput',
props: {
propA: 'haha',
},
});
pageNode && node && currentDocument?.insertNode(pageNode, node);
2022-01-25 15:30:17 +08:00
expect(nodeCreateHandler).toHaveBeenCalledTimes(1);
expect(nodeCreateHandler.mock.calls[0][0]).toBe(node);
expect(nodeCreateHandler.mock.calls[0][0].componentName).toBe('TextInput');
expect(nodeCreateHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
const nodeDestroyHandler = jest.fn();
const offDestroy = currentDocument?.onNodeDestroy(nodeDestroyHandler);
node?.remove();
2022-01-25 15:30:17 +08:00
expect(nodeDestroyHandler).toHaveBeenCalledTimes(1);
expect(nodeDestroyHandler.mock.calls[0][0]).toBe(node);
expect(nodeDestroyHandler.mock.calls[0][0].componentName).toBe('TextInput');
expect(nodeDestroyHandler.mock.calls[0][0].getPropValue('propA')).toBe('haha');
offCreate();
offDestroy();
});
it.skip('基本的节点模型初始化,节点插入等方法', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const getNode = currentDocument.getNode.bind(currentDocument);
const formNode = getNode('form');
const node1 = currentDocument.createNode({
componentName: 'TextInput',
props: {
propA: 'haha',
},
});
const node2 = currentDocument.createNode({
componentName: 'TextInput',
props: {
propA: 'heihei',
},
});
const node3 = currentDocument.createNode({
componentName: 'TextInput',
props: {
propA: 'heihei2',
},
});
const node4 = currentDocument.createNode({
componentName: 'TextInput',
props: {
propA: 'heihei3',
},
});
formNode?.insertBefore(node2);
// formNode?.insertBefore(node1, node2);
// formNode?.insertAfter(node3);
// formNode?.insertAfter(node4, node3);
expect(formNode?.children?.get(0)).toBe(node1);
expect(formNode?.children?.get(1)).toBe(node2);
// expect(formNode?.children?.get(5)).toBe(node3);
// expect(formNode?.children?.get(6)).toBe(node4);
});
it('基本的节点模型初始化,节点其他方法', () => {
expect(project).toBeTruthy();
const { currentDocument } = project;
const getNode = currentDocument.getNode.bind(currentDocument);
const pageNode = getNode('page');
expect(pageNode?.isPage()).toBe(true);
expect(pageNode?.isComponent()).toBe(false);
expect(pageNode?.isSlot()).toBe(false);
expect(pageNode?.title).toBe('hey, i\' a page!');
});
describe('节点新增insertNode', () => {
let project: Project;
beforeEach(() => {
project = new Project(designer, {
componentsTree: [
formSchema,
],
});
project.open();
});
it('场景一:插入 NodeSchema不指定 index', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const { nodesMap } = currentDocument;
const formNode = nodesMap.get('form') as Node;
const formNode2 = currentDocument?.getNode('form');
expect(formNode).toEqual(formNode2);
currentDocument?.insertNode(formNode, {
componentName: 'TextInput',
id: 'nodeschema-id1',
props: {
propA: 'haha',
propB: 3,
},
});
expect(nodesMap.size).toBe(ids.length + 1);
expect(formNode.children?.length).toBe(4);
const insertedNode = formNode.children.get(formNode.children.length - 1);
expect(insertedNode.componentName).toBe('TextInput');
expect(insertedNode.propsData).toEqual({
propA: 'haha',
propB: 3,
});
// TODO: 把 checkId 的 commit pick 过来
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
});
it('场景一:插入 NodeSchema指定 index: 0', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, {
2022-01-25 15:30:17 +08:00
componentName: 'TextInput',
id: 'nodeschema-id1',
props: {
propA: 'haha',
propB: 3,
},
}, 0);
expect(nodesMap?.size).toBe(ids.length + 1);
expect(formNode?.children?.length).toBe(4);
const insertedNode = formNode?.children?.get(0);
expect(insertedNode?.componentName).toBe('TextInput');
expect(insertedNode?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha',
propB: 3,
});
// TODO: 把 checkId 的 commit pick 过来
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
});
it('场景一:插入 NodeSchema指定 index: 1', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, {
2022-01-25 15:30:17 +08:00
componentName: 'TextInput',
id: 'nodeschema-id1',
props: {
propA: 'haha',
propB: 3,
},
}, 1);
expect(nodesMap?.size).toBe(ids.length + 1);
expect(formNode?.children?.length).toBe(4);
const insertedNode = formNode?.children?.get(1);
expect(insertedNode?.componentName).toBe('TextInput');
expect(insertedNode?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha',
propB: 3,
});
// TODO: 把 checkId 的 commit pick 过来
// expect(nodesMap.get('nodeschema-id1').componentName).toBe('TextInput');
});
it('场景一:插入 NodeSchema有 children', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form') as INode;
2022-01-25 15:30:17 +08:00
currentDocument?.insertNode(formNode, {
componentName: 'ParentNode',
props: {
propA: 'haha',
propB: 3,
},
children: [
{
componentName: 'SubNode',
props: {
propA: 'haha',
propB: 3,
},
},
{
componentName: 'SubNode2',
props: {
propA: 'haha',
propB: 3,
},
},
],
});
expect(nodesMap?.size).toBe(ids.length + 3);
expect(formNode.children?.length).toBe(4);
2022-01-25 15:30:17 +08:00
expect(formNode.children?.get(3)?.componentName).toBe('ParentNode');
expect(formNode.children?.get(3)?.children?.get(0)?.componentName).toBe('SubNode');
expect(formNode.children?.get(3)?.children?.get(1)?.componentName).toBe('SubNode2');
});
it.skip('场景一:插入 NodeSchemaid 与现有 schema 里的 id 重复', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, {
2022-01-25 15:30:17 +08:00
componentName: 'TextInput',
id: 'nodeschema-id1',
props: {
propA: 'haha',
propB: 3,
},
});
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
expect(nodesMap?.size).toBe(ids.length + 1);
2022-01-25 15:30:17 +08:00
});
it.skip('场景一:插入 NodeSchemaid 与现有 schema 里的 id 重复,但关闭了 id 检测器', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form');
formNode && currentDocument?.insertNode(formNode, {
2022-01-25 15:30:17 +08:00
componentName: 'TextInput',
id: 'nodeschema-id1',
props: {
propA: 'haha',
propB: 3,
},
});
expect(nodesMap?.get('nodeschema-id1')?.componentName).toBe('TextInput');
expect(nodesMap?.size).toBe(ids.length + 1);
2022-01-25 15:30:17 +08:00
});
it('场景二:插入 Node 实例', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form');
2022-01-25 15:30:17 +08:00
const inputNode = currentDocument?.createNode({
componentName: 'TextInput',
id: 'nodeschema-id2',
props: {
propA: 'haha',
propB: 3,
},
});
formNode && currentDocument?.insertNode(formNode, inputNode);
expect(formNode?.children?.get(3)?.componentName).toBe('TextInput');
expect(nodesMap?.size).toBe(ids.length + 1);
2022-01-25 15:30:17 +08:00
});
it('场景三:插入 JSExpression', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form') as Node;
2022-01-25 15:30:17 +08:00
currentDocument?.insertNode(formNode, {
type: 'JSExpression',
value: 'just a expression',
});
expect(nodesMap?.size).toBe(ids.length + 1);
2022-01-25 15:30:17 +08:00
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
// expect(formNode.children?.get(3)?.children).toEqual({
// type: 'JSExpression',
// value: 'just a expression'
// });
});
it('场景四:插入 string', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form') as Node;
2022-01-25 15:30:17 +08:00
currentDocument?.insertNode(formNode, 'just a string');
expect(nodesMap?.size).toBe(ids.length + 1);
2022-01-25 15:30:17 +08:00
expect(formNode.children?.get(3)?.componentName).toBe('Leaf');
// expect(formNode.children?.get(3)?.children).toBe('just a string');
});
});
describe('节点新增insertNodes', () => {
let project: Project;
beforeEach(() => {
project = new Project(designer, {
componentsTree: [
formSchema,
],
});
project.open();
});
it('场景一:插入 NodeSchema指定 index', () => {
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form') as Node;
2022-01-25 15:30:17 +08:00
const formNode2 = currentDocument?.getNode('form');
expect(formNode).toEqual(formNode2);
currentDocument?.insertNodes(formNode, [
{
componentName: 'TextInput',
props: {
propA: 'haha2',
propB: 3,
},
},
{
componentName: 'TextInput2',
props: {
propA: 'haha',
propB: 3,
},
},
], 1);
expect(nodesMap?.size).toBe(ids.length + 2);
2022-01-25 15:30:17 +08:00
expect(formNode.children?.length).toBe(5);
const insertedNode1 = formNode.children?.get(1);
const insertedNode2 = formNode.children?.get(2);
expect(insertedNode1?.componentName).toBe('TextInput');
expect(insertedNode1?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha2',
propB: 3,
});
expect(insertedNode2?.componentName).toBe('TextInput2');
expect(insertedNode2?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha',
propB: 3,
});
});
it.only('场景二:插入 Node 实例,指定 index', () => {
2022-01-25 15:30:17 +08:00
expect(project).toBeTruthy();
const ids = getIdsFromSchema(formSchema);
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
const formNode = nodesMap?.get('form') as INode;
2022-01-25 15:30:17 +08:00
const formNode2 = currentDocument?.getNode('form');
expect(formNode).toEqual(formNode2);
const createdNode1 = currentDocument?.createNode({
componentName: 'TextInput',
props: {
propA: 'haha2',
propB: 3,
},
});
const createdNode2 = currentDocument?.createNode({
componentName: 'TextInput2',
props: {
propA: 'haha',
propB: 3,
},
});
currentDocument?.insertNodes(formNode, [createdNode1, createdNode2], 1);
expect(nodesMap?.size).toBe(ids.length + 2);
2022-01-25 15:30:17 +08:00
expect(formNode.children?.length).toBe(5);
const insertedNode1 = formNode.children?.get(1);
const insertedNode2 = formNode.children?.get(2);
expect(insertedNode1?.componentName).toBe('TextInput');
expect(insertedNode1?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha2',
propB: 3,
});
expect(insertedNode2?.componentName).toBe('TextInput2');
expect(insertedNode2?.propsData).toEqual({
2022-01-25 15:30:17 +08:00
propA: 'haha',
propB: 3,
});
});
});
});
describe('block ❌ | component ❌ | slot ✅', () => {
it('基本的 slot 创建', () => {
const formSchemaWithSlot = set(cloneDeep(formSchema), 'children[0].children[0].props.title.type', 'JSSlot');
const project = new Project(designer, {
componentsTree: [
formSchemaWithSlot,
],
});
project.open();
expect(project).toBeTruthy();
const { currentDocument } = project;
const nodesMap = currentDocument?.nodesMap;
2022-01-25 15:30:17 +08:00
const ids = getIdsFromSchema(formSchema);
// 目前每个 slot 会新增1 + children.length个节点
const expectedNodeCnt = ids.length + 2;
expect(nodesMap?.size).toBe(expectedNodeCnt);
2022-01-25 15:30:17 +08:00
// PageHeader
expect(nodesMap?.get('node_k1ow3cbd')?.slots).toHaveLength(1);
2022-01-25 15:30:17 +08:00
});
});
});