refactor(chore): 完成稳定性迭代一

This commit is contained in:
力皓 2020-12-19 21:10:15 +08:00
parent 084c342a65
commit c97b0a39c2
20 changed files with 754 additions and 115 deletions

View File

@ -19,6 +19,7 @@ module.exports = {
'!src/**/*.d.ts',
'!src/icons/**',
'!src/locale/**',
'!src/builtin-simulator/utils/**',
'!src/document/node/exclusive-group.ts',
'!**/node_modules/**',
'!**/vendor/**',

View File

@ -27,6 +27,7 @@
"devDependencies": {
"@ali/lowcode-test-mate": "^1.0.1",
"@alib/build-scripts": "^0.1.29",
"@testing-library/react": "^11.2.2",
"@types/classnames": "^2.2.7",
"@types/jest": "^26.0.16",
"@types/lodash": "^4.14.165",

View File

@ -602,7 +602,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
[npm?.package, npm?.componentName].filter((item) => !!item).join('-') ||
node?.componentMeta?.componentName ||
'';
editor?.emit('desiger.builtinSimulator.contextmenu', {
editor?.emit('designer.builtinSimulator.contextmenu', {
selected,
});
});
@ -817,6 +817,7 @@ export class BuiltinSimulatorHost implements ISimulatorHost<BuiltinSimulatorProp
/**
* @see ISimulator
*/
/* istanbul ignore next */
scrollToNode(node: Node, detail?: any/* , tryTimes = 0 */) {
this.tryScrollAgain = null;
if (this.sensing) {

View File

@ -19,8 +19,7 @@ export default class Viewport implements IViewport {
}
get contentBounds(): DOMRect {
const { bounds } = this;
const { scale } = this;
const { bounds, scale } = this;
return new DOMRect(0, 0, bounds.width / scale, bounds.height / scale);
}

View File

@ -31,7 +31,15 @@ export class ActiveTracker {
return this._target?.detail;
}
/**
* @deprecated
*/
/* istanbul ignore next */
get intance() {
return this.instance;
}
get instance() {
return this._target?.instance;
}

View File

@ -138,7 +138,7 @@ export class Designer {
parent?.componentMeta?.componentName ||
'';
// eslint-disable-next-line no-unused-expressions
this.editor?.emit('designer.drag', {
this.postEvent('drag', {
time: (endTime - startTime).toFixed(2),
selected: nodes
?.map((n) => {
@ -193,7 +193,7 @@ export class Designer {
this.setupSelection();
setupHistory();
});
this.postEvent('designer.init', this);
this.postEvent('init', this);
this.setupSelection();
setupHistory();

View File

@ -18,18 +18,18 @@ export class ScrollTarget {
}
get scrollHeight(): number {
return ((this.doe || this.target) as any).scrollHeight;
return ((this.doc || this.target) as any).scrollHeight;
}
get scrollWidth(): number {
return ((this.doe || this.target) as any).scrollWidth;
return ((this.doc || this.target) as any).scrollWidth;
}
private doe?: HTMLElement;
private doc?: HTMLElement;
constructor(private target: Window | Element) {
if (isWindow(target)) {
this.doe = target.document.documentElement;
this.doc = target.document.documentElement;
}
}
}

View File

@ -0,0 +1,131 @@
import '../../fixtures/window';
import { 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 { Designer } from '../../../src/designer/designer';
import DragResizeEngine from '../../../src/builtin-simulator/bem-tools/drag-resize-engine';
import formSchema from '../../fixtures/schema/form';
import divMetadata from '../../fixtures/component-metadata/div';
import formMetadata from '../../fixtures/component-metadata/form';
import otherMeta from '../../fixtures/component-metadata/other';
import pageMetadata from '../../fixtures/component-metadata/page';
import { fireEvent, createEvent } from '@testing-library/react';
import { create } from 'lodash';
describe('DragResizeEngine 测试', () => {
let editor: Editor;
let designer: Designer;
let project: Project;
let doc: DocumentModel;
let resizeEngine: DragResizeEngine;
beforeAll(() => {
editor = new Editor();
!globalContext.has(Editor) && globalContext.register(editor, Editor);
});
beforeEach(() => {
designer = new Designer({ editor });
project = designer.project;
doc = project.createDocument(formSchema);
doc.open();
resizeEngine = new DragResizeEngine(designer);
});
afterEach(() => {
project.unload();
project.mountSimulator(undefined);
designer.purge();
resizeEngine = null;
designer = null;
project = null;
});
it('from', () => {
const resizeStartMockFn = jest.fn();
const resizeMockFn = jest.fn();
const resizeEndMockFn = jest.fn();
const offResizeStart = resizeEngine.onResizeStart(resizeStartMockFn);
const offResize = resizeEngine.onResize(resizeMockFn);
const offResizeEnd = resizeEngine.onResizeEnd(resizeEndMockFn);
const boostedNode = doc.getNode('node_k1ow3cbn');
const mockedBoostFn = jest
.fn((e) => {
return boostedNode;
});
// do nothing
resizeEngine.from();
const offFrom = resizeEngine.from(document, 'e', mockedBoostFn);
const mouseDownEvt = createEvent.mouseDown(document, { clientX: 100, clientY: 100 });
fireEvent(document, mouseDownEvt);
expect(resizeStartMockFn).toHaveBeenCalledTimes(1);
expect(resizeStartMockFn.mock.calls[0][0]).toBe(mouseDownEvt);
expect(resizeStartMockFn.mock.calls[0][1]).toBe('e');
expect(resizeStartMockFn.mock.calls[0][2]).toBe(boostedNode);
expect(resizeEngine.isDragResizing()).toBeTruthy();
const mouseMoveEvt1 = createEvent.mouseMove(document, { clientX: 108, clientY: 108 });
fireEvent(document, mouseMoveEvt1);
expect(resizeMockFn).toHaveBeenCalledTimes(1);
expect(resizeMockFn.mock.calls[0][0]).toBe(mouseMoveEvt1);
expect(resizeMockFn.mock.calls[0][1]).toBe('e');
expect(resizeMockFn.mock.calls[0][2]).toBe(boostedNode);
expect(resizeMockFn.mock.calls[0][3]).toBe(8);
expect(resizeMockFn.mock.calls[0][4]).toBe(8);
const mouseMoveEvt2 = createEvent.mouseMove(document, { clientX: 110, clientY: 110 }, 10, 10);
fireEvent(document, mouseMoveEvt2);
expect(resizeMockFn).toHaveBeenCalledTimes(2);
expect(resizeMockFn.mock.calls[1][0]).toBe(mouseMoveEvt2);
expect(resizeMockFn.mock.calls[1][1]).toBe('e');
expect(resizeMockFn.mock.calls[1][2]).toBe(boostedNode);
expect(resizeMockFn.mock.calls[1][3]).toBe(10);
expect(resizeMockFn.mock.calls[1][4]).toBe(10);
const mouseUpEvt = createEvent.mouseUp(document, { clientX: 118, clientY: 118 });
fireEvent(document, mouseUpEvt);
expect(resizeEndMockFn).toHaveBeenCalledTimes(1);
expect(resizeEndMockFn.mock.calls[0][0]).toBe(mouseUpEvt);
expect(resizeEndMockFn.mock.calls[0][1]).toBe('e');
expect(resizeEndMockFn.mock.calls[0][2]).toBe(boostedNode);
expect(resizeEngine.isDragResizing()).toBeFalsy();
offResizeStart();
offResize();
offResizeEnd();
resizeStartMockFn.mockClear();
resizeMockFn.mockClear();
fireEvent.mouseMove(document, { clientX: 100, clientY: 100 });
expect(resizeMockFn).not.toHaveBeenCalled();
offFrom();
fireEvent.mouseDown(document, { clientX: 100, clientY: 100 });
expect(resizeStartMockFn).not.toHaveBeenCalled();
});
it('has sensor', () => {
const mockedDoc = document.createElement('iframe').contentWindow?.document;
project.mountSimulator({
sensorAvailable: true,
contentDocument: document,
});
const mockedBoostFn = jest
.fn((e) => {
return doc.getNode('node_k1ow3cbn');
});
const offFrom = resizeEngine.from(document, 'e', mockedBoostFn);
// TODO: 想办法 mock 一个 iframe.currentDocument
fireEvent.mouseDown(document, { clientX: 100, clientY: 100 });
});
});

View File

@ -11,22 +11,31 @@ import {
assetItem,
AssetType,
} from '@ali/lowcode-utils';
import {
Dragon,
isDragNodeObject,
isDragNodeDataObject,
isDragAnyObject,
isLocateEvent,
DragObjectType,
isShaken,
setShaken,
} from '../../src/designer/dragon';
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 { getMockDocument, getMockWindow, getMockEvent, delayObxTick } from '../utils';
import { BuiltinSimulatorHost } from '../../src/builtin-simulator/host';
import { fireEvent } from '@testing-library/react';
const editor = new Editor();
describe('host 测试', () => {
describe('Host 测试', () => {
let editor: Editor;
let designer: Designer;
let project: Project;
let doc: DocumentModel;
let host: BuiltinSimulatorHost;
beforeAll(() => {
editor = new Editor();
@ -37,6 +46,7 @@ describe('host 测试', () => {
designer = new Designer({ editor });
project = designer.project;
doc = project.createDocument(formSchema);
host = new BuiltinSimulatorHost(designer.project);
});
afterEach(() => {
@ -44,13 +54,14 @@ describe('host 测试', () => {
project.mountSimulator(undefined);
designer._componentMetasMap.clear();
designer.purge();
host.purge();
designer = null;
project = null;
host = 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');
@ -60,13 +71,16 @@ describe('host 测试', () => {
renderEnv: 'rax',
device: 'mobile',
deviceClassName: 'mobile-rocks',
componentsAsset: [{
type: AssetType.JSText,
content: 'console.log(1)',
}, {
type: AssetType.JSUrl,
content: '//path/to/js',
}],
componentsAsset: [
{
type: AssetType.JSText,
content: 'console.log(1)',
},
{
type: AssetType.JSUrl,
content: '//path/to/js',
},
],
theme: {
type: AssetType.CSSText,
content: '.theme {font-size: 50px;}',
@ -76,13 +90,16 @@ describe('host 测试', () => {
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.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;}',
@ -96,22 +113,314 @@ describe('host 测试', () => {
expect(host.getComponentContext).toThrow('Method not implemented.');
});
it('connect', () => {});
it('mountViewport', () => {});
it('mountContentFrame', () => {});
it('autorun', () => {});
it('purge', () => {});
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('locate', () => {
host.locate({
dragObject: {
type: DragObjectType.Node,
nodes: [doc.getNode('page')],
},
})
});
});
describe('事件测试', () => {
it('setupDragAndClick', () => {
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' }},
};
}
const mockFn = jest.fn();
host.designer.editor.on('designer.builtinSimulator.contextmenu', mockFn);
fireEvent.contextMenu(document, {});
// TODO:
// expect(mockFn).toHaveBeenCalledWith({ selected: 'Button' });
});
});
it('事件测试', async () => {
const host = new BuiltinSimulatorHost(designer.project);
const mockDocument = getMockDocument();
const mockWindow = getMockWindow(mockDocument);
const mockIframe = {
@ -124,11 +433,13 @@ describe('host 测试', () => {
host.mountContentFrame();
expect(host._iframe).toBeUndefined();
host.set('library', [{
package: '@ali/vc-deep',
library: 'lib',
urls: ['a.js', 'b.js']
}]);
host.set('library', [
{
package: '@ali/vc-deep',
library: 'lib',
urls: ['a.js', 'b.js'],
},
]);
host.componentsConsumer.consume(() => {});
host.injectionConsumer.consume(() => {});
@ -161,11 +472,7 @@ describe('host 测试', () => {
getMockEvent(mockDocument.createElement('div')),
host,
);
mockDocument.triggerEventListener(
'click',
getMockEvent(document.createElement('input')),
host,
);
mockDocument.triggerEventListener('click', getMockEvent(document.createElement('input')), host);
mockDocument.triggerEventListener(
'dblclick',
getMockEvent(mockDocument.createElement('div')),
@ -176,5 +483,5 @@ describe('host 测试', () => {
getMockEvent(mockDocument.createElement('div')),
host,
);
})
});
});

View File

@ -1,4 +1,3 @@
jest.mock('@ali/lowcode-utils');
import set from 'lodash/set';
import cloneDeep from 'lodash/cloneDeep';
import '../fixtures/window';
@ -8,7 +7,6 @@ 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();
@ -243,7 +241,6 @@ describe('快捷键测试', () => {
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');

View File

@ -38,9 +38,12 @@ describe('Dragon 测试', () => {
let doc: DocumentModel;
let dragon: Dragon;
beforeEach(() => {
beforeAll(() => {
editor = new Editor();
!globalContext.has(Editor) && globalContext.register(editor, Editor);
});
beforeEach(() => {
designer = new Designer({ editor });
project = designer.project;
doc = project.createDocument(formSchema);
@ -51,16 +54,15 @@ describe('Dragon 测试', () => {
project.unload();
project.mountSimulator(undefined);
designer.purge();
editor = null;
designer = null;
project = null;
dragon = null;
});
it.skip('drag NodeData', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
dragon.onDragstart((e) => {
console.log('start', e, e.originalEvent, e.originalEvent.clientX);
@ -95,15 +97,15 @@ describe('Dragon 测试', () => {
});
it('mouse NodeData', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
const offDragStart = dragon.onDragstart(dragStartMockedFn);
const offDragStart = dragon.onDragstart(dragStartMockFn);
const offDrag = dragon.onDrag(dragMockedFn);
const offDrag = dragon.onDrag(dragMockFn);
const offDragEnd = dragon.onDragend(dragEndMockedFn);
const offDragEnd = dragon.onDragend(dragEndMockFn);
dragon.boost(
{
@ -117,19 +119,19 @@ describe('Dragon 测试', () => {
fireEvent.mouseMove(document, { clientX: 110, clientY: 110 });
fireEvent.mouseUp(document, { clientX: 118, clientY: 118 });
expect(dragStartMockedFn).toHaveBeenCalledTimes(1);
expect(dragMockedFn).toHaveBeenCalledTimes(2);
expect(dragEndMockedFn).toHaveBeenCalledTimes(1);
expect(dragStartMockFn).toHaveBeenCalledTimes(1);
expect(dragMockFn).toHaveBeenCalledTimes(2);
expect(dragEndMockFn).toHaveBeenCalledTimes(1);
});
it('mouse Node', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
const offDragStart = dragon.onDragstart(dragStartMockedFn);
const offDrag = dragon.onDrag(dragMockedFn);
const offDragEnd = dragon.onDragend(dragEndMockedFn);
const offDragStart = dragon.onDragstart(dragStartMockFn);
const offDrag = dragon.onDrag(dragMockFn);
const offDragEnd = dragon.onDragend(dragEndMockFn);
dragon.boost(
{
@ -140,23 +142,23 @@ describe('Dragon 测试', () => {
);
// mouseDown 模式正常不会触发 dragStart 事件,除非 shaken 型
expect(dragStartMockedFn).not.toHaveBeenCalled();
expect(dragStartMockFn).not.toHaveBeenCalled();
fireEvent.mouseMove(document, { clientX: 108, clientY: 108 });
expect(dragStartMockedFn).toHaveBeenCalledTimes(1);
expect(dragMockedFn).toHaveBeenCalledTimes(1);
expect(dragStartMockFn).toHaveBeenCalledTimes(1);
expect(dragMockFn).toHaveBeenCalledTimes(1);
fireEvent.mouseMove(document, { clientX: 110, clientY: 110 });
expect(dragMockedFn).toHaveBeenCalledTimes(2);
expect(dragMockFn).toHaveBeenCalledTimes(2);
expect(dragon.dragging).toBeTruthy();
fireEvent.mouseUp(document, { clientX: 118, clientY: 118 });
expect(dragEndMockedFn).toHaveBeenCalledTimes(1);
expect(dragEndMockFn).toHaveBeenCalledTimes(1);
offDragStart();
offDrag();
offDragEnd();
dragMockedFn.mockClear();
dragMockFn.mockClear();
dragon.boost(
{
@ -168,17 +170,17 @@ describe('Dragon 测试', () => {
fireEvent.mouseMove(document, { clientX: 108, clientY: 108 });
expect(dragMockedFn).not.toHaveBeenCalled();
expect(dragMockFn).not.toHaveBeenCalled();
});
it('mouse Node & esc', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
const offDragStart = dragon.onDragstart(dragStartMockedFn);
const offDrag = dragon.onDrag(dragMockedFn);
const offDragEnd = dragon.onDragend(dragEndMockedFn);
const offDragStart = dragon.onDragstart(dragStartMockFn);
const offDrag = dragon.onDrag(dragMockFn);
const offDragEnd = dragon.onDragend(dragEndMockFn);
dragon.boost(
{
@ -193,13 +195,13 @@ describe('Dragon 测试', () => {
});
it('mouse Node & copy', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
const offDragStart = dragon.onDragstart(dragStartMockedFn);
const offDrag = dragon.onDrag(dragMockedFn);
const offDragEnd = dragon.onDragend(dragEndMockedFn);
const offDragStart = dragon.onDragstart(dragStartMockFn);
const offDrag = dragon.onDrag(dragMockFn);
const offDragEnd = dragon.onDragend(dragEndMockFn);
dragon.boost(
{
@ -217,13 +219,13 @@ describe('Dragon 测试', () => {
});
it('from', () => {
const dragStartMockedFn = jest.fn();
const dragMockedFn = jest.fn();
const dragEndMockedFn = jest.fn();
const dragStartMockFn = jest.fn();
const dragMockFn = jest.fn();
const dragEndMockFn = jest.fn();
const offDragStart = dragon.onDragstart(dragStartMockedFn);
const offDrag = dragon.onDrag(dragMockedFn);
const offDragEnd = dragon.onDragend(dragEndMockedFn);
const offDragStart = dragon.onDragstart(dragStartMockFn);
const offDrag = dragon.onDrag(dragMockFn);
const offDragEnd = dragon.onDragend(dragEndMockFn);
const mockedBoostFn = jest
.fn((e) => {
return {
@ -237,37 +239,37 @@ describe('Dragon 测试', () => {
// 无用 mouseDown无效的按钮
fireEvent.mouseDown(document, { button: 2 });
expect(dragStartMockedFn).not.toHaveBeenCalled();
expect(dragStartMockFn).not.toHaveBeenCalled();
// 无用 mouseDown无效的 dragObject
fireEvent.mouseDown(document, { clientX: 100, clientY: 100 });
expect(dragStartMockedFn).not.toHaveBeenCalled();
expect(dragStartMockFn).not.toHaveBeenCalled();
fireEvent.mouseDown(document, { clientX: 100, clientY: 100 });
expect(dragStartMockedFn).not.toHaveBeenCalled();
expect(dragStartMockFn).not.toHaveBeenCalled();
fireEvent.mouseMove(document, { clientX: 108, clientY: 108 });
expect(dragStartMockedFn).toHaveBeenCalledTimes(1);
expect(dragMockedFn).toHaveBeenCalledTimes(1);
expect(dragStartMockFn).toHaveBeenCalledTimes(1);
expect(dragMockFn).toHaveBeenCalledTimes(1);
fireEvent.mouseMove(document, { clientX: 110, clientY: 110 });
expect(dragMockedFn).toHaveBeenCalledTimes(2);
expect(dragMockFn).toHaveBeenCalledTimes(2);
expect(dragon.dragging).toBeTruthy();
fireEvent.mouseUp(document, { clientX: 118, clientY: 118 });
expect(dragEndMockedFn).toHaveBeenCalledTimes(1);
expect(dragEndMockFn).toHaveBeenCalledTimes(1);
offDragStart();
offDrag();
offDragEnd();
dragMockedFn.mockClear();
dragMockFn.mockClear();
fireEvent.mouseMove(document, { clientX: 100, clientY: 100 });
expect(dragMockedFn).not.toHaveBeenCalled();
expect(dragMockFn).not.toHaveBeenCalled();
offFrom();
fireEvent.mouseMove(document, { clientX: 100, clientY: 100 });
expect(dragMockedFn).not.toHaveBeenCalled();
expect(dragMockFn).not.toHaveBeenCalled();
});
it('addSensor / removeSensor', () => {

View File

@ -0,0 +1,159 @@
import '../fixtures/window';
import { 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 { ScrollTarget, Scroller } from '../../src/designer/scroller';
import {
isRootNode,
isNode,
comparePosition,
contains,
insertChild,
insertChildren,
PositionNO,
} from '../../src/document/node/node';
import { Designer } from '../../src/designer/designer';
import {
Dragon,
isDragNodeObject,
isDragNodeDataObject,
isDragAnyObject,
isLocateEvent,
DragObjectType,
isShaken,
setShaken,
} from '../../src/designer/dragon';
import formSchema from '../fixtures/schema/form';
import divMetadata from '../fixtures/component-metadata/div';
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';
describe('Scroller 测试', () => {
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;
});
function getMockWindow() {
let scrollX = 0;
let scrollY = 0;
const mockWindow = {
scrollTo(x, y) {
if (typeof x === 'number') {
scrollX = x;
scrollY = y;
} else {
scrollX = x.left;
scrollY = x.top;
}
},
get scrollX() { return scrollX; },
get scrollY() { return scrollY; },
scrollHeight: 1000,
scrollWidth: 500,
document: {},
nodeType: Node.ELEMENT_NODE,
}
return mockWindow;
}
describe('ScrollTarget 测试', () => {
it('constructor', () => {
const win = getMockWindow();
const target = new ScrollTarget(win);
expect(target.scrollWidth).toBe(500);
expect(target.scrollHeight).toBe(1000);
target.scrollToXY(50, 50);
expect(target.left).toBe(50);
expect(target.top).toBe(50);
target.scrollTo({ left: 100, top: 100 });
expect(target.left).toBe(100);
expect(target.top).toBe(100);
console.log(target.left, target.top, target.scrollHeight, target.scrollWidth);
});
});
function mockRAF() {
let rafCount = 0;
window.requestAnimationFrame = (fn) => {
if (rafCount++ < 2) {
fn();
} else {
window.requestAnimationFrame = () => {};
}
};
}
describe('Scroller 测试', () => {
it('scrollTarget: ScrollTarget', () => {
const win = getMockWindow();
const scrollTarget = new ScrollTarget(win);
const scroller = new Scroller({ scrollTarget, bounds: { width: 50, height: 50, top: 50, bottom: 50, left: 50, right: 50 } });
mockRAF();
scroller.scrollTo({ left: 50, top: 50 });
mockRAF();
scroller.scrolling({ globalX: 100, globalY: 100 });
})
it('scrollTarget: ScrollTarget, same left / top', () => {
const win = getMockWindow();
const scrollTarget = new ScrollTarget(win);
const scroller = new Scroller({ scrollTarget, bounds: { width: 50, height: 50, top: 50, bottom: 50, left: 50, right: 50 } });
mockRAF();
scrollTarget.scrollTo({ left: 50, top: 50 });
scroller.scrollTo({ left: 50, top: 50 });
mockRAF();
scroller.scrolling({ globalX: 100, globalY: 100 });
})
it('scrollTarget: Element', () => {
const win = getMockWindow();
// const scrollTarget = new ScrollTarget(win);
const scroller = new Scroller({ scrollTarget: win, bounds: { width: 50, height: 50, top: 50, bottom: 50, left: 50, right: 50 } });
mockRAF();
scroller.scrollTo({ left: 50, top: 50 });
mockRAF();
scroller.scrolling({ globalX: 100, globalY: 100 });
})
it('scrollTarget: null', () => {
const win = getMockWindow();
// const scrollTarget = new ScrollTarget(win);
const scroller = new Scroller({ scrollTarget: null, bounds: { width: 50, height: 50, top: 50, bottom: 50, left: 50, right: 50 } });
mockRAF();
scroller.scrollTo({ left: 50, top: 50 });
mockRAF();
scroller.scrolling({ globalX: 100, globalY: 100 });
})
});
});

View File

@ -93,7 +93,7 @@ describe('setting-top-entry 测试', () => {
const { currentDocument } = designer.project;
const divNode = currentDocument?.getNode('div');
console.log(divNode?.getPropValue('behavior'));
// console.log(divNode?.getPropValue('behavior'));
const { settingEntry } = divNode!;
expect(typeof settingEntry.getChildren).toBe('function');

View File

@ -160,10 +160,10 @@ describe('Node 方法测试', () => {
const pageMeta = designer.getComponentMeta('Page');
set(pageMeta, 'prototype.options.canDropIn', () => true);
const o = doc.getNode('form')!.getSuitablePlace(doc.getNode('node_k1ow3cbj'), 1);
const o = doc.getNode('form')!.getSuitablePlace(doc.getNode('node_k1ow3cbj'), { index: 1 });
expect(o).toEqual({
container: doc.rootNode,
ref: 1,
ref: { index: 1 },
});
});

View File

@ -370,7 +370,7 @@ describe('Prop 类测试', () => {
// TODO: id 总是变,不好断言
expect(slotProp.code.includes('Button')).toBeTruthy();
console.log(slotProp.export());
slotProp.export();
expect(slotProp.export().value[0].componentName).toBe('Button');
expect(slotProp.export(TransformStage.Serilize).value[0].componentName).toBe('Button');

View File

@ -221,10 +221,9 @@ export default {
},
],
component: {
isContainer: true,
nestingRule: {
parentWhitelist: 'Div',
childWhitelist: 'Div',
// parentWhitelist: 'Div',
// childWhitelist: 'Div',
},
},
supports: {},

View File

@ -223,8 +223,8 @@ export default {
component: {
isContainer: true,
nestingRule: {
parentWhitelist: 'Div',
childWhitelist: 'Div',
// parentWhitelist: 'Div',
// childWhitelist: 'Div',
},
},
supports: {},

View File

@ -15,4 +15,6 @@ Object.defineProperty(window, 'matchMedia', {
Object.defineProperty(window, 'React', {
writable: true,
value: {},
});
});
window.scrollTo = () => {};

View File

@ -76,4 +76,36 @@ export function getMockWindow(doc?: MockDocument) {
export function clearEventsMap() {
eventsMap.clear();
}
export function getMockElement(tagName, options = {}) {
const elem = document.createElement(tagName);
let {
width = 0,
height = 0,
top = 0,
bottom = 0,
left = 0,
right = 0,
} = options;
elem.getBoundingClientRect = () => {
return {
width,
height,
top,
bottom,
left,
right,
};
};
elem.setWidth = (newWidth) => {
width = newWidth;
};
elem.setHeight = (newHeight) => {
height = newHeight;
};
// console.log(elem.ownerDocument);
// elem.ownerDocument = document;
// elem.ownerDocument.defaultView = window;
return elem;
}

View File

@ -2,7 +2,7 @@ export function getMockRenderer() {
return {
isSimulatorRenderer: true,
run() {
console.log('renderer run');
// console.log('renderer run');
}
}
}