mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-11 18:42:56 +00:00
482 lines
13 KiB
TypeScript
482 lines
13 KiB
TypeScript
import '../fixtures/window';
|
||
import { Editor, globalContext } from '@alilc/lowcode-editor-core';
|
||
import {
|
||
AssetType,
|
||
} from '@alilc/lowcode-utils';
|
||
import {
|
||
DragObjectType,
|
||
} from '@alilc/lowcode-types';
|
||
import { Project } from '../../src/project/project';
|
||
import pageMetadata from '../fixtures/component-metadata/page';
|
||
import { Designer } from '../../src/designer/designer';
|
||
import { DocumentModel } from '../../src/document/document-model';
|
||
import formSchema from '../fixtures/schema/form';
|
||
import { getMockDocument, getMockWindow, getMockEvent, delayObxTick } from '../utils';
|
||
import { BuiltinSimulatorHost } from '../../src/builtin-simulator/host';
|
||
import { fireEvent } from '@testing-library/react';
|
||
import { shellModelFactory } from '../../../engine/src/modules/shell-model-factory';
|
||
|
||
describe('Host 测试', () => {
|
||
let editor: Editor;
|
||
let designer: Designer;
|
||
let project: Project;
|
||
let doc: DocumentModel;
|
||
let host: BuiltinSimulatorHost;
|
||
|
||
beforeAll(() => {
|
||
editor = new Editor();
|
||
!globalContext.has(Editor) && globalContext.register(editor, Editor);
|
||
});
|
||
|
||
beforeEach(() => {
|
||
designer = new Designer({ editor, shellModelFactory });
|
||
project = designer.project;
|
||
designer.createComponentMeta(pageMetadata);
|
||
doc = project.createDocument(formSchema);
|
||
host = new BuiltinSimulatorHost(designer.project);
|
||
});
|
||
|
||
afterEach(() => {
|
||
project.unload();
|
||
project.mountSimulator(undefined);
|
||
designer._componentMetasMap.clear();
|
||
designer.purge();
|
||
host.purge();
|
||
designer = null;
|
||
project = null;
|
||
host = null;
|
||
});
|
||
|
||
describe('基础方法测试', () => {
|
||
it('setProps / get / set', async () => {
|
||
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',
|
||
},
|
||
]);
|
||
expect(host.theme).toEqual({
|
||
type: AssetType.CSSText,
|
||
content: '.theme {font-size: 50px;}',
|
||
});
|
||
expect(host.componentsMap).toEqual(designer.componentsMap);
|
||
expect(host.requestHandlersMap).toEqual({});
|
||
|
||
host.set('renderEnv', 'vue');
|
||
expect(host.renderEnv).toBe('vue');
|
||
|
||
expect(host.getComponentContext).toThrow('Method not implemented.');
|
||
});
|
||
|
||
it('connect', () => {
|
||
const mockFn = jest.fn();
|
||
const mockRenderer = { isSimulatorRenderer: true };
|
||
host.connect(mockRenderer, mockFn);
|
||
expect(host.renderer).toEqual(mockRenderer);
|
||
|
||
// await delayObxTick();
|
||
expect(mockFn).toHaveBeenCalled();
|
||
});
|
||
|
||
it('mountViewport', () => {
|
||
const mockBounds = {
|
||
top: 10,
|
||
bottom: 100,
|
||
left: 10,
|
||
right: 100,
|
||
};
|
||
host.mountViewport({
|
||
getBoundingClientRect() {
|
||
return mockBounds;
|
||
},
|
||
});
|
||
expect(host.viewport.bounds).toEqual(mockBounds);
|
||
});
|
||
|
||
it('autorun', () => {
|
||
const mockFn = jest.fn();
|
||
host.autorun(mockFn);
|
||
expect(mockFn).toHaveBeenCalled();
|
||
});
|
||
|
||
it('purge', () => {
|
||
host.purge();
|
||
});
|
||
|
||
it('isEnter', () => {
|
||
const mockBounds = {
|
||
top: 10,
|
||
bottom: 100,
|
||
left: 10,
|
||
right: 100,
|
||
};
|
||
host.mountViewport({
|
||
getBoundingClientRect() {
|
||
return mockBounds;
|
||
},
|
||
});
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 5,
|
||
globalY: 50,
|
||
}),
|
||
).toBeFalsy();
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 115,
|
||
globalY: 50,
|
||
}),
|
||
).toBeFalsy();
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 50,
|
||
globalY: 50,
|
||
}),
|
||
).toBeTruthy();
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 50,
|
||
globalY: 5,
|
||
}),
|
||
).toBeFalsy();
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 50,
|
||
globalY: 150,
|
||
}),
|
||
).toBeFalsy();
|
||
expect(
|
||
host.isEnter({
|
||
globalX: 150,
|
||
globalY: 150,
|
||
}),
|
||
).toBeFalsy();
|
||
});
|
||
|
||
it('fixEvent', () => {
|
||
expect(host.fixEvent({ fixed: true, clientX: 1 })).toEqual({ fixed: true, clientX: 1 });
|
||
});
|
||
|
||
it('findDOMNodes', () => {
|
||
host.connect({
|
||
findDOMNodes: () => {
|
||
return null;
|
||
},
|
||
}, () => {});
|
||
expect(host.findDOMNodes()).toBeNull();
|
||
|
||
const mockElems = [document.createElement('div')];
|
||
host.connect({
|
||
findDOMNodes: () => {
|
||
return mockElems;
|
||
},
|
||
}, () => {});
|
||
expect(host.findDOMNodes({})).toBe(mockElems);
|
||
expect(host.findDOMNodes({}, 'xxx')).toBeNull();
|
||
expect(host.findDOMNodes({}, 'div')).toEqual(mockElems);
|
||
});
|
||
|
||
it('getClosestNodeInstance', () => {
|
||
const mockFn = jest.fn(() => {
|
||
return {
|
||
node: {},
|
||
nodeId: 'id',
|
||
docId: 'docId',
|
||
};
|
||
});
|
||
host.connect({
|
||
getClosestNodeInstance: mockFn,
|
||
}, () => {});
|
||
expect(host.getClosestNodeInstance()).toEqual({
|
||
node: {},
|
||
nodeId: 'id',
|
||
docId: 'docId',
|
||
});
|
||
});
|
||
|
||
it('getNodeInstanceFromElement', () => {
|
||
expect(host.getNodeInstanceFromElement()).toBeNull();
|
||
host.getClosestNodeInstance = () => {
|
||
return null;
|
||
};
|
||
expect(host.getNodeInstanceFromElement({})).toBeNull();
|
||
host.getClosestNodeInstance = () => {
|
||
return {
|
||
docId: project.currentDocument.id,
|
||
nodeId: 'xxx',
|
||
};
|
||
};
|
||
expect(host.getNodeInstanceFromElement({})).toBeTruthy();
|
||
});
|
||
|
||
it('getDropContainer', () => {
|
||
host.getNodeInstanceFromElement = () => {
|
||
return {
|
||
node: doc.rootNode,
|
||
};
|
||
};
|
||
host.getDropContainer({
|
||
target: {},
|
||
dragObject: {
|
||
type: DragObjectType.Node,
|
||
nodes: [doc.getNode('page')],
|
||
},
|
||
});
|
||
});
|
||
|
||
it('getComponentInstances', () => {
|
||
const mockNode = {
|
||
document: { id: 'docId' },
|
||
};
|
||
host.instancesMap = {
|
||
docId: {
|
||
get() {
|
||
return [{ comp: true }, { comp2: true }];
|
||
},
|
||
},
|
||
};
|
||
expect(host.getComponentInstances(mockNode))
|
||
.toEqual([{ comp: true }, { comp2: true }]);
|
||
|
||
const mockInst = { inst: true };
|
||
host.getClosestNodeInstance = () => {
|
||
return {
|
||
instance: mockInst,
|
||
};
|
||
};
|
||
expect(host.getComponentInstances(mockNode, { instance: mockInst }))
|
||
.toEqual([{ comp: true }, { comp2: true }]);
|
||
});
|
||
|
||
it('setNativeSelection / setDraggingState / setCopyState / clearState', () => {
|
||
const mockFn1 = jest.fn();
|
||
const mockFn2 = jest.fn();
|
||
const mockFn3 = jest.fn();
|
||
const mockFn4 = jest.fn();
|
||
host.connect({
|
||
setNativeSelection: mockFn1,
|
||
setDraggingState: mockFn2,
|
||
setCopyState: mockFn3,
|
||
clearState: mockFn4,
|
||
}, () => {});
|
||
host.setNativeSelection(true);
|
||
expect(mockFn1).toHaveBeenCalledWith(true);
|
||
host.setDraggingState(false);
|
||
expect(mockFn2).toHaveBeenCalledWith(false);
|
||
host.setCopyState(true);
|
||
expect(mockFn3).toHaveBeenCalledWith(true);
|
||
host.clearState();
|
||
expect(mockFn4).toHaveBeenCalled();
|
||
});
|
||
|
||
it('sensorAvailable / deactiveSensor', () => {
|
||
expect(host.sensorAvailable).toBeTruthy();
|
||
host.deactiveSensor();
|
||
expect(host.sensing).toBeFalsy();
|
||
});
|
||
|
||
it('getComponent', () => {
|
||
host.connect({
|
||
getComponent: () => {
|
||
return {};
|
||
},
|
||
}, () => {});
|
||
expect(host.getComponent()).toEqual({});
|
||
expect(host.createComponent()).toBeNull();
|
||
expect(host.setSuspense()).toBeFalsy();
|
||
});
|
||
|
||
it('setInstance', () => {
|
||
host.instancesMap = {};
|
||
host.setInstance('docId1', 'id1', [{}]);
|
||
expect(host.instancesMap.docId1.get('id1')).toEqual([{}]);
|
||
|
||
host.setInstance('docId1', 'id1', null);
|
||
expect(host.instancesMap.docId1.get('id1')).toBeUndefined();
|
||
});
|
||
});
|
||
|
||
describe('locate 方法', () => {
|
||
beforeEach(() => {
|
||
const mockBounds = {
|
||
top: 10,
|
||
bottom: 100,
|
||
left: 10,
|
||
right: 100,
|
||
};
|
||
host.mountViewport({
|
||
getBoundingClientRect() {
|
||
return mockBounds;
|
||
},
|
||
});
|
||
});
|
||
it('locate,没有 nodes', () => {
|
||
expect(host.locate({
|
||
dragObject: {
|
||
type: DragObjectType.Node,
|
||
nodes: [],
|
||
},
|
||
})).toBeUndefined();
|
||
});
|
||
it('locate,没有 document', () => {
|
||
project.removeDocument(doc);
|
||
expect(host.locate({
|
||
dragObject: {
|
||
type: DragObjectType.Node,
|
||
nodes: [doc.getNode('page')],
|
||
},
|
||
})).toBeNull();
|
||
});
|
||
it('notFoundComponent', () => {
|
||
expect(host.locate({
|
||
dragObject: {
|
||
type: DragObjectType.Node,
|
||
nodes: [doc.getNode('form')],
|
||
},
|
||
})).toBeUndefined();
|
||
})
|
||
it('locate', () => {
|
||
host.locate({
|
||
dragObject: {
|
||
type: DragObjectType.Node,
|
||
nodes: [doc.getNode('page')],
|
||
},
|
||
});
|
||
});
|
||
});
|
||
|
||
describe('事件测试', () => {
|
||
it('setupDragAndClick', () => {});
|
||
it('setupContextMenu', async () => {
|
||
const mockDocument = getMockDocument();
|
||
const mockWindow = getMockWindow(mockDocument);
|
||
const mockIframe = {
|
||
contentWindow: mockWindow,
|
||
contentDocument: mockDocument,
|
||
dispatchEvent() {},
|
||
};
|
||
|
||
host.set('library', [
|
||
{
|
||
package: '@ali/vc-deep',
|
||
library: 'lib',
|
||
urls: ['a.js', 'b.js'],
|
||
},
|
||
]);
|
||
|
||
host.componentsConsumer.consume(() => {});
|
||
host.injectionConsumer.consume(() => {});
|
||
await host.mountContentFrame(mockIframe);
|
||
|
||
host.setupContextMenu();
|
||
host.getNodeInstanceFromElement = () => {
|
||
return {
|
||
node: { componentMeta: { componentName: 'Button', getMetadata() { return {} } }, contains() {} },
|
||
};
|
||
};
|
||
const mockFn = jest.fn();
|
||
host.designer.editor.on('designer.builtinSimulator.contextmenu', mockFn);
|
||
fireEvent.contextMenu(document, {});
|
||
// TODO:
|
||
// expect(mockFn).toHaveBeenCalledWith({ selected: 'Button' });
|
||
});
|
||
});
|
||
|
||
it('事件测试', async () => {
|
||
const mockDocument = getMockDocument();
|
||
const mockWindow = getMockWindow(mockDocument);
|
||
const mockIframe = {
|
||
contentWindow: mockWindow,
|
||
contentDocument: mockDocument,
|
||
dispatchEvent() {},
|
||
};
|
||
|
||
// 非法分支测试
|
||
host.mountContentFrame();
|
||
expect(host._iframe).toBeUndefined();
|
||
|
||
host.set('library', [
|
||
{
|
||
package: '@ali/vc-deep',
|
||
library: 'lib',
|
||
urls: ['a.js', 'b.js'],
|
||
},
|
||
]);
|
||
|
||
host.componentsConsumer.consume(() => {});
|
||
host.injectionConsumer.consume(() => {});
|
||
await host.mountContentFrame(mockIframe);
|
||
|
||
expect(host.contentWindow).toBe(mockWindow);
|
||
|
||
mockDocument.triggerEventListener(
|
||
'mouseover',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener(
|
||
'mouseleave',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener(
|
||
'mousedown',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener(
|
||
'mouseup',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener(
|
||
'mousemove',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener('click', getMockEvent(document.createElement('input')), host);
|
||
mockDocument.triggerEventListener(
|
||
'dblclick',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
mockDocument.triggerEventListener(
|
||
'contextmenu',
|
||
getMockEvent(mockDocument.createElement('div')),
|
||
host,
|
||
);
|
||
});
|
||
});
|