From ea78a4e41a9e1e4b7f3fb86c9d61020c89652804 Mon Sep 17 00:00:00 2001 From: Krist Wongsuphasawat Date: Tue, 31 Mar 2020 17:08:59 -0700 Subject: [PATCH] feat: add validator package (#322) * feat: add validator package * test: add unit tests * feat: add legacy function * fix: rename --- packages/superset-ui-validator/README.md | 23 +++++++++++++++ packages/superset-ui-validator/package.json | 29 +++++++++++++++++++ packages/superset-ui-validator/src/index.ts | 5 ++++ .../src/legacyValidateInteger.ts | 12 ++++++++ .../src/legacyValidateNumber.ts | 12 ++++++++ .../src/validateInteger.ts | 12 ++++++++ .../src/validateNonEmpty.ts | 8 +++++ .../src/validateNumber.ts | 12 ++++++++ .../test/legacyValidateInteger.test.ts | 20 +++++++++++++ .../test/legacyValidateNumber.test.ts | 20 +++++++++++++ .../test/validateInteger.test.ts | 18 ++++++++++++ .../test/validateNonEmpty.test.ts | 15 ++++++++++ .../test/validateNumber.test.ts | 18 ++++++++++++ test/setup.ts | 4 +++ 14 files changed, 208 insertions(+) create mode 100644 packages/superset-ui-validator/README.md create mode 100644 packages/superset-ui-validator/package.json create mode 100644 packages/superset-ui-validator/src/index.ts create mode 100644 packages/superset-ui-validator/src/legacyValidateInteger.ts create mode 100644 packages/superset-ui-validator/src/legacyValidateNumber.ts create mode 100644 packages/superset-ui-validator/src/validateInteger.ts create mode 100644 packages/superset-ui-validator/src/validateNonEmpty.ts create mode 100644 packages/superset-ui-validator/src/validateNumber.ts create mode 100644 packages/superset-ui-validator/test/legacyValidateInteger.test.ts create mode 100644 packages/superset-ui-validator/test/legacyValidateNumber.test.ts create mode 100644 packages/superset-ui-validator/test/validateInteger.test.ts create mode 100644 packages/superset-ui-validator/test/validateNonEmpty.test.ts create mode 100644 packages/superset-ui-validator/test/validateNumber.test.ts diff --git a/packages/superset-ui-validator/README.md b/packages/superset-ui-validator/README.md new file mode 100644 index 0000000000..d4044c1834 --- /dev/null +++ b/packages/superset-ui-validator/README.md @@ -0,0 +1,23 @@ +## @superset-ui/validator + +[![Version](https://img.shields.io/npm/v/@superset-ui/validator.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/validator.svg?style=flat) +[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-validator&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-validator) + +Description + +#### Example usage + +```js +import { xxx } from '@superset-ui/validator'; +``` + +#### API + +`fn(args)` + +- Do something + +### Development + +`@data-ui/build-config` is used to manage the build configuration for this package including babel +builds, jest testing, eslint, and prettier. diff --git a/packages/superset-ui-validator/package.json b/packages/superset-ui-validator/package.json new file mode 100644 index 0000000000..bb8bc39e3c --- /dev/null +++ b/packages/superset-ui-validator/package.json @@ -0,0 +1,29 @@ +{ + "name": "@superset-ui/validator", + "version": "0.0.0", + "description": "Superset UI validator", + "sideEffects": false, + "main": "lib/index.js", + "module": "esm/index.js", + "files": [ + "esm", + "lib" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/apache-superset/superset-ui.git" + }, + "keywords": ["superset"], + "author": "Superset", + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/apache-superset/superset-ui/issues" + }, + "homepage": "https://github.com/apache-superset/superset-ui#readme", + "publishConfig": { + "access": "public" + }, + "peerDependencies": { + "@superset-ui/translation": "^0.12.0" + } +} diff --git a/packages/superset-ui-validator/src/index.ts b/packages/superset-ui-validator/src/index.ts new file mode 100644 index 0000000000..edc93a7acf --- /dev/null +++ b/packages/superset-ui-validator/src/index.ts @@ -0,0 +1,5 @@ +export { default as legacyValidateInteger } from './legacyValidateInteger'; +export { default as legacyValidateNumber } from './legacyValidateNumber'; +export { default as validateInteger } from './validateInteger'; +export { default as validateNumber } from './validateNumber'; +export { default as validateNonEmpty } from './validateNonEmpty'; diff --git a/packages/superset-ui-validator/src/legacyValidateInteger.ts b/packages/superset-ui-validator/src/legacyValidateInteger.ts new file mode 100644 index 0000000000..ca38d39f7d --- /dev/null +++ b/packages/superset-ui-validator/src/legacyValidateInteger.ts @@ -0,0 +1,12 @@ +import { t } from '@superset-ui/translation'; + +/** + * formerly called integer() + * @param v + */ +export default function legacyValidateInteger(v: unknown) { + if (v && (isNaN(v as number) || parseInt(v as string, 10) !== Number(v))) { + return t('is expected to be an integer'); + } + return false; +} diff --git a/packages/superset-ui-validator/src/legacyValidateNumber.ts b/packages/superset-ui-validator/src/legacyValidateNumber.ts new file mode 100644 index 0000000000..062d30b025 --- /dev/null +++ b/packages/superset-ui-validator/src/legacyValidateNumber.ts @@ -0,0 +1,12 @@ +import { t } from '@superset-ui/translation'; + +/** + * formerly called numeric() + * @param v + */ +export default function numeric(v: unknown) { + if (v && isNaN(v as number)) { + return t('is expected to be a number'); + } + return false; +} diff --git a/packages/superset-ui-validator/src/validateInteger.ts b/packages/superset-ui-validator/src/validateInteger.ts new file mode 100644 index 0000000000..e761c274d0 --- /dev/null +++ b/packages/superset-ui-validator/src/validateInteger.ts @@ -0,0 +1,12 @@ +import { t } from '@superset-ui/translation'; + +export default function validateInteger(v: unknown) { + if ( + (typeof v === 'string' && v.trim().length > 0 && Number.isInteger(Number(v.trim()))) || + (typeof v === 'number' && Number.isInteger(v)) + ) { + return false; + } + + return t('is expected to be an integer'); +} diff --git a/packages/superset-ui-validator/src/validateNonEmpty.ts b/packages/superset-ui-validator/src/validateNonEmpty.ts new file mode 100644 index 0000000000..e4b28235b5 --- /dev/null +++ b/packages/superset-ui-validator/src/validateNonEmpty.ts @@ -0,0 +1,8 @@ +import { t } from '@superset-ui/translation'; + +export default function validateNonEmpty(v: unknown) { + if (v === null || typeof v === 'undefined' || v === '' || (Array.isArray(v) && v.length === 0)) { + return t('cannot be empty'); + } + return false; +} diff --git a/packages/superset-ui-validator/src/validateNumber.ts b/packages/superset-ui-validator/src/validateNumber.ts new file mode 100644 index 0000000000..a8a6f1a6de --- /dev/null +++ b/packages/superset-ui-validator/src/validateNumber.ts @@ -0,0 +1,12 @@ +import { t } from '@superset-ui/translation'; + +export default function validateInteger(v: unknown) { + if ( + (typeof v === 'string' && v.trim().length > 0 && Number.isFinite(Number(v.trim()))) || + (typeof v === 'number' && Number.isFinite(v)) + ) { + return false; + } + + return t('is expected to be a number'); +} diff --git a/packages/superset-ui-validator/test/legacyValidateInteger.test.ts b/packages/superset-ui-validator/test/legacyValidateInteger.test.ts new file mode 100644 index 0000000000..b342e3cd46 --- /dev/null +++ b/packages/superset-ui-validator/test/legacyValidateInteger.test.ts @@ -0,0 +1,20 @@ +import { legacyValidateInteger } from '../src'; + +describe('legacyValidateInteger()', () => { + it('returns the warning message if invalid', () => { + expect(legacyValidateInteger(10.1)).toBeTruthy(); + expect(legacyValidateInteger('abc')).toBeTruthy(); + expect(legacyValidateInteger(Infinity)).toBeTruthy(); + }); + it('returns false if the input is valid', () => { + // superset seems to operate on this incorrect behavior at the moment + expect(legacyValidateInteger(NaN)).toBeFalsy(); + expect(legacyValidateInteger(undefined)).toBeFalsy(); + expect(legacyValidateInteger(null)).toBeFalsy(); + expect(legacyValidateInteger('')).toBeFalsy(); + + expect(legacyValidateInteger(0)).toBeFalsy(); + expect(legacyValidateInteger(10)).toBeFalsy(); + expect(legacyValidateInteger('10')).toBeFalsy(); + }); +}); diff --git a/packages/superset-ui-validator/test/legacyValidateNumber.test.ts b/packages/superset-ui-validator/test/legacyValidateNumber.test.ts new file mode 100644 index 0000000000..1f45990ea1 --- /dev/null +++ b/packages/superset-ui-validator/test/legacyValidateNumber.test.ts @@ -0,0 +1,20 @@ +import { legacyValidateNumber } from '../src'; + +describe('legacyValidateNumber()', () => { + it('returns the warning message if invalid', () => { + expect(legacyValidateNumber('abc')).toBeTruthy(); + }); + it('returns false if the input is valid', () => { + // superset seems to operate on this incorrect behavior at the moment + expect(legacyValidateNumber(NaN)).toBeFalsy(); + expect(legacyValidateNumber(Infinity)).toBeFalsy(); + expect(legacyValidateNumber(undefined)).toBeFalsy(); + expect(legacyValidateNumber(null)).toBeFalsy(); + expect(legacyValidateNumber('')).toBeFalsy(); + + expect(legacyValidateNumber(0)).toBeFalsy(); + expect(legacyValidateNumber(10.1)).toBeFalsy(); + expect(legacyValidateNumber(10)).toBeFalsy(); + expect(legacyValidateNumber('10')).toBeFalsy(); + }); +}); diff --git a/packages/superset-ui-validator/test/validateInteger.test.ts b/packages/superset-ui-validator/test/validateInteger.test.ts new file mode 100644 index 0000000000..2f192b980f --- /dev/null +++ b/packages/superset-ui-validator/test/validateInteger.test.ts @@ -0,0 +1,18 @@ +import { validateInteger } from '../src'; + +describe('validateInteger()', () => { + it('returns the warning message if invalid', () => { + expect(validateInteger(10.1)).toBeTruthy(); + expect(validateInteger(NaN)).toBeTruthy(); + expect(validateInteger(Infinity)).toBeTruthy(); + expect(validateInteger(undefined)).toBeTruthy(); + expect(validateInteger(null)).toBeTruthy(); + expect(validateInteger('abc')).toBeTruthy(); + expect(validateInteger('')).toBeTruthy(); + }); + it('returns false if the input is valid', () => { + expect(validateInteger(0)).toBeFalsy(); + expect(validateInteger(10)).toBeFalsy(); + expect(validateInteger('10')).toBeFalsy(); + }); +}); diff --git a/packages/superset-ui-validator/test/validateNonEmpty.test.ts b/packages/superset-ui-validator/test/validateNonEmpty.test.ts new file mode 100644 index 0000000000..43a40f3d08 --- /dev/null +++ b/packages/superset-ui-validator/test/validateNonEmpty.test.ts @@ -0,0 +1,15 @@ +import { validateNonEmpty } from '../src'; + +describe('validateNonEmpty()', () => { + it('returns the warning message if invalid', () => { + expect(validateNonEmpty([])).toBeTruthy(); + expect(validateNonEmpty(undefined)).toBeTruthy(); + expect(validateNonEmpty(null)).toBeTruthy(); + expect(validateNonEmpty('')).toBeTruthy(); + }); + it('returns false if the input is valid', () => { + expect(validateNonEmpty(0)).toBeFalsy(); + expect(validateNonEmpty(10)).toBeFalsy(); + expect(validateNonEmpty('abc')).toBeFalsy(); + }); +}); diff --git a/packages/superset-ui-validator/test/validateNumber.test.ts b/packages/superset-ui-validator/test/validateNumber.test.ts new file mode 100644 index 0000000000..eecbea394b --- /dev/null +++ b/packages/superset-ui-validator/test/validateNumber.test.ts @@ -0,0 +1,18 @@ +import { validateNumber } from '../src'; + +describe('validateNumber()', () => { + it('returns the warning message if invalid', () => { + expect(validateNumber(NaN)).toBeTruthy(); + expect(validateNumber(Infinity)).toBeTruthy(); + expect(validateNumber(undefined)).toBeTruthy(); + expect(validateNumber(null)).toBeTruthy(); + expect(validateNumber('abc')).toBeTruthy(); + expect(validateNumber('')).toBeTruthy(); + }); + it('returns false if the input is valid', () => { + expect(validateNumber(0)).toBeFalsy(); + expect(validateNumber(10.1)).toBeFalsy(); + expect(validateNumber(10)).toBeFalsy(); + expect(validateNumber('10')).toBeFalsy(); + }); +}); diff --git a/test/setup.ts b/test/setup.ts index f568acb35b..c36712435c 100644 --- a/test/setup.ts +++ b/test/setup.ts @@ -1,3 +1,7 @@ +import { configure } from '@superset-ui/translation'; + +configure(); + const caches = {}; class Cache {