mirror of
https://github.com/alibaba/lowcode-engine.git
synced 2025-12-12 11:20:11 +00:00
feat(utils): checkPropTypes suport IPublicTypePropType as rule for check
This commit is contained in:
parent
de738b5d7c
commit
e6ba79b4d7
@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
/* eslint-disable no-new-func */
|
/* eslint-disable no-new-func */
|
||||||
import logger from './logger';
|
import logger from './logger';
|
||||||
import { IPublicTypeRootSchema, IPublicTypeNodeSchema, IPublicTypeJSSlot } from '@alilc/lowcode-types';
|
import { IPublicTypeRootSchema, IPublicTypeNodeSchema, IPublicTypeJSSlot, IPublicTypePropType, IPublicTypeRequiredType, IPublicTypeBasicType } from '@alilc/lowcode-types';
|
||||||
import { isI18nData, isJSExpression } from '@alilc/lowcode-utils';
|
import { isI18nData, isJSExpression } from '@alilc/lowcode-utils';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import IntlMessageFormat from 'intl-messageformat';
|
import IntlMessageFormat from 'intl-messageformat';
|
||||||
@ -183,8 +183,54 @@ export function transformArrayToMap(arr: any[], key: string, overwrite = true) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isBasicType(propType: IPublicTypePropType): propType is IPublicTypeBasicType {
|
||||||
|
if (!propType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return typeof propType === 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isRequiredType(propType: IPublicTypePropType): propType is IPublicTypeRequiredType {
|
||||||
|
if (!propType) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return typeof propType === 'object' && propType.type && ['array', 'bool', 'func', 'number', 'object', 'string', 'node', 'element', 'any'].includes(propType.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function transformPropTypesRuleToString(rule: IPublicTypePropType): string {
|
||||||
|
if (!rule) {
|
||||||
|
return 'PropTypes.any';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof rule === 'string') {
|
||||||
|
return `PropTypes.${rule}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isRequiredType(rule)) {
|
||||||
|
const { type, isRequired } = rule;
|
||||||
|
return `PropTypes.${type}${isRequired ? '.isRequired' : ''}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { type, value } = rule;
|
||||||
|
switch (type) {
|
||||||
|
case 'oneOf':
|
||||||
|
return `PropTypes.oneOf([${value.map((item: any) => `"${item}"`).join(',')}])`;
|
||||||
|
case 'oneOfType':
|
||||||
|
return `PropTypes.oneOfType([${value.map((item: any) => transformPropTypesRuleToString(item)).join(', ')}])`;
|
||||||
|
case 'arrayOf':
|
||||||
|
case 'objectOf':
|
||||||
|
return `PropTypes.${type}(${transformPropTypesRuleToString(value)})`;
|
||||||
|
case 'shape':
|
||||||
|
case 'exact':
|
||||||
|
return `PropTypes.${type}({${value.map((item: any) => `${item.name}: ${transformPropTypesRuleToString(item.propType)}`).join(',')}})`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function checkPropTypes(value: any, name: string, rule: any, componentName: string): boolean {
|
export function checkPropTypes(value: any, name: string, rule: any, componentName: string): boolean {
|
||||||
let ruleFunction = rule;
|
let ruleFunction = rule;
|
||||||
|
if (typeof rule === 'object') {
|
||||||
|
ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${transformPropTypesRuleToString(rule)}`)(PropTypes2);
|
||||||
|
}
|
||||||
if (typeof rule === 'string') {
|
if (typeof rule === 'string') {
|
||||||
ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2);
|
ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,9 @@ import {
|
|||||||
parseI18n,
|
parseI18n,
|
||||||
parseData,
|
parseData,
|
||||||
checkPropTypes,
|
checkPropTypes,
|
||||||
|
transformPropTypesRuleToString,
|
||||||
|
isRequiredType,
|
||||||
|
isBasicType,
|
||||||
} from '../../src/utils/common';
|
} from '../../src/utils/common';
|
||||||
import logger from '../../src/utils/logger';
|
import logger from '../../src/utils/logger';
|
||||||
|
|
||||||
@ -468,6 +471,28 @@ describe('test parseData ', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('test isBasicType ', () => {
|
||||||
|
it('should work', () => {
|
||||||
|
expect(isBasicType(null)).toBeFalsy();
|
||||||
|
expect(isBasicType(undefined)).toBeFalsy();
|
||||||
|
expect(isBasicType({})).toBeFalsy();
|
||||||
|
expect(isBasicType({ type: 'any other type' })).toBeFalsy();
|
||||||
|
expect(isBasicType('string')).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test isRequiredType', () => {
|
||||||
|
it('should work', () => {
|
||||||
|
expect(isRequiredType(null)).toBeFalsy();
|
||||||
|
expect(isRequiredType(undefined)).toBeFalsy();
|
||||||
|
expect(isRequiredType({})).toBeFalsy();
|
||||||
|
expect(isRequiredType({ type: 'any other type' })).toBeFalsy();
|
||||||
|
expect(isRequiredType('string')).toBeFalsy();
|
||||||
|
expect(isRequiredType({ type: 'string' })).toBeTruthy();
|
||||||
|
expect(isRequiredType({ type: 'string', isRequired: true })).toBeTruthy();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
describe('checkPropTypes', () => {
|
describe('checkPropTypes', () => {
|
||||||
it('should validate correctly with valid prop type', () => {
|
it('should validate correctly with valid prop type', () => {
|
||||||
expect(checkPropTypes(123, 'age', PropTypes.number, 'TestComponent')).toBe(true);
|
expect(checkPropTypes(123, 'age', PropTypes.number, 'TestComponent')).toBe(true);
|
||||||
@ -499,4 +524,159 @@ describe('checkPropTypes', () => {
|
|||||||
const result = checkPropTypes(123, 'age', 123, 'TestComponent');
|
const result = checkPropTypes(123, 'age', 123, 'TestComponent');
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// oneOf
|
||||||
|
it('should validate correctly with valid oneOf prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'oneOf',
|
||||||
|
value: ['News', 'Photos'],
|
||||||
|
}
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe(`PropTypes.oneOf(["News","Photos"])`);
|
||||||
|
expect(checkPropTypes('News', 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes('Others', 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// oneOfType
|
||||||
|
it('should validate correctly with valid oneOfType prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'oneOfType',
|
||||||
|
value: ['string', 'number', {
|
||||||
|
type: 'array',
|
||||||
|
isRequired: true,
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.array.isRequired])');
|
||||||
|
expect(checkPropTypes(['News', 'Photos'], 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes('News', 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes(123, 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({}, 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// arrayOf
|
||||||
|
it('should validate correctly with valid arrayOf prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'arrayOf',
|
||||||
|
value: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.arrayOf(PropTypes.string.isRequired)');
|
||||||
|
expect(checkPropTypes(['News', 'Photos'], 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes(['News', 123], 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// objectOf
|
||||||
|
it('should validate correctly with valid objectOf prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'objectOf',
|
||||||
|
value: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.objectOf(PropTypes.string.isRequired)');
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 'Photos' }, 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 123 }, 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// shape
|
||||||
|
it('should validate correctly with valid shape prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'shape',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
propType: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'b',
|
||||||
|
propType: {
|
||||||
|
type: 'number',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.shape({a: PropTypes.string.isRequired,b: PropTypes.number.isRequired})');
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 123 }, 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 'Photos' }, 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
|
||||||
|
// isRequired
|
||||||
|
const rule2 = {
|
||||||
|
type: 'shape',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
propType: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'b',
|
||||||
|
propType: {
|
||||||
|
type: 'number',
|
||||||
|
isRequired: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule2)).toBe('PropTypes.shape({a: PropTypes.string.isRequired,b: PropTypes.number})');
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 123 }, 'type', rule2, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({ b: 123 }, 'type', rule2, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
// exact
|
||||||
|
it('should validate correctly with valid exact prop type', () => {
|
||||||
|
const rule = {
|
||||||
|
type: 'exact',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
propType: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'b',
|
||||||
|
propType: {
|
||||||
|
type: 'number',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.exact({a: PropTypes.string.isRequired,b: PropTypes.number.isRequired})');
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 123 }, 'type', rule, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 'Photos' }, 'type', rule, 'TestComponent')).toBe(false);
|
||||||
|
|
||||||
|
// isRequired
|
||||||
|
const rule2 = {
|
||||||
|
type: 'exact',
|
||||||
|
value: [
|
||||||
|
{
|
||||||
|
name: 'a',
|
||||||
|
propType: {
|
||||||
|
type: 'string',
|
||||||
|
isRequired: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'b',
|
||||||
|
propType: {
|
||||||
|
type: 'number',
|
||||||
|
isRequired: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
expect(transformPropTypesRuleToString(rule2)).toBe('PropTypes.exact({a: PropTypes.string.isRequired,b: PropTypes.number})');
|
||||||
|
expect(checkPropTypes({ a: 'News', b: 123 }, 'type', rule2, 'TestComponent')).toBe(true);
|
||||||
|
expect(checkPropTypes({ b: 123 }, 'type', rule2, 'TestComponent')).toBe(false);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user