From 947c6218225e8b88df604cb3fa964e1298b18b84 Mon Sep 17 00:00:00 2001 From: liujuping Date: Thu, 25 Jan 2024 15:47:48 +0800 Subject: [PATCH] test(utils): add more test case for checkPropTypes --- packages/utils/src/check-prop-types.ts | 10 ++- .../utils/test/src/check-prop-types.test.ts | 65 +++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/packages/utils/src/check-prop-types.ts b/packages/utils/src/check-prop-types.ts index 89555c70b..dc9ce31ed 100644 --- a/packages/utils/src/check-prop-types.ts +++ b/packages/utils/src/check-prop-types.ts @@ -8,13 +8,13 @@ import { Logger } from './logger'; const PropTypes2 = factoryWithTypeCheckers(ReactIs.isElement, true); const logger = new Logger({ level: 'warn', bizName: 'utils' }); -export function transformPropTypesRuleToString(rule: IPublicTypePropType): string { +export function transformPropTypesRuleToString(rule: IPublicTypePropType | string): string { if (!rule) { return 'PropTypes.any'; } if (typeof rule === 'string') { - return `PropTypes.${rule}`; + return rule.startsWith('PropTypes.') ? rule : `PropTypes.${rule}`; } if (isRequiredPropType(rule)) { @@ -34,7 +34,11 @@ export function transformPropTypesRuleToString(rule: IPublicTypePropType): strin case 'shape': case 'exact': return `PropTypes.${type}({${value.map((item: any) => `${item.name}: ${transformPropTypesRuleToString(item.propType)}`).join(',')}})`; + default: + logger.error(`Unknown prop type: ${type}`); } + + return 'PropTypes.any'; } export function checkPropTypes(value: any, name: string, rule: any, componentName: string): boolean { @@ -45,7 +49,7 @@ export function checkPropTypes(value: any, name: string, rule: any, componentNam } if (typeof rule === 'string') { // eslint-disable-next-line no-new-func - ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${rule}`)(PropTypes2); + ruleFunction = new Function(`"use strict"; const PropTypes = arguments[0]; return ${transformPropTypesRuleToString(rule)}`)(PropTypes2); } if (!ruleFunction || typeof ruleFunction !== 'function') { logger.warn('checkPropTypes should have a function type rule argument'); diff --git a/packages/utils/test/src/check-prop-types.test.ts b/packages/utils/test/src/check-prop-types.test.ts index c1902bec3..74146f2d9 100644 --- a/packages/utils/test/src/check-prop-types.test.ts +++ b/packages/utils/test/src/check-prop-types.test.ts @@ -12,6 +12,26 @@ describe('checkPropTypes', () => { expect(checkPropTypes('123', 'age', PropTypes.number, 'TestComponent')).toBe(false); }); + it('should validate correctly with valid object prop type', () => { + expect(checkPropTypes({ a: 123 }, 'age', PropTypes.object, 'TestComponent')).toBe(true); + expect(checkPropTypes({ a: '123' }, 'age', PropTypes.object, 'TestComponent')).toBe(true); + }); + + it('should validate correctly with valid object string prop type', () => { + expect(checkPropTypes({ a: 123 }, 'age', 'object', 'TestComponent')).toBe(true); + expect(checkPropTypes({ a: '123' }, 'age', 'object', 'TestComponent')).toBe(true); + }); + + it('should validate correctly with valid isRequired prop type', () => { + const rule = { + type: 'string', + isRequired: true, + }; + expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.string.isRequired'); + expect(checkPropTypes('News', 'type', rule, 'TestComponent')).toBe(true); + expect(checkPropTypes(undefined, 'type', rule, 'TestComponent')).toBe(false); + }); + it('should handle custom rule functions correctly', () => { const customRule = (props, propName) => { if (props[propName] !== 123) { @@ -28,6 +48,11 @@ describe('checkPropTypes', () => { expect(result).toBe(true); }); + it('should interpret and validate a rule given as a string', () => { + expect(checkPropTypes(123, 'age', 'number', 'TestComponent')).toBe(true); + expect(checkPropTypes('123', 'age', 'string', 'TestComponent')).toBe(true); + }); + it('should log a warning for invalid rule type', () => { const result = checkPropTypes(123, 'age', 123, 'TestComponent'); expect(result).toBe(true); @@ -60,6 +85,46 @@ describe('checkPropTypes', () => { expect(checkPropTypes({}, 'type', rule, 'TestComponent')).toBe(false); }); + it('should validate correctly with valid oneOfType prop type', () => { + const rule = { + type: 'oneOfType', + value: [ + 'bool', + { + type: 'shape', + value: [ + { + name: 'type', + propType: { + type: 'oneOf', + value: ['JSExpression'], + } + }, + { + name: 'value', + propType: 'string', + }, + ], + }, + ], + }; + expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.oneOfType([PropTypes.bool, PropTypes.shape({type: PropTypes.oneOf(["JSExpression"]),value: PropTypes.string})])'); + expect(checkPropTypes(true, 'type', rule, 'TestComponent')).toBe(true); + expect(checkPropTypes({ type: 'JSExpression', value: '1 + 1 === 2' }, 'type', rule, 'TestComponent')).toBe(true); + expect(checkPropTypes({ type: 'JSExpression' }, 'type', rule, 'TestComponent')).toBe(true); + expect(checkPropTypes({ type: 'JSExpression', value: 123 }, 'type', rule, 'TestComponent')).toBe(false); + }); + + it('should log a warning for invalid type', () => { + const rule = { + type: 'inval', + value: ['News', 'Photos'], + } + expect(transformPropTypesRuleToString(rule)).toBe('PropTypes.any'); + expect(checkPropTypes('News', 'type', rule, 'TestComponent')).toBe(true); + expect(checkPropTypes('Others', 'type', rule, 'TestComponent')).toBe(true); + }); + // arrayOf it('should validate correctly with valid arrayOf prop type', () => { const rule = {