mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2026-01-13 01:21:58 +00:00
fix: 修复 prop 无法删除最后一个 item
refactor(test): 增加 prop/props 部分的单测 refactor: 不再给非 vc 组件传入 _leaf
This commit is contained in:
parent
ae37a02d62
commit
e18a3863cf
@ -86,7 +86,7 @@ export class SettingPropEntry implements SettingEntry {
|
||||
}
|
||||
const propName = this.path.join('.');
|
||||
let l = this.nodes.length;
|
||||
while (l-- > 1) {
|
||||
while (l-- > 0) {
|
||||
this.nodes[l].getProp(propName, true)!.key = key;
|
||||
}
|
||||
this._name = key;
|
||||
|
||||
@ -15,10 +15,14 @@ export function getConvertedExtraKey(key: string): string {
|
||||
if (key.indexOf('.') > 0) {
|
||||
_key = key.split('.')[0];
|
||||
}
|
||||
return EXTRA_KEY_PREFIX + _key + EXTRA_KEY_PREFIX + key.substr(_key.length);
|
||||
return EXTRA_KEY_PREFIX + _key + EXTRA_KEY_PREFIX + key.substr(_key.length + 1);
|
||||
}
|
||||
export function getOriginalExtraKey(key: string): string {
|
||||
return key.replace(new RegExp(`${EXTRA_KEY_PREFIX}`, 'g'), '');
|
||||
// 移除串首、串尾的 EXTRA_KEY_PREFIX,将剩下的转成 .
|
||||
return key
|
||||
.replace(new RegExp(`^${EXTRA_KEY_PREFIX}`), '')
|
||||
.replace(new RegExp(`${EXTRA_KEY_PREFIX}$`), '')
|
||||
.replace(new RegExp(`${EXTRA_KEY_PREFIX}`, 'g'), '.');
|
||||
}
|
||||
|
||||
export class Props implements IPropParent {
|
||||
|
||||
14
packages/designer/tests/designer/dragon.test.ts
Normal file
14
packages/designer/tests/designer/dragon.test.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { fireEvent } from '@testing-library/react';
|
||||
|
||||
it('test', () => {
|
||||
document.addEventListener('keydown', (e) => {
|
||||
console.log(e);
|
||||
})
|
||||
|
||||
fireEvent.keyDown(document, { key: 'Enter', })
|
||||
|
||||
document.addEventListener('drag', (e) => {
|
||||
console.log(e);
|
||||
})
|
||||
fireEvent.drag(document, {})
|
||||
})
|
||||
394
packages/designer/tests/document/node/props/prop.test.ts
Normal file
394
packages/designer/tests/document/node/props/prop.test.ts
Normal file
@ -0,0 +1,394 @@
|
||||
import '../../../fixtures/window';
|
||||
import { set } from '../../../utils';
|
||||
import { Editor } from '@ali/lowcode-editor-core';
|
||||
import { Props } from '../../../../src/document/node/props/props';
|
||||
import { Designer } from '../../../../src/designer/designer';
|
||||
import { Project } from '../../../../src/project/project';
|
||||
import { DocumentModel } from '../../../../src/document/document-model';
|
||||
import { Prop, isProp, isValidArrayIndex } from '../../../../src/document/node/props/prop';
|
||||
import { TransformStage } from '@ali/lowcode-types';
|
||||
import { delayObxTick } from '../../../utils';
|
||||
|
||||
const mockedOwner = {
|
||||
componentName: 'Div',
|
||||
};
|
||||
|
||||
const mockedPropsInst = {
|
||||
owner: mockedOwner,
|
||||
};
|
||||
mockedPropsInst.props = mockedPropsInst;
|
||||
|
||||
describe('Prop 类测试', () => {
|
||||
describe('基础类型', () => {
|
||||
let boolProp: Prop;
|
||||
let strProp: Prop;
|
||||
let numProp: Prop;
|
||||
let nullProp: Prop;
|
||||
let expProp: Prop;
|
||||
let slotProp: Prop;
|
||||
beforeEach(() => {
|
||||
boolProp = new Prop(mockedPropsInst, true, 'boolProp');
|
||||
strProp = new Prop(mockedPropsInst, 'haha', 'strProp');
|
||||
numProp = new Prop(mockedPropsInst, 1, 'numProp');
|
||||
nullProp = new Prop(mockedPropsInst, null, 'nullProp');
|
||||
expProp = new Prop(mockedPropsInst, { type: 'JSExpression', value: 'state.haha' }, 'expProp');
|
||||
// slotProp = new Prop(mockedPropsInst, { type: 'JSSlot', value: [{ componentName: 'Button' }] }, 'slotProp');
|
||||
});
|
||||
afterEach(() => {
|
||||
boolProp.purge();
|
||||
strProp.purge();
|
||||
numProp.purge();
|
||||
nullProp.purge();
|
||||
expProp.purge();
|
||||
// slotProp.purge();
|
||||
});
|
||||
|
||||
it('consturctor / getProps / getNode', () => {
|
||||
expect(boolProp.parent).toBe(mockedPropsInst);
|
||||
expect(boolProp.getProps()).toBe(mockedPropsInst);
|
||||
expect(boolProp.getNode()).toBe(mockedOwner);
|
||||
});
|
||||
|
||||
it('misc', () => {
|
||||
expect(boolProp.get('x', false)).toBeNull();
|
||||
expect(boolProp.maps).toBeNull();
|
||||
expect(boolProp.add()).toBeNull();
|
||||
|
||||
strProp.unset();
|
||||
strProp.add(2, true);
|
||||
strProp.set(1);
|
||||
|
||||
expect(numProp.set()).toBeNull();
|
||||
expect(numProp.has()).toBeFalsy();
|
||||
});
|
||||
|
||||
it('getValue / getAsString / setValue', () => {
|
||||
expect(strProp.getValue()).toBe('haha');
|
||||
strProp.setValue('heihei');
|
||||
expect(strProp.getValue()).toBe('heihei');
|
||||
expect(strProp.getAsString()).toBe('heihei');
|
||||
|
||||
strProp.unset();
|
||||
expect(strProp.getValue()).toBeUndefined();
|
||||
});
|
||||
|
||||
it('code', () => {
|
||||
expect(expProp.code).toBe('state.haha');
|
||||
expect(boolProp.code).toBe('true');
|
||||
expect(strProp.code).toBe('"haha"');
|
||||
|
||||
expProp.code = 'state.heihei';
|
||||
expect(expProp.code).toBe('state.heihei');
|
||||
expect(expProp.getValue()).toEqual({
|
||||
type: 'JSExpression',
|
||||
value: 'state.heihei',
|
||||
});
|
||||
|
||||
boolProp.code = 'false';
|
||||
expect(boolProp.code).toBe('false');
|
||||
expect(boolProp.getValue()).toBe(false);
|
||||
|
||||
strProp.code = '"heihei"';
|
||||
expect(strProp.code).toBe('"heihei"');
|
||||
expect(strProp.getValue()).toBe('heihei');
|
||||
|
||||
// TODO: 不确定为什么会有这个分支
|
||||
strProp.code = 'state.a';
|
||||
expect(strProp.code).toBe('state.a');
|
||||
expect(strProp.getValue()).toEqual({
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
mock: 'heihei',
|
||||
});
|
||||
});
|
||||
|
||||
it('export', () => {
|
||||
expect(boolProp.export(TransformStage.Save)).toBe(true);
|
||||
expect(strProp.export(TransformStage.Save)).toBe('haha');
|
||||
expect(numProp.export(TransformStage.Save)).toBe(1);
|
||||
expect(nullProp.export(TransformStage.Save)).toBe('');
|
||||
expect(nullProp.export(TransformStage.Serilize)).toBe(null);
|
||||
expect(expProp.export(TransformStage.Save)).toEqual({
|
||||
type: 'JSExpression',
|
||||
value: 'state.haha',
|
||||
});
|
||||
|
||||
strProp.unset();
|
||||
expect(strProp.getValue()).toBeUndefined();
|
||||
expect(strProp.isUnset()).toBeTruthy();
|
||||
expect(strProp.export(TransformStage.Save)).toBeUndefined();
|
||||
|
||||
expect(
|
||||
new Prop(mockedPropsInst, false, '___condition___').export(TransformStage.Render),
|
||||
).toBeTruthy();
|
||||
// console.log(slotProp.export(TransformStage.Render));
|
||||
});
|
||||
|
||||
it('compare', () => {
|
||||
const newProp = new Prop(mockedPropsInst, 'haha');
|
||||
expect(strProp.compare(newProp)).toBe(0);
|
||||
expect(strProp.compare(expProp)).toBe(2);
|
||||
|
||||
newProp.unset();
|
||||
expect(strProp.compare(newProp)).toBe(2);
|
||||
strProp.unset();
|
||||
expect(strProp.compare(newProp)).toBe(0);
|
||||
});
|
||||
|
||||
it('isVirtual', () => {
|
||||
expect(new Prop(mockedPropsInst, 111, '!virtualProp')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('purge', () => {
|
||||
boolProp.purge();
|
||||
expect(boolProp.purged).toBeTruthy();
|
||||
boolProp.purge();
|
||||
});
|
||||
|
||||
it('迭代器 / map / forEach', () => {
|
||||
const mockedFn = jest.fn();
|
||||
for (let item of strProp) {
|
||||
mockedFn();
|
||||
}
|
||||
expect(mockedFn).not.toHaveBeenCalled();
|
||||
mockedFn.mockClear();
|
||||
|
||||
strProp.forEach(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).not.toHaveBeenCalled();
|
||||
mockedFn.mockClear();
|
||||
|
||||
strProp.map(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).not.toHaveBeenCalled();
|
||||
mockedFn.mockClear();
|
||||
});
|
||||
});
|
||||
|
||||
describe('复杂类型', () => {
|
||||
describe('items(map 类型)', () => {
|
||||
let prop: Prop;
|
||||
beforeEach(() => {
|
||||
prop = new Prop(mockedPropsInst, {
|
||||
a: 1,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
});
|
||||
});
|
||||
afterEach(() => {
|
||||
prop.purge();
|
||||
});
|
||||
|
||||
it('items / get', async () => {
|
||||
expect(prop.size).toBe(5);
|
||||
|
||||
expect(prop.get('a').getValue()).toBe(1);
|
||||
expect(prop.get('b').getValue()).toBe('str');
|
||||
expect(prop.get('c').getValue()).toBe(true);
|
||||
expect(prop.get('d').getValue()).toEqual({ type: 'JSExpression', value: 'state.a' });
|
||||
expect(prop.get('z').getValue()).toEqual({
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
});
|
||||
|
||||
|
||||
expect(prop.getPropValue('a')).toBe(1);
|
||||
prop.setPropValue('a', 2);
|
||||
expect(prop.getPropValue('a')).toBe(2);
|
||||
prop.clearPropValue('a');
|
||||
expect(prop.get('a')?.isUnset()).toBeTruthy();
|
||||
|
||||
expect(prop.get('z.z1')?.getValue()).toBe(1);
|
||||
expect(prop.get('z.z2')?.getValue()).toBe('str');
|
||||
|
||||
const fromStashProp = prop.get('l');
|
||||
const fromStashNestedProp = prop.get('m.m1');
|
||||
fromStashProp.setValue('fromStashProp');
|
||||
fromStashNestedProp?.setValue('fromStashNestedProp')
|
||||
|
||||
await delayObxTick();
|
||||
expect(prop.get('l').getValue()).toBe('fromStashProp');
|
||||
expect(prop.get('m.m1').getValue()).toBe('fromStashNestedProp');
|
||||
});
|
||||
|
||||
it('export', () => {
|
||||
// TODO: 需要访问一下才能触发构造 _items
|
||||
prop.items;
|
||||
expect(prop.export()).toEqual({
|
||||
a: 1,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('compare', () => {
|
||||
const prop1 = new Prop(mockedPropsInst, { a: 1 });
|
||||
const prop2 = new Prop(mockedPropsInst, { b: 1 });
|
||||
expect(prop1.compare(prop2)).toBe(1);
|
||||
});
|
||||
|
||||
it('has / add / delete / deleteKey / remove', () => {
|
||||
expect(prop.has('a')).toBeTruthy();
|
||||
expect(prop.has('b')).toBeTruthy();
|
||||
expect(prop.has('c')).toBeTruthy();
|
||||
expect(prop.has('d')).toBeTruthy();
|
||||
expect(prop.has('z')).toBeTruthy();
|
||||
expect(prop.has('y')).toBeFalsy();
|
||||
|
||||
// 触发一下内部 maps 构造
|
||||
prop.items;
|
||||
expect(prop.has('z')).toBeTruthy();
|
||||
|
||||
expect(prop.add(1)).toBeNull();
|
||||
|
||||
prop.deleteKey('c');
|
||||
expect(prop.get('c', false)).toBeNull();
|
||||
prop.delete(prop.get('b'));
|
||||
expect(prop.get('b', false)).toBeNull();
|
||||
|
||||
prop.get('d')?.remove();
|
||||
expect(prop.get('d', false)).toBeNull();
|
||||
});
|
||||
|
||||
it('set', () => {
|
||||
prop.set('e', 1);
|
||||
expect(prop.get('e', false)?.getValue()).toBe(1);
|
||||
prop.set('a', 5);
|
||||
expect(prop.get('a', false)?.getValue()).toBe(5);
|
||||
});
|
||||
|
||||
it('迭代器 / map / forEach', () => {
|
||||
const mockedFn = jest.fn();
|
||||
for (let item of prop) {
|
||||
mockedFn();
|
||||
}
|
||||
expect(mockedFn).toHaveBeenCalledTimes(5);
|
||||
mockedFn.mockClear();
|
||||
|
||||
prop.forEach(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).toHaveBeenCalledTimes(5);
|
||||
mockedFn.mockClear();
|
||||
|
||||
prop.map(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).toHaveBeenCalledTimes(5);
|
||||
mockedFn.mockClear();
|
||||
});
|
||||
|
||||
it('dispose', () => {
|
||||
prop.dispose();
|
||||
|
||||
expect(prop._items).toBeNull();
|
||||
expect(prop._maps).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('items(list 类型)', () => {
|
||||
let prop: Prop;
|
||||
beforeEach(() => {
|
||||
prop = new Prop(mockedPropsInst, [1, true, 'haha']);
|
||||
});
|
||||
afterEach(() => {
|
||||
prop.purge();
|
||||
});
|
||||
|
||||
it('items / get', () => {
|
||||
expect(prop.size).toBe(3);
|
||||
|
||||
expect(prop.get(0).getValue()).toBe(1);
|
||||
expect(prop.get(1).getValue()).toBe(true);
|
||||
expect(prop.get(2).getValue()).toBe('haha');
|
||||
|
||||
expect(prop.getAsString()).toBe('');
|
||||
});
|
||||
|
||||
it('export', () => {
|
||||
// 触发构造
|
||||
prop.items;
|
||||
expect(prop.export()).toEqual([1, true, 'haha']);
|
||||
});
|
||||
|
||||
it('compare', () => {
|
||||
const prop1 = new Prop(mockedPropsInst, [1]);
|
||||
const prop2 = new Prop(mockedPropsInst, [2]);
|
||||
const prop3 = new Prop(mockedPropsInst, [1, 2]);
|
||||
expect(prop1.compare(prop2)).toBe(1);
|
||||
expect(prop1.compare(prop3)).toBe(2);
|
||||
});
|
||||
|
||||
it('set', () => {
|
||||
prop.set(0, 1);
|
||||
expect(prop.get(0, false)?.getValue()).toBe(1);
|
||||
// illegal
|
||||
// expect(prop.set(5, 1)).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('slotNode / setAsSlot', () => {
|
||||
const editor = new Editor();
|
||||
const designer = new Designer({ editor });
|
||||
const doc = new DocumentModel(designer.project, {
|
||||
componentName: 'Page',
|
||||
children: [{
|
||||
id: 'div',
|
||||
componentName: 'Div',
|
||||
}],
|
||||
});
|
||||
const div = doc.getNode('div');
|
||||
|
||||
const slotProp = new Prop(div?.getProps(), {
|
||||
type: 'JSSlot',
|
||||
value: [{
|
||||
componentName: 'Button'
|
||||
}],
|
||||
});
|
||||
|
||||
expect(slotProp.slotNode?.componentName).toBe('Slot');
|
||||
|
||||
// TODO: id 总是变,不好断言
|
||||
expect(slotProp.code.includes('Button')).toBeTruthy();
|
||||
|
||||
console.log(slotProp.export());
|
||||
|
||||
expect(slotProp.export().value[0].componentName).toBe('Button');
|
||||
expect(slotProp.export(TransformStage.Serilize).value[0].componentName).toBe('Button');
|
||||
|
||||
slotProp.purge();
|
||||
expect(slotProp.purged).toBeTruthy();
|
||||
slotProp.dispose();
|
||||
});
|
||||
});
|
||||
|
||||
describe('其他导出函数', () => {
|
||||
it('isProp', () => {
|
||||
expect(isProp({ isProp: true })).toBeTruthy();
|
||||
});
|
||||
|
||||
it('isValidArrayIndex', () => {
|
||||
expect(isValidArrayIndex('1')).toBeTruthy();
|
||||
expect(isValidArrayIndex('1', 2)).toBeTruthy();
|
||||
expect(isValidArrayIndex('2', 1)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
244
packages/designer/tests/document/node/props/props.test.ts
Normal file
244
packages/designer/tests/document/node/props/props.test.ts
Normal file
@ -0,0 +1,244 @@
|
||||
|
||||
import '../../../fixtures/window';
|
||||
import { set } from '../../../utils';
|
||||
import { Editor } from '@ali/lowcode-editor-core';
|
||||
import { Props, getConvertedExtraKey, getOriginalExtraKey } from '../../../../src/document/node/props/props';
|
||||
import { Designer } from '../../../../src/designer/designer';
|
||||
import { Project } from '../../../../src/project/project';
|
||||
import { DocumentModel } from '../../../../src/document/document-model';
|
||||
import { Prop, isProp, isValidArrayIndex } from '../../../../src/document/node/props/props';
|
||||
import { TransformStage } from '@ali/lowcode-types';
|
||||
import { delayObxTick } from '../../../utils';
|
||||
|
||||
const mockedOwner = { componentName: 'Page' };
|
||||
|
||||
describe('Props 类测试', () => {
|
||||
let props: Props;
|
||||
beforeEach(() => {
|
||||
props = new Props(mockedOwner, {
|
||||
a: 1,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
}, { condition: true });
|
||||
});
|
||||
afterEach(() => {
|
||||
props.purge();
|
||||
});
|
||||
|
||||
it('getNode', () => {
|
||||
expect(props.getNode()).toBe(mockedOwner);
|
||||
});
|
||||
|
||||
it('items / get', async () => {
|
||||
expect(props.size).toBe(6);
|
||||
|
||||
expect(props.get('a').getValue()).toBe(1);
|
||||
expect(props.get('b').getValue()).toBe('str');
|
||||
expect(props.get('c').getValue()).toBe(true);
|
||||
expect(props.get('d').getValue()).toEqual({ type: 'JSExpression', value: 'state.a' });
|
||||
expect(props.get('z').getValue()).toEqual({
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
});
|
||||
|
||||
|
||||
expect(props.getPropValue('a')).toBe(1);
|
||||
props.setPropValue('a', 2);
|
||||
expect(props.getPropValue('a')).toBe(2);
|
||||
// props.clearPropValue('a');
|
||||
// expect(props.get('a')?.isUnset()).toBeTruthy();
|
||||
|
||||
expect(props.get('z.z1')?.getValue()).toBe(1);
|
||||
expect(props.get('z.z2')?.getValue()).toBe('str');
|
||||
|
||||
const fromStashProp = props.get('l', true);
|
||||
const fromStashNestedProp = props.get('m.m1', true);
|
||||
fromStashProp.setValue('fromStashProp');
|
||||
fromStashNestedProp?.setValue('fromStashNestedProp')
|
||||
|
||||
await delayObxTick();
|
||||
expect(props.get('l').getValue()).toBe('fromStashProp');
|
||||
expect(props.get('m.m1').getValue()).toBe('fromStashNestedProp');
|
||||
});
|
||||
|
||||
it('export', () => {
|
||||
expect(props.export()).toEqual({
|
||||
props: {
|
||||
a: 1,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
},
|
||||
extras: {
|
||||
condition: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(props.toData()).toEqual({
|
||||
a: 1,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
});
|
||||
|
||||
props.get('a')?.unset();
|
||||
expect(props.toData()).toEqual({
|
||||
a: undefined,
|
||||
b: 'str',
|
||||
c: true,
|
||||
d: {
|
||||
type: 'JSExpression',
|
||||
value: 'state.a',
|
||||
},
|
||||
z: {
|
||||
z1: 1,
|
||||
z2: 'str',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('import', () => {
|
||||
props.import({
|
||||
x: 1,
|
||||
y: true
|
||||
}, { loop: false });
|
||||
expect(props.export()).toEqual({
|
||||
props: {
|
||||
x: 1,
|
||||
y: true,
|
||||
},
|
||||
extras: {
|
||||
loop: false,
|
||||
}
|
||||
});
|
||||
|
||||
props.import();
|
||||
});
|
||||
|
||||
it('merge', async () => {
|
||||
props.merge({ x: 1 });
|
||||
|
||||
await delayObxTick();
|
||||
|
||||
expect(props.get('x')?.getValue()).toBe(1);
|
||||
});
|
||||
|
||||
it('has / add / delete / deleteKey / remove', () => {
|
||||
expect(props.has('a')).toBeTruthy();
|
||||
expect(props.has('b')).toBeTruthy();
|
||||
expect(props.has('c')).toBeTruthy();
|
||||
expect(props.has('d')).toBeTruthy();
|
||||
expect(props.has('z')).toBeTruthy();
|
||||
expect(props.has('y')).toBeFalsy();
|
||||
|
||||
props.add(1, 'newAdded');
|
||||
expect(props.has('newAdded')).toBeTruthy();
|
||||
|
||||
props.deleteKey('c');
|
||||
expect(props.get('c', false)).toBeNull();
|
||||
props.delete(props.get('b'));
|
||||
expect(props.get('b', false)).toBeNull();
|
||||
|
||||
props.get('d')?.remove();
|
||||
expect(props.get('d', false)).toBeNull();
|
||||
});
|
||||
|
||||
it('迭代器 / map / forEach', () => {
|
||||
const mockedFn = jest.fn();
|
||||
for (let item of props) {
|
||||
mockedFn();
|
||||
}
|
||||
expect(mockedFn).toHaveBeenCalledTimes(6);
|
||||
mockedFn.mockClear();
|
||||
|
||||
props.forEach(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).toHaveBeenCalledTimes(6);
|
||||
mockedFn.mockClear();
|
||||
|
||||
props.map(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).toHaveBeenCalledTimes(6);
|
||||
mockedFn.mockClear();
|
||||
|
||||
props.filter(item => {
|
||||
mockedFn();
|
||||
});
|
||||
expect(mockedFn).toHaveBeenCalledTimes(6);
|
||||
mockedFn.mockClear();
|
||||
});
|
||||
|
||||
it('purge', () => {
|
||||
props.purge();
|
||||
|
||||
expect(props.purged).toBeTruthy();
|
||||
});
|
||||
|
||||
it('empty items', () => {
|
||||
expect(new Props(mockedOwner).export()).toEqual({});
|
||||
});
|
||||
|
||||
describe('list 类型', () => {
|
||||
let props: Props;
|
||||
beforeEach(() => {
|
||||
props = new Props(mockedOwner, [1, true, 'haha'], { condition: true });
|
||||
});
|
||||
it('constructor', () => {
|
||||
props.purge();
|
||||
});
|
||||
|
||||
it('export', () => {
|
||||
expect(props.export().extras).toEqual({
|
||||
condition: true
|
||||
})
|
||||
});
|
||||
|
||||
it('import', () => {
|
||||
props.import([1], { loop: true });
|
||||
expect(props.export().extras).toEqual({
|
||||
loop: true
|
||||
});
|
||||
|
||||
props.items[0]?.unset();
|
||||
props.export();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('其他函数', () => {
|
||||
it('getConvertedExtraKey', () => {
|
||||
expect(getConvertedExtraKey()).toBe('');
|
||||
expect(getConvertedExtraKey('a')).toBe('___a___');
|
||||
expect(getConvertedExtraKey('a.b')).toBe('___a___b');
|
||||
});
|
||||
|
||||
it('getOriginalExtraKey', () => {
|
||||
expect(getOriginalExtraKey('___a___')).toBe('a');
|
||||
expect(getOriginalExtraKey('___a___b')).toBe('a.b');
|
||||
});
|
||||
});
|
||||
@ -1,6 +1,8 @@
|
||||
import { Node } from '@ali/lowcode-designer';
|
||||
import LowCodeRenderer from '@ali/lowcode-react-renderer';
|
||||
import { ReactInstance, Fragment, Component, createElement } from 'react';
|
||||
import { observer } from '@recore/obx-react';
|
||||
import { isFromVC } from '@ali/lowcode-utils';
|
||||
import { SimulatorRendererContainer, DocumentInstance } from './renderer';
|
||||
import { Router, Route, Switch } from 'react-router';
|
||||
import './renderer.less';
|
||||
@ -103,7 +105,7 @@ class Layout extends Component<{ rendererContainer: SimulatorRendererContainer }
|
||||
if (layout) {
|
||||
const { Component, props, componentName } = layout;
|
||||
if (Component) {
|
||||
return <Component key='layout' props={props}>{children}</Component>;
|
||||
return <Component key="layout" props={props}>{children}</Component>;
|
||||
}
|
||||
if (componentName && rendererContainer.getComponent(componentName)) {
|
||||
return createElement(
|
||||
@ -147,8 +149,10 @@ class Renderer extends Component<{
|
||||
customCreateElement={(Component: any, props: any, children: any) => {
|
||||
const { __id, __desingMode, ...viewProps } = props;
|
||||
viewProps.componentId = __id;
|
||||
const leaf = documentInstance.getNode(__id);
|
||||
viewProps._leaf = leaf;
|
||||
const leaf = documentInstance.getNode(__id) as Node;
|
||||
if (isFromVC(leaf?.componentMeta)) {
|
||||
viewProps._leaf = leaf;
|
||||
}
|
||||
viewProps._componentName = leaf?.componentName;
|
||||
// 如果是容器 && 无children && 高宽为空 增加一个占位容器,方便拖动
|
||||
if (
|
||||
|
||||
0
packages/react-simulator-renderer/src/utils/misc.ts
Normal file
0
packages/react-simulator-renderer/src/utils/misc.ts
Normal file
@ -1,6 +1,7 @@
|
||||
|
||||
import { isI18NObject } from './is-object';
|
||||
import get from 'lodash.get';
|
||||
import { ComponentMeta } from '@ali/lowcode-designer';
|
||||
|
||||
export function isUseI18NSetter(prototype: any, propName: string) {
|
||||
const configure = prototype?.options?.configure;
|
||||
@ -43,3 +44,11 @@ export function waitForThing(obj: any, path: string): Promise<any> {
|
||||
}
|
||||
return _innerWaitForThing(obj, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前 meta 是否从 vc prototype 转换而来
|
||||
* @param meta
|
||||
*/
|
||||
export function isFromVC(meta: ComponentMeta) {
|
||||
return !!meta?.getMetadata()?.experimental;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user