mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
test: add renderer-core hoc/leaf single test
This commit is contained in:
parent
bf2c1e96a1
commit
11319e1ac9
@ -23,6 +23,8 @@ const jestConfig = {
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.ts',
|
||||
'src/**/*.tsx',
|
||||
'!src/utils/logger.ts',
|
||||
'!src/types/index.ts',
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
@ -216,24 +216,6 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
this.recordTime();
|
||||
}
|
||||
|
||||
get childrenMap(): any {
|
||||
const map = new Map();
|
||||
|
||||
if (!this.hasChildren) {
|
||||
return map;
|
||||
}
|
||||
|
||||
this.children.forEach((d: any) => {
|
||||
if (Array.isArray(d)) {
|
||||
map.set(d[0].props.componentId, d);
|
||||
return;
|
||||
}
|
||||
map.set(d.props.componentId, d);
|
||||
});
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
get defaultState() {
|
||||
const {
|
||||
hidden = false,
|
||||
@ -253,18 +235,18 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
super(props, context);
|
||||
// 监听以下事件,当变化时更新自己
|
||||
__debug(`${schema.componentName}[${this.props.componentId}] leaf render in SimulatorRendererView`);
|
||||
clearRerenderEvent(this.props.componentId);
|
||||
clearRerenderEvent(componentCacheId);
|
||||
const _leaf = this.leaf;
|
||||
this.initOnPropsChangeEvent(_leaf);
|
||||
this.initOnChildrenChangeEvent(_leaf);
|
||||
this.initOnVisibleChangeEvent(_leaf);
|
||||
this.curEventLeaf = _leaf;
|
||||
|
||||
cache.ref.set(props.componentId, {
|
||||
cache.ref.set(componentCacheId, {
|
||||
makeUnitRender: this.makeUnitRender,
|
||||
});
|
||||
|
||||
let cacheState = cache.state.get(props.componentId);
|
||||
let cacheState = cache.state.get(componentCacheId);
|
||||
if (!cacheState || cacheState.__tag !== props.__tag) {
|
||||
cacheState = this.defaultState;
|
||||
}
|
||||
@ -275,7 +257,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
private curEventLeaf: Node | undefined;
|
||||
|
||||
setState(state: any) {
|
||||
cache.state.set(this.props.componentId, {
|
||||
cache.state.set(componentCacheId, {
|
||||
...this.state,
|
||||
...state,
|
||||
__tag: this.props.__tag,
|
||||
@ -489,7 +471,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
// TODO: 缓存同级其他元素的 children。
|
||||
// 缓存二级 children Next 查询筛选组件有问题
|
||||
// 缓存一级 children Next Tab 组件有问题
|
||||
const nextChild = getChildren(leaf?.export?.(TransformStage.Render) as types.ISchema, scope, Comp); // this.childrenMap
|
||||
const nextChild = getChildren(leaf?.export?.(TransformStage.Render) as types.ISchema, scope, Comp);
|
||||
__debug(`${schema.componentName}[${this.props.componentId}] component trigger onChildrenChange event`, nextChild);
|
||||
this.setState({
|
||||
nodeChildren: nextChild,
|
||||
@ -531,7 +513,7 @@ export function leafWrapper(Comp: types.IBaseRenderComponent, {
|
||||
}
|
||||
|
||||
get leaf(): Node | undefined {
|
||||
return this.props._leaf || getNode(this.props.componentId);
|
||||
return this.props._leaf || getNode(componentCacheId);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
||||
@ -1,97 +1,146 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`leafWrapper base 1`] = `
|
||||
<div
|
||||
_leaf={
|
||||
Node {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"onChildrenChange": [Function],
|
||||
"onPropChange": [Function],
|
||||
"onVisibleChange": [Function],
|
||||
},
|
||||
"_eventsCount": 3,
|
||||
"_maxListeners": undefined,
|
||||
Symbol(kCapture): false,
|
||||
},
|
||||
"hasLoop": false,
|
||||
"schema": Object {},
|
||||
}
|
||||
}
|
||||
>
|
||||
<div>
|
||||
exports[`children this.props.children is array 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`leafWrapper change ___condition___ props 1`] = `
|
||||
exports[`lifecycle leaf change and make componentWillReceiveProps 1`] = `
|
||||
<div>
|
||||
<div
|
||||
__tag="222"
|
||||
content="content new leaf"
|
||||
>
|
||||
content new leaf
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`lifecycle props change and make componentWillReceiveProps 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`lifecycle props change and make componentWillReceiveProps 2`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content 123"
|
||||
>
|
||||
content 123
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`lifecycle props change and make componentWillReceiveProps 3`] = `
|
||||
<div>
|
||||
<div
|
||||
__tag="111"
|
||||
content="content 123"
|
||||
>
|
||||
content 123
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mini unit render leaf has a loop, render from parent 1`] = `
|
||||
<div>
|
||||
this is a new children
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mini unit render make text props change 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`mini unit render make text props change 2`] = `
|
||||
<div
|
||||
_leaf={
|
||||
Node {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"onChildrenChange": [Function],
|
||||
"onPropChange": [Function],
|
||||
"onVisibleChange": [Function],
|
||||
},
|
||||
"_eventsCount": 3,
|
||||
"_maxListeners": undefined,
|
||||
Symbol(kCapture): false,
|
||||
},
|
||||
"hasLoop": false,
|
||||
"schema": Object {},
|
||||
}
|
||||
}
|
||||
newPropKey="newPropValue"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`leafWrapper change ___condition___ props, but not hidden component 1`] = `
|
||||
<div
|
||||
_leaf={
|
||||
Node {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"onChildrenChange": [Function],
|
||||
"onPropChange": [Function],
|
||||
"onVisibleChange": [Function],
|
||||
},
|
||||
"_eventsCount": 3,
|
||||
"_maxListeners": undefined,
|
||||
Symbol(kCapture): false,
|
||||
},
|
||||
"hasLoop": false,
|
||||
"schema": Object {},
|
||||
}
|
||||
}
|
||||
>
|
||||
<div>
|
||||
new content
|
||||
exports[`mini unit render parent is a mock leaf 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="new content to mock"
|
||||
>
|
||||
new content to mock
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`leafWrapper change props 1`] = `
|
||||
<div
|
||||
_leaf={
|
||||
Node {
|
||||
"emitter": EventEmitter {
|
||||
"_events": Object {
|
||||
"onChildrenChange": [Function],
|
||||
"onPropChange": [Function],
|
||||
"onVisibleChange": [Function],
|
||||
},
|
||||
"_eventsCount": 3,
|
||||
"_maxListeners": undefined,
|
||||
Symbol(kCapture): false,
|
||||
},
|
||||
"hasLoop": false,
|
||||
"schema": Object {},
|
||||
}
|
||||
}
|
||||
>
|
||||
<div>
|
||||
new content
|
||||
exports[`mini unit render props has new children 1`] = `
|
||||
<div>
|
||||
children 01
|
||||
children 02
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`onChildrenChange children is array string 1`] = `
|
||||
<div>
|
||||
onChildrenChange content 01
|
||||
onChildrenChange content 02
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`onPropChange change textNode [key:___condition___] props, but not hidden component 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`onPropChange change textNode [key:___condition___] props, hide textNode component 1`] = `<div />`;
|
||||
|
||||
exports[`onPropChange change textNode [key:content], content in this.props but not in leaf.export result 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`onPropChange change textNode [key:content], content in this.props but not in leaf.export result 2`] = `
|
||||
<div>
|
||||
<div
|
||||
content={null}
|
||||
/>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`onVisibleChange visible is false 1`] = `<div />`;
|
||||
|
||||
exports[`onVisibleChange visible is true 1`] = `
|
||||
<div>
|
||||
<div
|
||||
content="content"
|
||||
>
|
||||
content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@ -6,12 +6,23 @@ import { leafWrapper } from '../../src/hoc/leaf';
|
||||
import components from '../utils/components';
|
||||
import Node from '../utils/node';
|
||||
|
||||
let rerenderCount = 0;
|
||||
|
||||
const nodeMap = new Map();
|
||||
|
||||
const makeSnapshot = (component) => {
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
}
|
||||
|
||||
const baseRenderer: any = {
|
||||
__debug () {},
|
||||
__getComponentProps (schema: any) {
|
||||
return schema.props;
|
||||
},
|
||||
__getSchemaChildrenVirtualDom () {},
|
||||
__getSchemaChildrenVirtualDom (schema: any) {
|
||||
return schema.children;
|
||||
},
|
||||
context: {
|
||||
engine: {
|
||||
createElement,
|
||||
@ -19,110 +30,525 @@ const baseRenderer: any = {
|
||||
},
|
||||
props: {
|
||||
__host: {},
|
||||
getNode: () => {},
|
||||
__container: () => {},
|
||||
getNode: (id) => nodeMap.get(id),
|
||||
__container: {
|
||||
rerender: () => {
|
||||
rerenderCount = 1 + rerenderCount;
|
||||
}
|
||||
},
|
||||
documentId: '01'
|
||||
}
|
||||
}
|
||||
|
||||
describe('leafWrapper', () => {
|
||||
const Div = leafWrapper(components.Div as any, {
|
||||
schema: {
|
||||
id: 'div',
|
||||
},
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
let Div, DivNode, Text, TextNode, component, textSchema, divSchema;
|
||||
let id = 0;
|
||||
|
||||
const DivNode = new Node({});
|
||||
const TextNode = new Node({});
|
||||
|
||||
const Text = leafWrapper(components.Text as any, {
|
||||
schema: {
|
||||
id: 'div',
|
||||
beforeEach(() => {
|
||||
textSchema = {
|
||||
id: 'text' + id,
|
||||
props: {
|
||||
content: 'content'
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
divSchema = {
|
||||
id: 'div' + id,
|
||||
};
|
||||
|
||||
id++;
|
||||
|
||||
Div = leafWrapper(components.Div as any, {
|
||||
schema: divSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
const component = renderer.create(
|
||||
DivNode = new Node(divSchema);
|
||||
TextNode = new Node(textSchema);
|
||||
|
||||
nodeMap.set(divSchema.id, DivNode);
|
||||
nodeMap.set(textSchema.id, TextNode);
|
||||
|
||||
Text = leafWrapper(components.Text as any, {
|
||||
schema: textSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
component = renderer.create(
|
||||
// @ts-ignore
|
||||
<Div _leaf={DivNode}>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</Div>
|
||||
);
|
||||
});
|
||||
|
||||
it('base', () => {
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
afterEach(() => {
|
||||
component.unmount(component);
|
||||
});
|
||||
|
||||
it('change props', () => {
|
||||
describe('onPropChange', () => {
|
||||
it('change textNode [key:content] props', () => {
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
const root = component.root;
|
||||
expect(root.findByType(components.Text).props.content).toEqual('new content')
|
||||
});
|
||||
|
||||
it('change ___condition___ props', () => {
|
||||
it('change textNode [key:___condition___] props, hide textNode component', () => {
|
||||
// mock leaf?.export result
|
||||
TextNode.schema.condition = false;
|
||||
TextNode.emitPropChange({
|
||||
key: '___condition___',
|
||||
newValue: false,
|
||||
} as any);
|
||||
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('change ___condition___ props, but not hidden component', () => {
|
||||
it('change textNode [key:___condition___] props, but not hidden component', () => {
|
||||
TextNode.schema.condition = true;
|
||||
TextNode.emitPropChange({
|
||||
key: '___condition___',
|
||||
newValue: false,
|
||||
} as any);
|
||||
|
||||
let tree = component.toJSON();
|
||||
expect(tree).toMatchSnapshot();
|
||||
})
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('change textNode [key:content], content in this.props but not in leaf.export result', () => {
|
||||
makeSnapshot(component);
|
||||
|
||||
delete TextNode.schema.props.content;
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: null,
|
||||
} as any, true);
|
||||
|
||||
makeSnapshot(component);
|
||||
|
||||
const root = component.root;
|
||||
|
||||
const TextInst = root.findByType(components.Text);
|
||||
|
||||
expect(TextInst.props.content).toBeNull();
|
||||
});
|
||||
|
||||
it('change textNode [key:___loop___], make rerender', () => {
|
||||
expect(leafWrapper(components.Text as any, {
|
||||
schema: textSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
})).toEqual(Text);
|
||||
|
||||
const nextRerenderCount = rerenderCount + 1;
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: '___loop___',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
expect(rerenderCount).toBe(nextRerenderCount);
|
||||
expect(leafWrapper(components.Text as any, {
|
||||
schema: textSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
})).not.toEqual(Text);
|
||||
});
|
||||
});
|
||||
|
||||
describe('loop', () => {
|
||||
const Div = leafWrapper(components.Div as any, {
|
||||
schema: {
|
||||
id: 'div',
|
||||
},
|
||||
describe('lifecycle', () => {
|
||||
it('props change and make componentWillReceiveProps', () => {
|
||||
makeSnapshot(component);
|
||||
|
||||
// 没有 __tag 标识
|
||||
component.update((
|
||||
<Div _leaf={DivNode}>
|
||||
<Text _leaf={TextNode} content="content 123"></Text>
|
||||
</Div>
|
||||
));
|
||||
|
||||
makeSnapshot(component);
|
||||
|
||||
// 有 __tag 标识
|
||||
component.update((
|
||||
<Div _leaf={DivNode}>
|
||||
<Text _leaf={TextNode} __tag="111" content="content 123"></Text>
|
||||
</Div>
|
||||
));
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('leaf change and make componentWillReceiveProps', () => {
|
||||
const newTextNodeLeaf = new Node(textSchema);
|
||||
component.update((
|
||||
<Div _leaf={DivNode}>
|
||||
<Text _leaf={newTextNodeLeaf} __tag="222" content="content 123"></Text>
|
||||
</Div>
|
||||
));
|
||||
|
||||
newTextNodeLeaf.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'content new leaf',
|
||||
});
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
});
|
||||
|
||||
describe('mini unit render', () => {
|
||||
let miniRenderSchema, MiniRenderDiv, MiniRenderDivNode;
|
||||
beforeEach(() => {
|
||||
miniRenderSchema = {
|
||||
id: 'miniDiv' + id,
|
||||
};
|
||||
|
||||
MiniRenderDiv = leafWrapper(components.MiniRenderDiv as any, {
|
||||
schema: miniRenderSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
const DivNode = new Node({});
|
||||
const TextNode = new Node({});
|
||||
MiniRenderDivNode = new Node(miniRenderSchema, {
|
||||
componentMeta: {
|
||||
isMinimalRenderUnit: true,
|
||||
},
|
||||
});
|
||||
|
||||
const Text = leafWrapper(components.Text as any, {
|
||||
schema: {
|
||||
id: 'div',
|
||||
props: {
|
||||
content: 'content'
|
||||
TextNode = new Node(textSchema, {
|
||||
parent: MiniRenderDivNode,
|
||||
});
|
||||
|
||||
component = renderer.create(
|
||||
// @ts-ignore
|
||||
<MiniRenderDiv _leaf={MiniRenderDivNode}>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</MiniRenderDiv>
|
||||
);
|
||||
})
|
||||
|
||||
it('make text props change', () => {
|
||||
if (!MiniRenderDivNode.schema.props) {
|
||||
MiniRenderDivNode.schema.props = {};
|
||||
}
|
||||
MiniRenderDivNode.schema.props['newPropKey'] = 'newPropValue';
|
||||
|
||||
makeSnapshot(component);
|
||||
|
||||
const inst = component.root;
|
||||
|
||||
const TextInst = inst.findByType(Text).children[0];
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
expect((TextInst as any)?._fiber.stateNode.renderUnitInfo).toEqual({
|
||||
singleRender: false,
|
||||
minimalUnitId: 'miniDiv' + id,
|
||||
minimalUnitName: undefined,
|
||||
});
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('dont render mini render component', () => {
|
||||
const TextNode = new Node(textSchema, {
|
||||
parent: new Node({
|
||||
id: 'random',
|
||||
}, {
|
||||
componentMeta: {
|
||||
isMinimalRenderUnit: true,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
renderer.create(
|
||||
// @ts-ignore
|
||||
<div>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
const nextCount = rerenderCount + 1;
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
expect(rerenderCount).toBe(nextCount);
|
||||
});
|
||||
|
||||
it('leaf is a mock function', () => {
|
||||
const TextNode = new Node(textSchema, {
|
||||
parent: {
|
||||
isEmpty: () => false,
|
||||
}
|
||||
});
|
||||
|
||||
renderer.create(
|
||||
// @ts-ignore
|
||||
<div>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
});
|
||||
|
||||
it('change component leaf isRoot is true', () => {
|
||||
const TextNode = new Node(textSchema, {
|
||||
isRoot: true,
|
||||
});
|
||||
|
||||
const component = renderer.create(
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
);
|
||||
|
||||
const inst = component.root;
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
expect((inst.children[0] as any)?._fiber.stateNode.renderUnitInfo).toEqual({
|
||||
singleRender: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('change component leaf parent isRoot is true', () => {
|
||||
const TextNode = new Node(textSchema, {
|
||||
parent: new Node({
|
||||
id: 'first-parent',
|
||||
}, {
|
||||
componentMeta: {
|
||||
isMinimalRenderUnit: true,
|
||||
},
|
||||
parent: new Node({
|
||||
id: 'rootId',
|
||||
}, {
|
||||
isRoot: true,
|
||||
}),
|
||||
})
|
||||
});
|
||||
|
||||
const component = renderer.create(
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
);
|
||||
|
||||
const inst = component.root;
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content',
|
||||
} as any);
|
||||
|
||||
expect((inst.children[0] as any)?._fiber.stateNode.renderUnitInfo).toEqual({
|
||||
singleRender: false,
|
||||
minimalUnitId: 'first-parent',
|
||||
minimalUnitName: undefined,
|
||||
});
|
||||
});
|
||||
|
||||
it('parent is a mock leaf', () => {
|
||||
const MiniRenderDivNode = {};
|
||||
|
||||
const component = renderer.create(
|
||||
// @ts-ignore
|
||||
<MiniRenderDiv _leaf={MiniRenderDivNode}>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</MiniRenderDiv>
|
||||
);
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'new content to mock',
|
||||
} as any);
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('props has new children', () => {
|
||||
MiniRenderDivNode.schema.props.children = [
|
||||
'children 01',
|
||||
'children 02',
|
||||
];
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: 'props'
|
||||
});
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('leaf has a loop, render from parent', () => {
|
||||
MiniRenderDivNode = new Node(miniRenderSchema, {});
|
||||
|
||||
TextNode = new Node(textSchema, {
|
||||
parent: MiniRenderDivNode,
|
||||
hasLoop: true,
|
||||
});
|
||||
|
||||
component = renderer.create(
|
||||
// @ts-ignore
|
||||
<MiniRenderDiv _leaf={MiniRenderDivNode}>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</MiniRenderDiv>
|
||||
);
|
||||
|
||||
MiniRenderDivNode.schema.children = ['this is a new children'];
|
||||
|
||||
TextNode.emitPropChange({
|
||||
key: 'content',
|
||||
newValue: '1',
|
||||
});
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
});
|
||||
|
||||
describe('component cache', () => {
|
||||
it('get different component with same is and different doc id', () => {
|
||||
const baseRenderer02 = {
|
||||
...baseRenderer,
|
||||
props: {
|
||||
...baseRenderer.props,
|
||||
documentId: '02',
|
||||
}
|
||||
}
|
||||
const Div3 = leafWrapper(components.Div as any, {
|
||||
schema: divSchema,
|
||||
baseRenderer: baseRenderer02,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
expect(Div).not.toEqual(Div3);
|
||||
});
|
||||
|
||||
it('get component again and get ths cache component', () => {
|
||||
const Div2 = leafWrapper(components.Div as any, {
|
||||
schema: divSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
expect(Div).toEqual(Div2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onVisibleChange', () => {
|
||||
it('visible is false', () => {
|
||||
TextNode.emitVisibleChange(false);
|
||||
makeSnapshot(component);
|
||||
});
|
||||
|
||||
it('visible is true', () => {
|
||||
TextNode.emitVisibleChange(true);
|
||||
makeSnapshot(component);
|
||||
});
|
||||
});
|
||||
|
||||
describe('children', () => {
|
||||
it('this.props.children is array', () => {
|
||||
const component = renderer.create(
|
||||
// @ts-ignore
|
||||
<Div _leaf={DivNode}>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
</Div>
|
||||
);
|
||||
|
||||
makeSnapshot(component);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChildrenChange', () => {
|
||||
it('children is array string', () => {
|
||||
DivNode.schema.children = [
|
||||
'onChildrenChange content 01',
|
||||
'onChildrenChange content 02'
|
||||
]
|
||||
DivNode.emitChildrenChange();
|
||||
makeSnapshot(component);
|
||||
});
|
||||
});
|
||||
|
||||
describe('not render leaf', () => {
|
||||
let miniRenderSchema, MiniRenderDiv, MiniRenderDivNode;
|
||||
beforeEach(() => {
|
||||
miniRenderSchema = {
|
||||
id: 'miniDiv' + id,
|
||||
};
|
||||
|
||||
MiniRenderDivNode = new Node(miniRenderSchema, {
|
||||
componentMeta: {
|
||||
isMinimalRenderUnit: true,
|
||||
},
|
||||
});
|
||||
|
||||
nodeMap.set(miniRenderSchema.id, MiniRenderDivNode);
|
||||
|
||||
MiniRenderDiv = leafWrapper(components.MiniRenderDiv as any, {
|
||||
schema: miniRenderSchema,
|
||||
baseRenderer,
|
||||
componentInfo: {},
|
||||
scope: {},
|
||||
});
|
||||
|
||||
TextNode = new Node(textSchema, {
|
||||
parent: MiniRenderDivNode,
|
||||
});
|
||||
|
||||
component = renderer.create(
|
||||
<Text _leaf={TextNode} content="content"></Text>
|
||||
);
|
||||
});
|
||||
|
||||
it('onPropsChange', () => {
|
||||
const nextCount = rerenderCount + 1;
|
||||
|
||||
MiniRenderDivNode.emitPropChange({
|
||||
key: 'any',
|
||||
newValue: 'any',
|
||||
});
|
||||
|
||||
expect(rerenderCount).toBe(nextCount);
|
||||
});
|
||||
|
||||
it('onChildrenChange', () => {
|
||||
const nextCount = rerenderCount + 1;
|
||||
|
||||
MiniRenderDivNode.emitChildrenChange({
|
||||
key: 'any',
|
||||
newValue: 'any',
|
||||
});
|
||||
|
||||
expect(rerenderCount).toBe(nextCount);
|
||||
});
|
||||
|
||||
it('onVisibleChange', () => {
|
||||
const nextCount = rerenderCount + 1;
|
||||
|
||||
MiniRenderDivNode.emitVisibleChange(true);
|
||||
|
||||
expect(rerenderCount).toBe(nextCount);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1026,7 +1026,20 @@ exports[`JSExpression JSSlot has loop 1`] = `
|
||||
forwardRef={[Function]}
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
__id="node_ocl1ao1o7w4"
|
||||
__style__=":root {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}"
|
||||
behavior="NORMAL"
|
||||
className="text_l1ao7pfb"
|
||||
content="这是一个低代码业务组件~"
|
||||
fieldId="text_l1ao7lvp"
|
||||
forwardRef={[Function]}
|
||||
maxLine={0}
|
||||
showTitle={false}
|
||||
>
|
||||
这是一个低代码业务组件~
|
||||
</div>
|
||||
</div>
|
||||
@ -1044,7 +1057,20 @@ exports[`JSExpression JSSlot has loop 1`] = `
|
||||
forwardRef={[Function]}
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
__id="node_ocl1ao1o7w4"
|
||||
__style__=":root {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}"
|
||||
behavior="NORMAL"
|
||||
className="text_l1ao7pfb"
|
||||
content="这是一个低代码业务组件~"
|
||||
fieldId="text_l1ao7lvp"
|
||||
forwardRef={[Function]}
|
||||
maxLine={0}
|
||||
showTitle={false}
|
||||
>
|
||||
这是一个低代码业务组件~
|
||||
</div>
|
||||
</div>
|
||||
@ -1062,7 +1088,20 @@ exports[`JSExpression JSSlot has loop 1`] = `
|
||||
forwardRef={[Function]}
|
||||
useFieldIdAsDomId={false}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
__id="node_ocl1ao1o7w4"
|
||||
__style__=":root {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}"
|
||||
behavior="NORMAL"
|
||||
className="text_l1ao7pfb"
|
||||
content="这是一个低代码业务组件~"
|
||||
fieldId="text_l1ao7lvp"
|
||||
forwardRef={[Function]}
|
||||
maxLine={0}
|
||||
showTitle={false}
|
||||
>
|
||||
这是一个低代码业务组件~
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -11,6 +11,16 @@ jest.mock('zen-logger', () => {
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('lodash', () => {
|
||||
const original = jest.requireActual('lodash');
|
||||
|
||||
return {
|
||||
...original,
|
||||
debounce: (fn) => () => fn(),
|
||||
throttle: (fn) => () => fn(),
|
||||
}
|
||||
})
|
||||
|
||||
export const mockConsoleWarn = jest.fn();
|
||||
console.warn = mockConsoleWarn;
|
||||
|
||||
|
||||
@ -1,9 +1,17 @@
|
||||
import React from 'react';
|
||||
import { Box, Breadcrumb, Form, Select, Input, Button, Table, Pagination, Dialog } from '@alifd/next';
|
||||
|
||||
const Div = (props: any) => (<div {...props}>{props.children}</div>);
|
||||
const Div = ({_leaf, ...rest}: any) => (<div {...rest}>{rest.children}</div>);
|
||||
|
||||
const Text = (props: any) => (<div>{props.content}</div>);
|
||||
const MiniRenderDiv = ({_leaf, ...rest}: any) => {
|
||||
return (
|
||||
<div {...rest}>
|
||||
{rest.children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Text = ({_leaf, ...rest}: any) => (<div {...rest}>{rest.content}</div>);
|
||||
|
||||
const SlotComponent = (props: any) => props.mobileSlot;
|
||||
|
||||
@ -24,6 +32,7 @@ const components = {
|
||||
Div,
|
||||
SlotComponent,
|
||||
Text,
|
||||
MiniRenderDiv,
|
||||
};
|
||||
|
||||
export default components;
|
||||
@ -6,16 +6,47 @@ export default class Node {
|
||||
schema: any = {
|
||||
props: {},
|
||||
};
|
||||
hasLoop = false;
|
||||
|
||||
constructor(schema: any) {
|
||||
componentMeta = {};
|
||||
|
||||
parent;
|
||||
|
||||
hasLoop = () => this._hasLoop;
|
||||
|
||||
id;
|
||||
|
||||
_isRoot: false;
|
||||
|
||||
_hasLoop: false;
|
||||
|
||||
constructor(schema: any, info: any = {}) {
|
||||
this.emitter = new EventEmitter();
|
||||
this.schema = schema;
|
||||
const {
|
||||
componentMeta,
|
||||
parent,
|
||||
isRoot,
|
||||
hasLoop,
|
||||
} = info;
|
||||
this.schema = {
|
||||
props: {},
|
||||
...schema,
|
||||
};
|
||||
this.componentMeta = componentMeta || {};
|
||||
this.parent = parent;
|
||||
this.id = schema.id;
|
||||
this._isRoot = isRoot;
|
||||
this._hasLoop = hasLoop;
|
||||
}
|
||||
|
||||
mockLoop() {
|
||||
this.hasLoop = true;
|
||||
}
|
||||
isRoot = () => this._isRoot;
|
||||
|
||||
// componentMeta() {
|
||||
// return this.componentMeta;
|
||||
// }
|
||||
|
||||
// mockLoop() {
|
||||
// // this.hasLoop = true;
|
||||
// }
|
||||
|
||||
onChildrenChange(fn: any) {
|
||||
this.emitter.on('onChildrenChange', fn);
|
||||
@ -24,6 +55,10 @@ export default class Node {
|
||||
}
|
||||
}
|
||||
|
||||
emitChildrenChange() {
|
||||
this.emitter?.emit('onChildrenChange', {});
|
||||
}
|
||||
|
||||
onPropChange(fn: any) {
|
||||
this.emitter.on('onPropChange', fn);
|
||||
return () => {
|
||||
@ -31,11 +66,14 @@ export default class Node {
|
||||
}
|
||||
}
|
||||
|
||||
emitPropChange(val: PropChangeOptions) {
|
||||
emitPropChange(val: PropChangeOptions, skip?: boolean) {
|
||||
if (!skip) {
|
||||
this.schema.props = {
|
||||
...this.schema.props,
|
||||
[val.key + '']: val.newValue,
|
||||
}
|
||||
}
|
||||
|
||||
this.emitter?.emit('onPropChange', val);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user