mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
refactor: 兼容 propTypes 写错
refactor(test): 增加 dragon / host / designer 部分单测
This commit is contained in:
parent
4cf6637c4a
commit
084c342a65
@ -103,7 +103,7 @@ LowcodeTypes.exact = (typesMap: any) => {
|
||||
const configs = Object.keys(typesMap).map(key => {
|
||||
return {
|
||||
name: key,
|
||||
propType: typesMap[key].lowcodeType || 'any',
|
||||
propType: typesMap[key]?.lowcodeType || 'any',
|
||||
};
|
||||
});
|
||||
return define(PropTypes.exact(typesMap), {
|
||||
@ -117,7 +117,7 @@ LowcodeTypes.shape = (typesMap: any) => {
|
||||
const configs = Object.keys(typesMap).map(key => {
|
||||
return {
|
||||
name: key,
|
||||
propType: typesMap[key].lowcodeType || 'any',
|
||||
propType: typesMap[key]?.lowcodeType || 'any',
|
||||
};
|
||||
});
|
||||
return define(PropTypes.shape(typesMap), {
|
||||
|
||||
@ -8,7 +8,6 @@ function isInLiveEditing() {
|
||||
if (globalContext.has(Editor)) {
|
||||
return Boolean(globalContext.get(Editor).get('designer')?.project?.simulator?.liveEditing?.editing);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNextForSelect(next: any, head?: any, parent?: any): any {
|
||||
|
||||
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import set from 'lodash/set';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import '../fixtures/window';
|
||||
import { Editor } from '@ali/lowcode-editor-core';
|
||||
import { Editor, globalContext } from '@ali/lowcode-editor-core';
|
||||
import {
|
||||
AssetLevel,
|
||||
Asset,
|
||||
@ -14,65 +14,100 @@ import {
|
||||
import { Project } from '../../src/project/project';
|
||||
import { Node } from '../../src/document/node/node';
|
||||
import { Designer } from '../../src/designer/designer';
|
||||
import { DocumentModel } from '../../src/document/document-model';
|
||||
import formSchema from '../fixtures/schema/form';
|
||||
import { getMockDocument, getMockWindow, getMockEvent } from '../utils';
|
||||
import { BuiltinSimulatorHost } from '../../src/builtin-simulator/host';
|
||||
import { eq } from 'lodash';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
|
||||
const editor = new Editor();
|
||||
|
||||
describe('host 测试', () => {
|
||||
let editor: Editor;
|
||||
let designer: Designer;
|
||||
beforeEach(() => {
|
||||
designer = new Designer({ editor });
|
||||
});
|
||||
afterEach(() => {
|
||||
designer._componentMetasMap.clear();
|
||||
designer = null;
|
||||
let project: Project;
|
||||
let doc: DocumentModel;
|
||||
|
||||
beforeAll(() => {
|
||||
editor = new Editor();
|
||||
!globalContext.has(Editor) && globalContext.register(editor, Editor);
|
||||
});
|
||||
|
||||
it('基础方法测试', async () => {
|
||||
const host = new BuiltinSimulatorHost(designer.project);
|
||||
expect(host.currentDocument).toBe(designer.project.currentDocument);
|
||||
expect(host.renderEnv).toBe('default');
|
||||
expect(host.device).toBe('default');
|
||||
expect(host.deviceClassName).toBeUndefined();
|
||||
host.setProps({
|
||||
renderEnv: 'rax',
|
||||
device: 'mobile',
|
||||
deviceClassName: 'mobile-rocks',
|
||||
componentsAsset: [{
|
||||
beforeEach(() => {
|
||||
designer = new Designer({ editor });
|
||||
project = designer.project;
|
||||
doc = project.createDocument(formSchema);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
project.unload();
|
||||
project.mountSimulator(undefined);
|
||||
designer._componentMetasMap.clear();
|
||||
designer.purge();
|
||||
designer = null;
|
||||
project = null;
|
||||
});
|
||||
|
||||
describe('基础方法测试', () => {
|
||||
it('setProps / get / set', async () => {
|
||||
const host = new BuiltinSimulatorHost(designer.project);
|
||||
expect(host.currentDocument).toBe(designer.project.currentDocument);
|
||||
expect(host.renderEnv).toBe('default');
|
||||
expect(host.device).toBe('default');
|
||||
expect(host.deviceClassName).toBeUndefined();
|
||||
expect(host.requestHandlersMap).toBeNull();
|
||||
host.setProps({
|
||||
renderEnv: 'rax',
|
||||
device: 'mobile',
|
||||
deviceClassName: 'mobile-rocks',
|
||||
componentsAsset: [{
|
||||
type: AssetType.JSText,
|
||||
content: 'console.log(1)',
|
||||
}, {
|
||||
type: AssetType.JSUrl,
|
||||
content: '//path/to/js',
|
||||
}],
|
||||
theme: {
|
||||
type: AssetType.CSSText,
|
||||
content: '.theme {font-size: 50px;}',
|
||||
},
|
||||
requestHandlersMap: {},
|
||||
});
|
||||
expect(host.renderEnv).toBe('rax');
|
||||
expect(host.device).toBe('mobile');
|
||||
expect(host.deviceClassName).toBe('mobile-rocks');
|
||||
expect(host.componentsAsset).toEqual([{
|
||||
type: AssetType.JSText,
|
||||
content: 'console.log(1)',
|
||||
}, {
|
||||
type: AssetType.JSUrl,
|
||||
content: '//path/to/js',
|
||||
}],
|
||||
theme: {
|
||||
}]);
|
||||
expect(host.theme).toEqual({
|
||||
type: AssetType.CSSText,
|
||||
content: '.theme {font-size: 50px;}',
|
||||
}
|
||||
});
|
||||
expect(host.renderEnv).toBe('rax');
|
||||
expect(host.device).toBe('mobile');
|
||||
expect(host.deviceClassName).toBe('mobile-rocks');
|
||||
expect(host.componentsAsset).toEqual([{
|
||||
type: AssetType.JSText,
|
||||
content: 'console.log(1)',
|
||||
}, {
|
||||
type: AssetType.JSUrl,
|
||||
content: '//path/to/js',
|
||||
}]);
|
||||
expect(host.theme).toEqual({
|
||||
type: AssetType.CSSText,
|
||||
content: '.theme {font-size: 50px;}',
|
||||
});
|
||||
expect(host.componentsMap).toBe(designer.componentsMap);
|
||||
});
|
||||
expect(host.componentsMap).toBe(designer.componentsMap);
|
||||
expect(host.requestHandlersMap).toEqual({});
|
||||
|
||||
host.set('renderEnv', 'vue');
|
||||
expect(host.renderEnv).toBe('vue');
|
||||
host.set('renderEnv', 'vue');
|
||||
expect(host.renderEnv).toBe('vue');
|
||||
|
||||
expect(host.getComponentContext).toThrow('Method not implemented.');
|
||||
expect(host.getComponentContext).toThrow('Method not implemented.');
|
||||
});
|
||||
|
||||
it('connect', () => {});
|
||||
it('mountViewport', () => {});
|
||||
it('mountContentFrame', () => {});
|
||||
it('autorun', () => {});
|
||||
it('purge', () => {});
|
||||
|
||||
});
|
||||
|
||||
describe('事件测试', () => {
|
||||
it('setupDragAndClick', () => {
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
it('事件测试', async () => {
|
||||
@ -0,0 +1,60 @@
|
||||
import ResourceConsumer from '../../src/builtin-simulator/resource-consumer';
|
||||
import { delayObxTick, delay } from '../utils';
|
||||
|
||||
it('ResourceConsumer 测试,先消费再监听', async () => {
|
||||
const con = new ResourceConsumer(() => ({ a: 1, b: 2}));
|
||||
|
||||
const mockFn = jest.fn();
|
||||
con.consume((data) => {
|
||||
mockFn(data);
|
||||
});
|
||||
|
||||
await delay(1000);
|
||||
|
||||
expect(mockFn).toHaveBeenCalledWith({ a: 1, b: 2 });
|
||||
con.consume(() => {});
|
||||
|
||||
await con.waitFirstConsume();
|
||||
|
||||
con.dispose();
|
||||
});
|
||||
|
||||
it('ResourceConsumer 测试,先消费再监听,isSimulatorRenderer', async () => {
|
||||
const mockFn = jest.fn();
|
||||
const con = new ResourceConsumer(() => ({ a: 1, b: 2}), () => {
|
||||
const o = { a: 3, b: 4 };
|
||||
mockFn(o)
|
||||
return o;
|
||||
});
|
||||
|
||||
con.consume({ isSimulatorRenderer: true });
|
||||
|
||||
await delay(1000);
|
||||
|
||||
expect(mockFn).toHaveBeenCalledWith({ a: 3, b: 4 });
|
||||
con.consume(() => {});
|
||||
|
||||
await con.waitFirstConsume();
|
||||
});
|
||||
|
||||
it('ResourceConsumer 测试,先消费再监听,isSimulatorRenderer,没有 consume', async () => {
|
||||
const mockFn = jest.fn();
|
||||
const con = new ResourceConsumer(() => ({ a: 1, b: 2}));
|
||||
|
||||
con.consume({ isSimulatorRenderer: true });
|
||||
});
|
||||
|
||||
it('ResourceConsumer 测试,先监听再消费', async () => {
|
||||
const con = new ResourceConsumer(() => ({ a: 1, b: 2}));
|
||||
|
||||
con.waitFirstConsume();
|
||||
|
||||
const mockFn = jest.fn();
|
||||
con.consume((data) => {
|
||||
mockFn(data);
|
||||
});
|
||||
|
||||
await delay(1000);
|
||||
|
||||
expect(mockFn).toHaveBeenCalledWith({ a: 1, b: 2 });
|
||||
});
|
||||
@ -1,5 +1,5 @@
|
||||
import '../fixtures/window';
|
||||
import { parseMetadata } from '../../src/builtin-simulator/utils/parse-metadata';
|
||||
import '../../fixtures/window';
|
||||
import { parseMetadata } from '../../../src/builtin-simulator/utils/parse-metadata';
|
||||
|
||||
describe('parseMetadata', () => {
|
||||
it('parseMetadata', async () => {
|
||||
@ -7,7 +7,7 @@ import {
|
||||
removeVersion,
|
||||
resolveAbsoluatePath,
|
||||
joinPath,
|
||||
} from '../../src/builtin-simulator/utils/path';
|
||||
} from '../../../src/builtin-simulator/utils/path';
|
||||
|
||||
describe('builtin-simulator/utils/path 测试', () => {
|
||||
it('isPackagePath', () => {
|
||||
@ -1,5 +1,5 @@
|
||||
import '../fixtures/disable-raf';
|
||||
import { throttle } from '../../src/builtin-simulator/utils/throttle';
|
||||
import '../../fixtures/disable-raf';
|
||||
import { throttle } from '../../../src/builtin-simulator/utils/throttle';
|
||||
|
||||
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
|
||||
|
||||
180
packages/designer/tests/builtin-simulator/viewport.test.ts
Normal file
180
packages/designer/tests/builtin-simulator/viewport.test.ts
Normal file
@ -0,0 +1,180 @@
|
||||
import '../fixtures/window';
|
||||
import { getMockWindow, set } from '../utils';
|
||||
import { Editor, globalContext } from '@ali/lowcode-editor-core';
|
||||
import { Project } from '../../src/project/project';
|
||||
import { DocumentModel } from '../../src/document/document-model';
|
||||
import Viewport from '../../src/builtin-simulator/viewport';
|
||||
import { Designer } from '../../src/designer/designer';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { getMockElement, delay } from '../utils';
|
||||
|
||||
describe('Viewport 测试', () => {
|
||||
let editor: Editor;
|
||||
let designer: Designer;
|
||||
let project: Project;
|
||||
let doc: DocumentModel;
|
||||
let viewport: Viewport;
|
||||
let viewportElem;
|
||||
|
||||
beforeAll(() => {
|
||||
editor = new Editor();
|
||||
!globalContext.has(Editor) && globalContext.register(editor, Editor);
|
||||
|
||||
window.DOMRect = class {
|
||||
constructor(top, left, width, height) {
|
||||
return { top, left, width, height };
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
designer = new Designer({ editor });
|
||||
project = designer.project;
|
||||
// doc = project.createDocument(formSchema);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
project.unload();
|
||||
// project.mountSimulator(undefined);
|
||||
designer.purge();
|
||||
designer = null;
|
||||
project = null;
|
||||
viewport = null;
|
||||
});
|
||||
|
||||
it('基本函数测试', async () => {
|
||||
const rect = {
|
||||
width: 500,
|
||||
height: 500,
|
||||
top: 100,
|
||||
bottom: 500,
|
||||
left: 100,
|
||||
right: 500,
|
||||
};
|
||||
viewportElem = getMockElement('div', rect);
|
||||
viewport = new Viewport();
|
||||
viewport.mount();
|
||||
expect(viewport.viewportElement).toBeUndefined();
|
||||
expect(viewport.width).toBe(1000);
|
||||
expect(viewport.height).toBe(600);
|
||||
expect(viewport.toGlobalPoint({ left: 0, top: 0 })).toEqual({ left: 0, top: 0 });
|
||||
expect(viewport.toLocalPoint({ left: 0, top: 0 })).toEqual({ left: 0, top: 0 });
|
||||
|
||||
viewport.mount(viewportElem);
|
||||
expect(viewport.viewportElement).toBe(viewportElem);
|
||||
|
||||
expect(viewport.bounds).toEqual(rect);
|
||||
expect(viewport.contentBounds).toEqual({ top: 0, left: 0, width: 500, height: 500 });
|
||||
expect(viewport.rect).toEqual(rect);
|
||||
|
||||
expect(viewport.width).toBe(500);
|
||||
expect(viewport.contentWidth).toBe('100%');
|
||||
expect(viewport.height).toBe(500);
|
||||
expect(viewport.contentHeight).toBe('100%');
|
||||
|
||||
await delay(100);
|
||||
viewportElem.setWidth(300);
|
||||
viewport.width = 300;
|
||||
expect(viewport.width).toBe(300);
|
||||
|
||||
await delay(100);
|
||||
viewportElem.setHeight(300);
|
||||
viewport.height = 300;
|
||||
expect(viewport.height).toBe(300);
|
||||
|
||||
viewport.contentWidth = 200;
|
||||
expect(viewport.contentWidth).toBe(200);
|
||||
|
||||
viewport.contentHeight = 200;
|
||||
expect(viewport.contentHeight).toBe(200);
|
||||
});
|
||||
|
||||
it('scale', () => {
|
||||
const rect = {
|
||||
width: 500,
|
||||
height: 500,
|
||||
top: 100,
|
||||
bottom: 500,
|
||||
left: 100,
|
||||
right: 500,
|
||||
};
|
||||
viewportElem = getMockElement('div', rect);
|
||||
viewport = new Viewport();
|
||||
viewport.mount(viewportElem);
|
||||
|
||||
expect(viewport.scale).toBe(1);
|
||||
viewport.scale = 2;
|
||||
expect(viewport.scale).toBe(2);
|
||||
|
||||
expect(viewport.contentWidth).toBe(500 / 2);
|
||||
expect(viewport.contentHeight).toBe(500 / 2);
|
||||
|
||||
viewport.width = 300;
|
||||
viewportElem.setWidth(300);
|
||||
expect(viewport.contentWidth).toBe(300 / 2);
|
||||
|
||||
viewport.height = 300;
|
||||
viewportElem.setHeight(300);
|
||||
expect(viewport.contentHeight).toBe(300 / 2);
|
||||
|
||||
expect(() => viewport.scale = NaN).toThrow();
|
||||
expect(() => viewport.scale = -1).toThrow();
|
||||
});
|
||||
|
||||
it('setScrollTarget / scrollTarget / scrolling', async () => {
|
||||
const rect = {
|
||||
width: 500,
|
||||
height: 500,
|
||||
top: 100,
|
||||
bottom: 500,
|
||||
left: 100,
|
||||
right: 500,
|
||||
};
|
||||
viewportElem = getMockElement('div', rect);
|
||||
viewport = new Viewport();
|
||||
viewport.mount(viewportElem);
|
||||
|
||||
const mockWindow = getMockWindow();
|
||||
viewport.setScrollTarget(mockWindow);
|
||||
// TODO: 待 mock
|
||||
viewport.scrollTarget;
|
||||
// expect(viewport.scrollTarget).toBe(mockWindow);
|
||||
|
||||
// mock scrollTarget
|
||||
// viewport._scrollTarget = { left: 0, top: 0 };
|
||||
// viewport._scrollTarget.left = 123;
|
||||
// viewport._scrollTarget.top = 1234;
|
||||
mockWindow.triggerEventListener('scroll');
|
||||
expect(viewport.scrolling).toBeTruthy();
|
||||
// TODO: 待 mock
|
||||
viewport.scrollX;
|
||||
viewport.scrollY;
|
||||
// expect(viewport.scrollX).toBe(123);
|
||||
// expect(viewport.scrollY).toBe(1234);
|
||||
await delay(100);
|
||||
expect(viewport.scrolling).toBeFalsy();
|
||||
|
||||
mockWindow.triggerEventListener('resize');
|
||||
});
|
||||
|
||||
it('toGlobalPoint / toLocalPoint', () => {
|
||||
const rect = {
|
||||
width: 500,
|
||||
height: 500,
|
||||
top: 100,
|
||||
bottom: 500,
|
||||
left: 100,
|
||||
right: 500,
|
||||
};
|
||||
viewportElem = getMockElement('div', rect);
|
||||
viewport = new Viewport();
|
||||
viewport.mount(viewportElem);
|
||||
|
||||
expect(viewport.toGlobalPoint({ clientX: 100, clientY: 100 })).toEqual({ clientX: 200, clientY: 200 });
|
||||
expect(viewport.toLocalPoint({ clientX: 200, clientY: 200 })).toEqual({ clientX: 100, clientY: 100 });
|
||||
|
||||
viewport.scale = 2;
|
||||
expect(viewport.toGlobalPoint({ clientX: 100, clientY: 100 })).toEqual({ clientX: 300, clientY: 300 });
|
||||
expect(viewport.toLocalPoint({ clientX: 300, clientY: 300 })).toEqual({ clientX: 100, clientY: 100 });
|
||||
});
|
||||
});
|
||||
40
packages/designer/tests/designer/active-tracker.test.ts
Normal file
40
packages/designer/tests/designer/active-tracker.test.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { ActiveTracker } from '../../src/designer/active-tracker';
|
||||
|
||||
it('ActiveTracker 测试,Node', () => {
|
||||
const tracker = new ActiveTracker();
|
||||
|
||||
const mockFn = jest.fn();
|
||||
const mockNode = { isNode: true };
|
||||
const off = tracker.onChange(mockFn);
|
||||
|
||||
tracker.track(mockNode);
|
||||
expect(mockFn).toHaveBeenCalledWith({ node: mockNode });
|
||||
|
||||
expect(tracker.currentNode).toBe(mockNode);
|
||||
|
||||
off();
|
||||
mockFn.mockClear();
|
||||
tracker.track(mockNode);
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('ActiveTracker 测试,ActiveTarget', () => {
|
||||
const tracker = new ActiveTracker();
|
||||
|
||||
const mockFn = jest.fn();
|
||||
const mockNode = { isNode: true };
|
||||
const off = tracker.onChange(mockFn);
|
||||
const mockTarget = { node: mockNode, detail: { isDetail: true }, instance: { isInstance: true } };
|
||||
|
||||
tracker.track(mockTarget);
|
||||
expect(mockFn).toHaveBeenCalledWith(mockTarget);
|
||||
|
||||
expect(tracker.currentNode).toBe(mockNode);
|
||||
expect(tracker.detail).toEqual({ isDetail: true });
|
||||
expect(tracker.instance).toEqual({ isInstance: true });
|
||||
|
||||
off();
|
||||
mockFn.mockClear();
|
||||
tracker.track(mockNode);
|
||||
expect(mockFn).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -1,3 +1,4 @@
|
||||
jest.mock('@ali/lowcode-utils');
|
||||
import set from 'lodash/set';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import '../fixtures/window';
|
||||
@ -6,6 +7,8 @@ import { Designer } from '../../src/designer/designer';
|
||||
import { Project } from '../../src/project/project';
|
||||
import formSchema from '../fixtures/schema/form';
|
||||
import '../../src/designer/builtin-hotkey';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { isFormEvent } from '@ali/lowcode-utils';
|
||||
|
||||
const editor = new Editor();
|
||||
|
||||
@ -28,8 +31,7 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbj')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 39 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 39 });
|
||||
|
||||
expect(designer.currentSelection?.selected.includes('node_k1ow3cbl')).toBeTruthy();
|
||||
});
|
||||
@ -38,8 +40,7 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbl')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 37 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 37 });
|
||||
|
||||
expect(designer.currentSelection?.selected.includes('node_k1ow3cbj')).toBeTruthy();
|
||||
});
|
||||
@ -48,8 +49,7 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbl')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 40 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 40 });
|
||||
|
||||
expect(designer.currentSelection?.selected.includes('node_k1ow3cbo')).toBeTruthy();
|
||||
});
|
||||
@ -58,8 +58,7 @@ describe('快捷键测试', () => {
|
||||
const secondCardNode = designer.currentDocument?.getNode('node_k1ow3cbm')!;
|
||||
secondCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 38 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 38 });
|
||||
|
||||
expect(designer.currentSelection?.selected.includes('node_k1ow3cbl')).toBeTruthy();
|
||||
});
|
||||
@ -69,8 +68,7 @@ describe('快捷键测试', () => {
|
||||
const firstButtonNode = designer.currentDocument?.getNode('node_k1ow3cbn')!;
|
||||
firstButtonNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 39, altKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 39, altKey: true });
|
||||
|
||||
expect(firstButtonNode.prevSibling?.getId()).toBe('node_k1ow3cbp');
|
||||
});
|
||||
@ -80,8 +78,7 @@ describe('快捷键测试', () => {
|
||||
const secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
secondButtonNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 37, altKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 37, altKey: true });
|
||||
|
||||
expect(secondButtonNode.nextSibling?.getId()).toBe('node_k1ow3cbn');
|
||||
});
|
||||
@ -91,8 +88,7 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 38, altKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 38, altKey: true });
|
||||
});
|
||||
|
||||
// 将节点移入到兄弟节点中
|
||||
@ -100,8 +96,7 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 40, altKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 40, altKey: true });
|
||||
});
|
||||
|
||||
// 撤销
|
||||
@ -114,8 +109,7 @@ describe('快捷键测试', () => {
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 90, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 90, metaKey: true });
|
||||
|
||||
// 重新获取一次节点,因为 documentModel.import 是全画布刷新
|
||||
secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
@ -132,8 +126,7 @@ describe('快捷键测试', () => {
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 90, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 90, metaKey: true });
|
||||
|
||||
// 重新获取一次节点,因为 documentModel.import 是全画布刷新
|
||||
secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
@ -141,8 +134,7 @@ describe('快捷键测试', () => {
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
event = new KeyboardEvent('keydown', { keyCode: 89, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 89, metaKey: true });
|
||||
|
||||
// 重新获取一次节点,因为 documentModel.import 是全画布刷新
|
||||
secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
@ -153,19 +145,16 @@ describe('快捷键测试', () => {
|
||||
const firstCardNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
firstCardNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 67, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 67, metaKey: true });
|
||||
});
|
||||
|
||||
it('command + v', async () => {
|
||||
const secondButtonNode = designer.currentDocument?.getNode('node_k1ow3cbp')!;
|
||||
secondButtonNode.select();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 67, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 67, metaKey: true });
|
||||
|
||||
event = new KeyboardEvent('keydown', { keyCode: 86, metaKey: true });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 86, metaKey: true });
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, 1000));
|
||||
|
||||
@ -180,8 +169,7 @@ describe('快捷键测试', () => {
|
||||
|
||||
expect(designer.currentSelection!.selected.includes('node_k1ow3cbp')).toBeTruthy();
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 27 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 27 });
|
||||
|
||||
expect(designer.currentSelection!.selected.length).toBe(0);
|
||||
});
|
||||
@ -194,9 +182,110 @@ describe('快捷键测试', () => {
|
||||
|
||||
expect(secondButtonNode.prevSibling.id).toBe('node_k1ow3cbn');
|
||||
|
||||
let event = new KeyboardEvent('keydown', { keyCode: 46 });
|
||||
document.dispatchEvent(event);
|
||||
fireEvent.keyDown(document, { keyCode: 46 });
|
||||
|
||||
expect(secondButtonNode.prevSibling).toBeNull();
|
||||
});
|
||||
|
||||
|
||||
describe('非正常分支', () => {
|
||||
it('liveEditing mode', () => {
|
||||
designer.project.mountSimulator({
|
||||
liveEditing: {
|
||||
editing: {},
|
||||
},
|
||||
});
|
||||
editor.set('designer', designer);
|
||||
designer.currentDocument?.selection.select('page');
|
||||
// nothing happened
|
||||
fireEvent.keyDown(document, { keyCode: 39 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 37 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 40 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 38 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 39, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 37, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 40, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 38, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 90, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 89, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 67, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 86, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 27 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 46 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
});
|
||||
it('isFormEvent: true', () => {
|
||||
designer.currentDocument?.selection.select('page');
|
||||
// nothing happened
|
||||
isFormEvent.mockReturnValue(true);
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 39 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 37 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 40 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 38 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 39, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 37, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 40, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 38, altKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 90, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 89, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 67, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 86, metaKey: true });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 27 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
|
||||
fireEvent.keyDown(document, { keyCode: 46 });
|
||||
expect(designer.currentDocument?.selection.selected[0]).toBe('page');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
404
packages/designer/tests/designer/designer.test.ts
Normal file
404
packages/designer/tests/designer/designer.test.ts
Normal file
@ -0,0 +1,404 @@
|
||||
import '../fixtures/window';
|
||||
import { Editor, globalContext } from '@ali/lowcode-editor-core';
|
||||
import { Project } from '../../src/project/project';
|
||||
import { DocumentModel } from '../../src/document/document-model';
|
||||
import { Designer } from '../../src/designer/designer';
|
||||
import { Dragon, DragObjectType } from '../../src/designer/dragon';
|
||||
import { TransformStage } from '../../src/document/node/transform-stage';
|
||||
import formSchema from '../fixtures/schema/form';
|
||||
import buttonMetadata from '../fixtures/component-metadata/button';
|
||||
import pageMetadata from '../fixtures/component-metadata/page';
|
||||
import divMetadata from '../fixtures/component-metadata/div';
|
||||
import { delayObxTick } from '../utils';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
|
||||
describe('Designer 测试', () => {
|
||||
let editor: Editor;
|
||||
let designer: Designer;
|
||||
let project: Project;
|
||||
let doc: DocumentModel;
|
||||
let dragon: Dragon;
|
||||
|
||||
beforeAll(() => {
|
||||
editor = new Editor();
|
||||
!globalContext.has(Editor) && globalContext.register(editor, Editor);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
designer = new Designer({ editor });
|
||||
project = designer.project;
|
||||
doc = project.createDocument(formSchema);
|
||||
dragon = new Dragon(designer);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
project.unload();
|
||||
project.mountSimulator(undefined);
|
||||
designer.purge();
|
||||
designer = null;
|
||||
project = null;
|
||||
dragon = null;
|
||||
});
|
||||
|
||||
describe('onDragstart / onDrag / onDragend', () => {
|
||||
it('DragObjectType.Node', () => {
|
||||
const dragStartMockFn = jest.fn();
|
||||
const dragMockFn = jest.fn();
|
||||
const dragEndMockFn = jest.fn();
|
||||
const dragStartMockFn2 = jest.fn();
|
||||
const dragMockFn2 = jest.fn();
|
||||
const dragEndMockFn2 = jest.fn();
|
||||
|
||||
const designer = new Designer({
|
||||
editor,
|
||||
onDragstart: dragStartMockFn,
|
||||
onDrag: dragMockFn,
|
||||
onDragend: dragEndMockFn,
|
||||
});
|
||||
editor.on('designer.dragstart', dragStartMockFn2);
|
||||
editor.on('designer.drag', dragMockFn2);
|
||||
editor.on('designer.dragend', dragEndMockFn2);
|
||||
const dragon = designer.dragon;
|
||||
|
||||
dragon.boost(
|
||||
{
|
||||
type: DragObjectType.Node,
|
||||
nodes: [doc.getNode('node_k1ow3cbn')],
|
||||
},
|
||||
new MouseEvent('mousedown', { clientX: 100, clientY: 100 }),
|
||||
);
|
||||
|
||||
fireEvent.mouseMove(document, { clientX: 108, clientY: 108 });
|
||||
expect(dragStartMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragStartMockFn2).toHaveBeenCalledTimes(1);
|
||||
expect(dragMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragMockFn2).toHaveBeenCalledTimes(1);
|
||||
|
||||
fireEvent.mouseMove(document, { clientX: 110, clientY: 110 });
|
||||
expect(dragMockFn).toHaveBeenCalledTimes(2);
|
||||
expect(dragMockFn2).toHaveBeenCalledTimes(2);
|
||||
|
||||
setMockDropLocation();
|
||||
fireEvent.mouseUp(document, { clientX: 118, clientY: 118 });
|
||||
|
||||
expect(dragEndMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragEndMockFn2).toHaveBeenCalledTimes(1);
|
||||
|
||||
function setMockDropLocation() {
|
||||
const mockTarget = {
|
||||
document: doc,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
insert() {},
|
||||
},
|
||||
};
|
||||
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
|
||||
return designer.createLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it('DragObjectType.NodeData', () => {
|
||||
const dragStartMockFn = jest.fn();
|
||||
const dragMockFn = jest.fn();
|
||||
const dragEndMockFn = jest.fn();
|
||||
const dragStartMockFn2 = jest.fn();
|
||||
const dragMockFn2 = jest.fn();
|
||||
const dragEndMockFn2 = jest.fn();
|
||||
|
||||
const designer = new Designer({
|
||||
editor,
|
||||
onDragstart: dragStartMockFn,
|
||||
onDrag: dragMockFn,
|
||||
onDragend: dragEndMockFn,
|
||||
});
|
||||
editor.on('designer.dragstart', dragStartMockFn2);
|
||||
editor.on('designer.drag', dragMockFn2);
|
||||
editor.on('designer.dragend', dragEndMockFn2);
|
||||
const dragon = designer.dragon;
|
||||
|
||||
dragon.boost(
|
||||
{
|
||||
type: DragObjectType.NodeData,
|
||||
data: [{
|
||||
componentName: 'Button',
|
||||
}],
|
||||
},
|
||||
new MouseEvent('mousedown', { clientX: 100, clientY: 100 }),
|
||||
);
|
||||
|
||||
fireEvent.mouseMove(document, { clientX: 108, clientY: 108 });
|
||||
expect(dragStartMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragStartMockFn2).toHaveBeenCalledTimes(1);
|
||||
expect(dragMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragMockFn2).toHaveBeenCalledTimes(1);
|
||||
|
||||
fireEvent.mouseMove(document, { clientX: 110, clientY: 110 });
|
||||
expect(dragMockFn).toHaveBeenCalledTimes(2);
|
||||
expect(dragMockFn2).toHaveBeenCalledTimes(2);
|
||||
|
||||
setMockDropLocation();
|
||||
fireEvent.mouseUp(document, { clientX: 118, clientY: 118 });
|
||||
|
||||
expect(dragEndMockFn).toHaveBeenCalledTimes(1);
|
||||
expect(dragEndMockFn2).toHaveBeenCalledTimes(1);
|
||||
|
||||
function setMockDropLocation() {
|
||||
const mockTarget = {
|
||||
document: doc,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
insert() {},
|
||||
},
|
||||
};
|
||||
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
|
||||
return designer.createLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('addPropsReducer / transformProps', () => {
|
||||
// 没有相应的 reducer
|
||||
expect(designer.transformProps({ num: 1 }, TransformStage.Init)).toEqual({ num: 1 });
|
||||
// props 是数组
|
||||
expect(designer.transformProps([{ num: 1 }], TransformStage.Init)).toEqual([{ num: 1 }]);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Init);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Init);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Clone);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Serilize);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Render);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Save);
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
props.num = props.num + 1;
|
||||
return props;
|
||||
}, TransformStage.Upgrade);
|
||||
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Init)).toEqual({ num: 3 });
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Clone)).toEqual({ num: 2 });
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Serilize)).toEqual({ num: 2 });
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Render)).toEqual({ num: 2 });
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Save)).toEqual({ num: 2 });
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Upgrade)).toEqual({ num: 2 });
|
||||
|
||||
designer.addPropsReducer((props, node) => {
|
||||
throw new Error('calculate error');
|
||||
}, TransformStage.Upgrade);
|
||||
expect(designer.transformProps({ num: 1 }, {}, TransformStage.Upgrade)).toEqual({ num: 2 });
|
||||
});
|
||||
|
||||
it('setProps', () => {
|
||||
// 第一次设置 props
|
||||
const initialProps = {
|
||||
simulatorComponent: { isSimulatorComp: true },
|
||||
simulatorProps: { designMode: 'design' },
|
||||
suspensed: true,
|
||||
componentMetadatas: [buttonMetadata, divMetadata],
|
||||
};
|
||||
designer = new Designer({ editor, ...initialProps });
|
||||
|
||||
expect(designer.simulatorComponent).toEqual({ isSimulatorComp: true });
|
||||
expect(designer.simulatorProps).toEqual({ designMode: 'design' });
|
||||
expect(designer.suspensed).toBeTruthy();
|
||||
expect(designer._componentMetasMap.has('Div')).toBeTruthy();
|
||||
expect(designer._componentMetasMap.has('Button')).toBeTruthy();
|
||||
const { editor: editorFromDesigner, ...others } = designer.props;
|
||||
expect(others).toEqual(initialProps);
|
||||
expect(designer.get('simulatorProps')).toEqual({ designMode: 'design' });
|
||||
expect(designer.get('suspensed')).toBeTruthy();
|
||||
expect(designer.get('xxx')).toBeUndefined();
|
||||
|
||||
// 第二次设置 props
|
||||
const updatedProps = {
|
||||
simulatorComponent: { isSimulatorComp2: true },
|
||||
simulatorProps: { designMode: 'live' },
|
||||
suspensed: false,
|
||||
componentMetadatas: [buttonMetadata],
|
||||
};
|
||||
designer.setProps(updatedProps);
|
||||
|
||||
expect(designer.simulatorComponent).toEqual({ isSimulatorComp2: true });
|
||||
expect(designer.simulatorProps).toEqual({ designMode: 'live' });
|
||||
expect(designer.suspensed).toBeFalsy();
|
||||
expect(designer._componentMetasMap.has('Button')).toBeTruthy();
|
||||
expect(designer._componentMetasMap.has('Div')).toBeTruthy();
|
||||
const { editor: editorFromDesigner2, ...others2 } = designer.props;
|
||||
expect(others2).toEqual(updatedProps);
|
||||
});
|
||||
|
||||
describe('getSuitableInsertion', () => {
|
||||
it('没有 currentDocument', () => {
|
||||
project.unload();
|
||||
expect(designer.getSuitableInsertion({})).toBeNull();
|
||||
});
|
||||
|
||||
it('有选中节点,isContainer && 允许放子节点', () => {
|
||||
designer.createComponentMeta(divMetadata);
|
||||
designer.createComponentMeta(buttonMetadata);
|
||||
designer.currentSelection?.select('node_k1ow3cbo');
|
||||
const { target, index } = designer.getSuitableInsertion(
|
||||
doc.createNode({ componentName: 'Button' }),
|
||||
);
|
||||
expect(target).toBe(doc.getNode('node_k1ow3cbo'));
|
||||
expect(index).toBeUndefined();
|
||||
});
|
||||
|
||||
it('有选中节点,不是 isContainer', () => {
|
||||
designer.createComponentMeta(divMetadata);
|
||||
designer.createComponentMeta(buttonMetadata);
|
||||
designer.currentSelection?.select('node_k1ow3cbn');
|
||||
const { target, index } = designer.getSuitableInsertion(
|
||||
doc.createNode({ componentName: 'Button' }),
|
||||
);
|
||||
expect(target).toBe(doc.getNode('node_k1ow3cbo'));
|
||||
expect(index).toBe(1);
|
||||
});
|
||||
|
||||
it('无选中节点', () => {
|
||||
designer.createComponentMeta(pageMetadata);
|
||||
const { target, index } = designer.getSuitableInsertion(
|
||||
doc.createNode({ componentName: 'Button' }),
|
||||
);
|
||||
expect(target).toBe(doc.getNode('page'));
|
||||
expect(index).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
it('createLocation / clearLocation', () => {
|
||||
const mockTarget = {
|
||||
document: doc,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
insert() {},
|
||||
},
|
||||
};
|
||||
const mockDetail = { type: 'Children', index: 1, near: { node: { x: 1 } } };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
|
||||
const loc = designer.createLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(designer.dropLocation).toBe(loc);
|
||||
|
||||
const doc2 = project.createDocument({ componentName: 'Page' });
|
||||
designer.createLocation({
|
||||
target: {
|
||||
document: doc2,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
insert() {},
|
||||
},
|
||||
},
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
designer.clearLocation();
|
||||
expect(designer.dropLocation).toBeUndefined();
|
||||
});
|
||||
|
||||
it('autorun', async () => {
|
||||
const mockFn = jest.fn();
|
||||
designer.autorun(() => {
|
||||
mockFn();
|
||||
}, true);
|
||||
|
||||
await delayObxTick();
|
||||
|
||||
expect(mockFn).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('suspensed', () => {
|
||||
designer.suspensed = true;
|
||||
expect(designer.suspensed).toBeTruthy();
|
||||
designer.suspensed = false;
|
||||
expect(designer.suspensed).toBeFalsy();
|
||||
});
|
||||
|
||||
it('schema', () => {
|
||||
// TODO: matchSnapshot
|
||||
designer.schema;
|
||||
designer.setSchema({
|
||||
componentsTree: [
|
||||
{
|
||||
componentName: 'Page',
|
||||
props: {},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('createOffsetObserver / clearOobxList / touchOffsetObserver', () => {
|
||||
project.mountSimulator({
|
||||
computeComponentInstanceRect() {},
|
||||
});
|
||||
designer.createOffsetObserver({ node: doc.getNode('page'), instance: {} });
|
||||
expect(designer.oobxList).toHaveLength(1);
|
||||
designer.createOffsetObserver({ node: doc.getNode('page'), instance: {} });
|
||||
expect(designer.oobxList).toHaveLength(2);
|
||||
|
||||
designer.clearOobxList(true);
|
||||
expect(designer.oobxList).toHaveLength(0);
|
||||
|
||||
const obx = designer.createOffsetObserver({ node: doc.getNode('page'), instance: {} });
|
||||
obx.pid = 'xxx';
|
||||
obx.compute = () => {};
|
||||
expect(designer.oobxList).toHaveLength(1);
|
||||
|
||||
designer.touchOffsetObserver();
|
||||
expect(designer.oobxList).toHaveLength(1);
|
||||
});
|
||||
});
|
||||
22
packages/designer/tests/designer/detecting.test.ts
Normal file
22
packages/designer/tests/designer/detecting.test.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { Detecting } from '../../src/designer/detecting';
|
||||
|
||||
it('Detecting 测试', () => {
|
||||
const detecting = new Detecting();
|
||||
|
||||
expect(detecting.enable).toBeTruthy();
|
||||
|
||||
const mockNode = { document };
|
||||
detecting.capture(mockNode);
|
||||
expect(detecting.current).toBe(mockNode);
|
||||
|
||||
detecting.release(mockNode);
|
||||
expect(detecting.current).toBeNull();
|
||||
|
||||
detecting.capture(mockNode);
|
||||
detecting.leave(document);
|
||||
expect(detecting.current).toBeNull();
|
||||
|
||||
detecting.capture(mockNode);
|
||||
detecting.enable = false;
|
||||
expect(detecting.current).toBeNull();
|
||||
});
|
||||
@ -30,7 +30,6 @@ import formMetadata from '../fixtures/component-metadata/form';
|
||||
import otherMeta from '../fixtures/component-metadata/other';
|
||||
import pageMetadata from '../fixtures/component-metadata/page';
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
import { clearScreenDown } from 'readline';
|
||||
|
||||
describe('Dragon 测试', () => {
|
||||
let editor: Editor;
|
||||
|
||||
196
packages/designer/tests/designer/location.test.ts
Normal file
196
packages/designer/tests/designer/location.test.ts
Normal file
@ -0,0 +1,196 @@
|
||||
import {
|
||||
DropLocation,
|
||||
isLocationData,
|
||||
isLocationChildrenDetail,
|
||||
isRowContainer,
|
||||
isChildInline,
|
||||
getRectTarget,
|
||||
isVerticalContainer,
|
||||
isVertical,
|
||||
getWindow,
|
||||
} from '../../src/designer/location';
|
||||
import { getMockElement } from '../utils';
|
||||
|
||||
describe('DropLocation 测试', () => {
|
||||
it('constructor', () => {
|
||||
const mockTarget = { document };
|
||||
const mockDetail = {};
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
const loc = new DropLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(loc.getContainer()).toBe(mockTarget);
|
||||
expect(loc.document).toBe(document);
|
||||
expect(loc.target).toBe(mockTarget);
|
||||
expect(loc.detail).toBe(mockDetail);
|
||||
expect(loc.source).toBe(mockSource);
|
||||
expect(loc.event).toBe(mockEvent);
|
||||
|
||||
const mockEvent2 = { type: 'LocateEvent', data: [] };
|
||||
const loc2 = loc.clone(mockEvent2);
|
||||
expect(loc2.target).toBe(mockTarget);
|
||||
expect(loc2.detail).toBe(mockDetail);
|
||||
expect(loc2.source).toBe(mockSource);
|
||||
expect(loc2.event).toBe(mockEvent2);
|
||||
});
|
||||
|
||||
it('constructor, detail: undefined', () => {
|
||||
const mockTarget = { document };
|
||||
const mockDetail = undefined;
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
const loc = new DropLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(loc.getInsertion()).toBeNull();
|
||||
});
|
||||
|
||||
it('constructor, detail.type: Children, detail.index <= 0', () => {
|
||||
const mockTarget = { document };
|
||||
const mockDetail = { type: 'Children', index: -1 };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
const loc = new DropLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(loc.getInsertion()).toBeNull();
|
||||
});
|
||||
|
||||
it('constructor, detail.type: Children, detail.index > 0', () => {
|
||||
const mockTarget = {
|
||||
document,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockDetail = { type: 'Children', index: 1 };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
const loc = new DropLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(loc.getInsertion()).toBe(0);
|
||||
});
|
||||
|
||||
it('constructor, detail.type: Prop', () => {
|
||||
const mockTarget = {
|
||||
document,
|
||||
children: {
|
||||
get(x) {
|
||||
return x;
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockDetail = { type: 'Prop', index: 1, near: { node: { x: 1 } } };
|
||||
const mockSource = {};
|
||||
const mockEvent = { type: 'LocateEvent', nodes: [] };
|
||||
const loc = new DropLocation({
|
||||
target: mockTarget,
|
||||
detail: mockDetail,
|
||||
source: mockSource,
|
||||
event: mockEvent,
|
||||
});
|
||||
|
||||
expect(loc.getInsertion()).toEqual({ x: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
it('isLocationData', () => {
|
||||
expect(isLocationData({ target: {}, detail: {} })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('isLocationChildrenDetail', () => {
|
||||
expect(isLocationChildrenDetail({ type: 'Children' })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('isRowContainer', () => {
|
||||
expect(isRowContainer({ nodeType: Node.TEXT_NODE })).toBeTruthy();
|
||||
window.getComputedStyle = jest
|
||||
.fn(() => {
|
||||
return {
|
||||
getPropertyValue: (pName) => {
|
||||
return pName === 'display' ? 'flex' : 'row';
|
||||
}
|
||||
}
|
||||
})
|
||||
.mockImplementationOnce(() => {
|
||||
return {
|
||||
getPropertyValue: (pName) => {
|
||||
return pName === 'display' ? 'flex' : 'column';
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(isRowContainer(getMockElement('div'))).toBeFalsy();
|
||||
expect(isRowContainer(getMockElement('div'))).toBeTruthy();
|
||||
});
|
||||
|
||||
it('isChildInline', () => {
|
||||
window.getComputedStyle = jest
|
||||
.fn(() => {
|
||||
return {
|
||||
getPropertyValue: (pName) => {
|
||||
return pName === 'display' ? 'inline' : 'float';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
expect(isChildInline({ nodeType: Node.TEXT_NODE })).toBeTruthy();
|
||||
expect(isChildInline(getMockElement('div'))).toBeTruthy();
|
||||
});
|
||||
|
||||
it('getRectTarget', () => {
|
||||
expect(getRectTarget()).toBeNull();
|
||||
expect(getRectTarget({ computed: false })).toBeNull();
|
||||
expect(getRectTarget({ elements: [{}] })).toEqual({});
|
||||
});
|
||||
|
||||
it('isVerticalContainer', () => {
|
||||
window.getComputedStyle = jest
|
||||
.fn(() => {
|
||||
return {
|
||||
getPropertyValue: (pName) => {
|
||||
return pName === 'display' ? 'flex' : 'row';
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(isVerticalContainer()).toBeFalsy();
|
||||
expect(isVerticalContainer({ elements: [getMockElement('div')] })).toBeTruthy()
|
||||
});
|
||||
|
||||
it('isVertical', () => {
|
||||
expect(isVertical({ elements: [] })).toBeFalsy();
|
||||
expect(isVertical({ elements: [getMockElement('div')] })).toBeFalsy();
|
||||
window.getComputedStyle = jest
|
||||
.fn(() => {
|
||||
return {
|
||||
getPropertyValue: (pName) => {
|
||||
return pName === 'display' ? 'inline' : 'float';
|
||||
}
|
||||
}
|
||||
});
|
||||
expect(isVertical({ elements: [getMockElement('div')] })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('getWindow', () => {
|
||||
const mockElem = getMockElement('div');
|
||||
expect(getWindow(mockElem)).toBe(window);
|
||||
});
|
||||
@ -14,6 +14,7 @@ interface MockDocument extends Document {
|
||||
|
||||
|
||||
const eventsMap : Map<string, Set<Function>> = new Map<string, Set<Function>>();
|
||||
const mockRemoveAttribute = jest.fn();
|
||||
const mockAddEventListener = jest.fn((eventName: string, cb) => {
|
||||
if (!eventsMap.has(eventName)) {
|
||||
eventsMap.set(eventName, new Set([cb]));
|
||||
@ -45,6 +46,7 @@ const mockCreateElement = jest.fn((tagName) => {
|
||||
addEventListener: mockAddEventListener,
|
||||
removeEventListener: mockRemoveEventListener,
|
||||
triggerEventListener: mockTriggerEventListener,
|
||||
removeAttribute: mockRemoveAttribute,
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user