Skip to content

Commit cd67a8c

Browse files
liujupingJackLian
authored andcommitted
test(designer): add parse-metadata test
1 parent e6ba79b commit cd67a8c

File tree

3 files changed

+176
-3
lines changed

3 files changed

+176
-3
lines changed

packages/designer/jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const jestConfig = {
2121
// testMatch: ['**/builtin-hotkey.test.ts'],
2222
// testMatch: ['**/selection.test.ts'],
2323
// testMatch: ['**/plugin/sequencify.test.ts'],
24+
// testMatch: ['**/builtin-simulator/utils/parse-metadata.test.ts'],
2425
transformIgnorePatterns: [
2526
`/node_modules/(?!${esModules})/`,
2627
],

packages/designer/src/builtin-simulator/utils/parse-metadata.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,16 @@ export const primitiveTypes = [
1616
'any',
1717
];
1818

19+
interface LowcodeCheckType {
20+
// isRequired, props, propName, componentName, location, propFullName, secret
21+
(props: any, propName: string, componentName: string, ...rest: any[]): Error | null;
22+
// (...reset: any[]): Error | null;
23+
isRequired?: LowcodeCheckType;
24+
type?: string | object;
25+
}
26+
1927
// eslint-disable-next-line @typescript-eslint/ban-types
20-
function makeRequired(propType: any, lowcodeType: string | object) {
28+
function makeRequired(propType: any, lowcodeType: string | object): LowcodeCheckType {
2129
function lowcodeCheckTypeIsRequired(...rest: any[]) {
2230
return propType.isRequired(...rest);
2331
}
@@ -34,7 +42,7 @@ function makeRequired(propType: any, lowcodeType: string | object) {
3442
}
3543

3644
// eslint-disable-next-line @typescript-eslint/ban-types
37-
function define(propType: any = PropTypes.any, lowcodeType: string | object = {}) {
45+
function define(propType: any = PropTypes.any, lowcodeType: string | object = {}): LowcodeCheckType {
3846
if (!propType._inner && propType.name !== 'lowcodeCheckType') {
3947
propType.lowcodeType = lowcodeType;
4048
}

packages/designer/tests/builtin-simulator/utils/parse-metadata.test.ts

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import '../../fixtures/window';
2-
import { parseMetadata } from '../../../src/builtin-simulator/utils/parse-metadata';
2+
import PropTypes from 'prop-types';
3+
import { LowcodeTypes, parseMetadata, parseProps } from '../../../src/builtin-simulator/utils/parse-metadata';
4+
import { default as ReactPropTypesSecret } from 'prop-types/lib/ReactPropTypesSecret';
35

46
describe('parseMetadata', () => {
57
it('parseMetadata', async () => {
@@ -11,3 +13,165 @@ describe('parseMetadata', () => {
1113
expect(result).toBeDefined();
1214
});
1315
});
16+
17+
describe('LowcodeTypes basic type validators', () => {
18+
it('should validate string types', () => {
19+
const stringValidator = LowcodeTypes.string;
20+
// 对 stringValidator 进行测试
21+
const props = { testProp: 'This is a string' };
22+
const propName = 'testProp';
23+
const componentName = 'TestComponent';
24+
25+
const result = stringValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
26+
expect(result).toBeNull(); // No error for valid string
27+
});
28+
29+
it('should fail with a non-string type', () => {
30+
const stringValidator = LowcodeTypes.string;
31+
const props = { testProp: 42 };
32+
const propName = 'testProp';
33+
const componentName = 'TestComponent';
34+
35+
const result = stringValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
36+
expect(result).toBeInstanceOf(Error); // Error for non-string type
37+
expect(result.message).toContain('Invalid prop `testProp` of type `number` supplied to `TestComponent`, expected `string`.');
38+
});
39+
40+
it('should pass with a valid number', () => {
41+
const numberValidator = LowcodeTypes.number;
42+
const props = { testProp: 42 };
43+
const propName = 'testProp';
44+
const componentName = 'TestComponent';
45+
46+
const result = numberValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
47+
expect(result).toBeNull(); // No error for valid number
48+
});
49+
50+
it('should fail with a non-number type', () => {
51+
const numberValidator = LowcodeTypes.number;
52+
const props = { testProp: 'Not a number' };
53+
const propName = 'testProp';
54+
const componentName = 'TestComponent';
55+
56+
const result = numberValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
57+
expect(result).toBeInstanceOf(Error); // Error for non-number type
58+
expect(result.message).toContain('Invalid prop `testProp` of type `string` supplied to `TestComponent`, expected `number`.');
59+
});
60+
});
61+
62+
describe('Custom type constructors', () => {
63+
it('should create a custom type validator using define', () => {
64+
const customType = LowcodeTypes.define(PropTypes.string, 'customType');
65+
const props = { testProp: 'This is a string' };
66+
const propName = 'testProp';
67+
const componentName = 'TestComponent';
68+
69+
// 测试有效值
70+
const validResult = customType(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
71+
expect(validResult).toBeNull(); // No error for valid string
72+
73+
// 测试无效值
74+
const invalidProps = { testProp: 42 };
75+
const invalidResult = customType(invalidProps, propName, componentName, 'prop', null, ReactPropTypesSecret);
76+
expect(invalidResult).toBeInstanceOf(Error); // Error for non-string type
77+
78+
// 验证 lowcodeType 属性
79+
expect(customType.lowcodeType).toEqual('customType');
80+
81+
// 验证 isRequired 属性
82+
const requiredResult = customType.isRequired(invalidProps, propName, componentName, 'prop', null, ReactPropTypesSecret);
83+
expect(requiredResult).toBeInstanceOf(Error); // Error for non-string type
84+
});
85+
});
86+
87+
88+
describe('Advanced type constructors', () => {
89+
describe('oneOf Type Validator', () => {
90+
const oneOfValidator = LowcodeTypes.oneOf(['red', 'green', 'blue']);
91+
const propName = 'color';
92+
const componentName = 'ColorPicker';
93+
94+
it('should pass with a valid value', () => {
95+
const props = { color: 'red' };
96+
const result = oneOfValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
97+
expect(result).toBeNull(); // No error for valid value
98+
});
99+
100+
it('should fail with an invalid value', () => {
101+
const props = { color: 'yellow' };
102+
const result = oneOfValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
103+
expect(result).toBeInstanceOf(Error); // Error for invalid value
104+
expect(result.message).toContain(`Invalid prop \`${propName}\` of value \`yellow\` supplied to \`${componentName}\`, expected one of ["red","green","blue"].`);
105+
});
106+
107+
it('should fail with a non-existing value', () => {
108+
const props = { color: 'others' };
109+
const result = oneOfValidator(props, propName, componentName, 'prop', null, ReactPropTypesSecret);
110+
expect(result).toBeInstanceOf(Error); // Error for non-existing value
111+
expect(result.message).toContain(`Invalid prop \`${propName}\` of value \`others\` supplied to \`${componentName}\`, expected one of ["red","green","blue"].`);
112+
});
113+
});
114+
});
115+
116+
117+
describe('parseProps function', () => {
118+
it('should correctly parse propTypes and defaultProps', () => {
119+
const component = {
120+
propTypes: {
121+
name: LowcodeTypes.string,
122+
age: LowcodeTypes.number,
123+
},
124+
defaultProps: {
125+
name: 'John Doe',
126+
age: 30,
127+
},
128+
};
129+
const parsedProps = parseProps(component);
130+
131+
// 测试结果长度
132+
expect(parsedProps.length).toBe(2);
133+
134+
// 测试 name 属性
135+
const nameProp: any = parsedProps.find(prop => prop.name === 'name');
136+
expect(nameProp).toBeDefined();
137+
expect(nameProp.propType).toEqual('string');
138+
expect(nameProp.defaultValue).toEqual('John Doe');
139+
140+
// 测试 age 属性
141+
const ageProp: any = parsedProps.find(prop => prop.name === 'age');
142+
expect(ageProp).toBeDefined();
143+
expect(ageProp.propType).toEqual('number');
144+
expect(ageProp.defaultValue).toEqual(30);
145+
});
146+
});
147+
148+
describe('parseProps function', () => {
149+
it('should correctly parse propTypes and defaultProps', () => {
150+
const component = {
151+
propTypes: {
152+
name: LowcodeTypes.string,
153+
age: LowcodeTypes.number,
154+
},
155+
defaultProps: {
156+
name: 'John Doe',
157+
age: 30,
158+
},
159+
};
160+
const parsedProps = parseProps(component);
161+
162+
// 测试结果长度
163+
expect(parsedProps.length).toBe(2);
164+
165+
// 测试 name 属性
166+
const nameProp: any = parsedProps.find(prop => prop.name === 'name');
167+
expect(nameProp).toBeDefined();
168+
expect(nameProp.propType).toEqual('string');
169+
expect(nameProp.defaultValue).toEqual('John Doe');
170+
171+
// 测试 age 属性
172+
const ageProp: any = parsedProps.find(prop => prop.name === 'age');
173+
expect(ageProp).toBeDefined();
174+
expect(ageProp.propType).toEqual('number');
175+
expect(ageProp.defaultValue).toEqual(30);
176+
});
177+
});

0 commit comments

Comments
 (0)