From 7e88e0be6b7b641945a630eb36ee589156adc455 Mon Sep 17 00:00:00 2001
From: Heath C <51679588+heath-freenome@users.noreply.github.com>
Date: Mon, 31 Oct 2022 06:55:21 -0700
Subject: [PATCH] feature: Support raw validation in the playground (#3217)
---
CHANGELOG.md | 4 ++
packages/playground/src/app.jsx | 8 +--
packages/utils/src/types.ts | 12 ++++-
.../utils/test/testUtils/getTestValidator.ts | 1 +
packages/validator-ajv6/src/validator.ts | 52 ++++++++++++-------
.../test/utilsTests/getTestValidator.ts | 6 +++
packages/validator-ajv8/src/validator.ts | 52 ++++++++++++-------
.../test/utilsTests/getTestValidator.ts | 6 +++
8 files changed, 97 insertions(+), 44 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 888e43635a..89f72c5790 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -50,20 +50,24 @@ should change the heading of the (upcoming) version to include a major version b
- `StrictRJSFSchema` was added as the alias to `JSON7Schema` and `RJSFSchema` was modified to be `StrictRJSFSchema & GenericObjectType`
- This new generic was added BEFORE the newly added `F = any` generic because it is assumed that more people will want to change the schema than the formContext types
- This provides future support for the newer draft versions of the schema
+- Updated the `ValidatorType` interface to add a new `rawValidation()` method for use by the playground
## @rjsf/validator-ajv6
- Fixed a few type casts given the new expanded definition of the `RJSFSchema` type change
- Deprecated this library in favor of the `@rjsf/validator-ajv8`
+- Refactored out the `rawValidation()` function for use by the playground
## @rjsf/validator-ajv8
- Updated the typing to add the new `S extends StrictRJSFSchema = RJSFSchema` generic and fixed up type casts
- Added the `AjvClass` prop to the `CustomValidatorOptionsType` to support using the `Ajv2019` or `Ajv2020` class implementation instead of the default `Ajv` class; fixing [#3189](https://github.com/rjsf-team/react-jsonschema-form/issues/3189)
+- Refactored out the `rawValidation()` function for use by the playground
## Dev / docs / playground
- Updated the `5.x upgrade guide` and `utility-functions.md` to document the new `StrictRJSFSchema` and `S` generic
- Updated the `validation` guide to document the new `AjvClass` prop on `CustomValidatorOptionsType` and mentioning the deprecation of `@rjsf/validator-ajv6`
- Updated the playground to add support for using the AJV 8 validator with the `draft-2019-09` and `draft-2020-12` schemas and to make the `AJV8` validator the default validator, marking `AJV6` as deprecated
- Updated all the documentation to switch to Typescript notation where missing along with switching to using the `@rjsf/validator-ajv8` validator as the default
+- Added a way of doing a raw Ajv validation in the playground to determine whether an issue is with RJSF or Ajv
# 5.0.0-beta.11
diff --git a/packages/playground/src/app.jsx b/packages/playground/src/app.jsx
index 04993b9320..6ca58dd1eb 100644
--- a/packages/playground/src/app.jsx
+++ b/packages/playground/src/app.jsx
@@ -285,17 +285,17 @@ class CopyLink extends Component {
}
}
-const EMPTY_RAW_VALIDATION = { errors: undefined, validationError: undefined };
-
function RawValidatorTest({ validator, schema, formData }) {
const [rawValidation, setRawValidation] = React.useState();
- const { errors, validationError } = rawValidation || EMPTY_RAW_VALIDATION;
const handleClearClick = () => setRawValidation(undefined);
const handleRawClick = () => setRawValidation(validator.rawValidation(schema, formData));
let displayErrors;
if (rawValidation) {
- displayErrors = errors ? JSON.stringify(errors, null, 2) : "No AJV errors encountered";
+ displayErrors =
+ rawValidation.errors || rawValidation.validationError ?
+ JSON.stringify(rawValidation, null, 2) :
+ "No AJV errors encountered";
}
return (
diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts
index 3d63b63394..398cb80492 100644
--- a/packages/utils/src/types.ts
+++ b/packages/utils/src/types.ts
@@ -902,10 +902,20 @@ export interface ValidatorType<
* false.
*
* @param schema - The schema against which to validate the form data * @param schema
- * @param formData- - The form data to validate
+ * @param formData - The form data to validate
* @param rootSchema - The root schema used to provide $ref resolutions
*/
isValid(schema: S, formData: T, rootSchema: S): boolean;
+ /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
+ * by the playground. Returns the `errors` from the validation
+ *
+ * @param schema - The schema against which to validate the form data * @param schema
+ * @param formData - The form data to validate
+ */
+ rawValidation(
+ schema: S,
+ formData?: T
+ ): { errors?: Result[]; validationError?: Error };
}
/** The `SchemaUtilsType` interface provides a wrapper around the publicly exported APIs in the `@rjsf/utils/schema`
diff --git a/packages/utils/test/testUtils/getTestValidator.ts b/packages/utils/test/testUtils/getTestValidator.ts
index 18b6299c2b..04f956efee 100644
--- a/packages/utils/test/testUtils/getTestValidator.ts
+++ b/packages/utils/test/testUtils/getTestValidator.ts
@@ -45,6 +45,7 @@ export default function getTestValidator({
}
return [];
}),
+ rawValidation: jest.fn().mockImplementation(() => {}),
setReturnValues({ isValid, data, errorList }: TestValidatorParams) {
if (isValid !== undefined) {
testValidator._isValid = isValid;
diff --git a/packages/validator-ajv6/src/validator.ts b/packages/validator-ajv6/src/validator.ts
index dc031804c7..0970379ed1 100644
--- a/packages/validator-ajv6/src/validator.ts
+++ b/packages/validator-ajv6/src/validator.ts
@@ -27,7 +27,9 @@ const ROOT_SCHEMA_PREFIX = "__rjsf_rootSchema";
*
* @deprecated in favor of the `@rjsf/validator-ajv8
*/
-export default class AJV6Validator implements ValidatorType {
+export default class AJV6Validator
+ implements ValidatorType
+{
/** The AJV instance to use for all validations
*
* @private
@@ -198,12 +200,8 @@ export default class AJV6Validator implements ValidatorType {
* @private
*/
private transformRJSFValidationErrors(
- errors: Ajv["errors"] = []
+ errors: ErrorObject[] = []
): RJSFValidationError[] {
- if (errors === null) {
- return [];
- }
-
return errors.map((e: ErrorObject) => {
const { dataPath, keyword, message, params, schemaPath } = e;
const property = `${dataPath}`;
@@ -220,6 +218,31 @@ export default class AJV6Validator implements ValidatorType {
});
}
+ /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
+ * by the playground. Returns the `errors` from the validation
+ *
+ * @param schema - The schema against which to validate the form data * @param schema
+ * @param formData - The form data to validate
+ */
+ rawValidation(
+ schema: RJSFSchema,
+ formData?: T
+ ): { errors?: Result[]; validationError?: Error } {
+ let validationError: Error | undefined = undefined;
+ try {
+ this.ajv.validate(schema, formData);
+ } catch (err) {
+ validationError = err as Error;
+ }
+
+ const errors = this.ajv.errors || undefined;
+
+ // Clear errors to prevent persistent errors, see #1104
+ this.ajv.errors = null;
+
+ return { errors: errors as unknown as Result[], validationError };
+ }
+
/** This function processes the `formData` with an optional user contributed `customValidate` function, which receives
* the form data and a `errorHandler` function that will be used to add custom validation errors for each field. Also
* supports a `transformErrors` function that will take the raw AJV validation errors, prior to custom validation and
@@ -238,7 +261,7 @@ export default class AJV6Validator implements ValidatorType {
): ValidationData {
// Include form data with undefined values, which is required for validation.
const rootSchema = schema;
- const newFormData = getDefaultFormState(
+ const newFormData = getDefaultFormState(
this,
schema,
formData,
@@ -246,22 +269,13 @@ export default class AJV6Validator implements ValidatorType {
true
) as T;
- let validationError: Error | null = null;
- try {
- this.ajv.validate(schema, newFormData);
- } catch (err) {
- validationError = err as Error;
- }
-
- let errors = this.transformRJSFValidationErrors(this.ajv.errors);
- // Clear errors to prevent persistent errors, see #1104
-
- this.ajv.errors = null;
+ const rawErrors = this.rawValidation(schema, newFormData);
+ const { validationError } = rawErrors;
+ let errors = this.transformRJSFValidationErrors(rawErrors.errors);
const noProperMetaSchema =
validationError &&
validationError.message &&
- typeof validationError.message === "string" &&
validationError.message.includes("no schema with key or ref ");
if (noProperMetaSchema) {
diff --git a/packages/validator-ajv6/test/utilsTests/getTestValidator.ts b/packages/validator-ajv6/test/utilsTests/getTestValidator.ts
index 4a3ba70822..e6c9b28522 100644
--- a/packages/validator-ajv6/test/utilsTests/getTestValidator.ts
+++ b/packages/validator-ajv6/test/utilsTests/getTestValidator.ts
@@ -37,6 +37,12 @@ export default function getTestValidator(
isValid(schema: RJSFSchema, formData: T, rootSchema: RJSFSchema): boolean {
return validator.isValid(schema, formData, rootSchema);
},
+ rawValidation(
+ schema: RJSFSchema,
+ formData?: T
+ ): { errors?: Result[]; validationError?: Error } {
+ return validator.rawValidation(schema, formData);
+ },
// This is intentionally a no-op as we are using the real validator here
setReturnValues() {},
};
diff --git a/packages/validator-ajv8/src/validator.ts b/packages/validator-ajv8/src/validator.ts
index c601d0a6ac..4988577ed8 100644
--- a/packages/validator-ajv8/src/validator.ts
+++ b/packages/validator-ajv8/src/validator.ts
@@ -217,12 +217,8 @@ export default class AJV8Validator<
* @private
*/
private transformRJSFValidationErrors(
- errors: Ajv["errors"] = []
+ errors: ErrorObject[] = []
): RJSFValidationError[] {
- if (errors === null) {
- return [];
- }
-
return errors.map((e: ErrorObject) => {
const { instancePath, keyword, message, params, schemaPath } = e;
const property = instancePath.replace(/\//g, ".");
@@ -239,6 +235,34 @@ export default class AJV8Validator<
});
}
+ /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
+ * by the playground. Returns the `errors` from the validation
+ *
+ * @param schema - The schema against which to validate the form data * @param schema
+ * @param formData - The form data to validate
+ */
+ rawValidation(
+ schema: RJSFSchema,
+ formData?: T
+ ): { errors?: Result[]; validationError?: Error } {
+ let validationError: Error | undefined = undefined;
+ try {
+ this.ajv.validate(schema, formData);
+ } catch (err) {
+ validationError = err as Error;
+ }
+
+ if (typeof this.localizer === "function") {
+ this.localizer(this.ajv.errors);
+ }
+ const errors = this.ajv.errors || undefined;
+
+ // Clear errors to prevent persistent errors, see #1104
+ this.ajv.errors = null;
+
+ return { errors: errors as unknown as Result[], validationError };
+ }
+
/** This function processes the `formData` with an optional user contributed `customValidate` function, which receives
* the form data and a `errorHandler` function that will be used to add custom validation errors for each field. Also
* supports a `transformErrors` function that will take the raw AJV validation errors, prior to custom validation and
@@ -265,25 +289,13 @@ export default class AJV8Validator<
true
) as T;
- let validationError: Error | null = null;
- try {
- this.ajv.validate(schema, newFormData);
- } catch (err) {
- validationError = err as Error;
- }
-
- if (typeof this.localizer === "function") {
- this.localizer(this.ajv.errors);
- }
- let errors = this.transformRJSFValidationErrors(this.ajv.errors);
- // Clear errors to prevent persistent errors, see #1104
-
- this.ajv.errors = null;
+ const rawErrors = this.rawValidation(schema, newFormData);
+ const { validationError } = rawErrors;
+ let errors = this.transformRJSFValidationErrors(rawErrors.errors);
const noProperMetaSchema =
validationError &&
validationError.message &&
- typeof validationError.message === "string" &&
validationError.message.includes("no schema with key or ref ");
if (noProperMetaSchema) {
diff --git a/packages/validator-ajv8/test/utilsTests/getTestValidator.ts b/packages/validator-ajv8/test/utilsTests/getTestValidator.ts
index 4a3ba70822..e6c9b28522 100644
--- a/packages/validator-ajv8/test/utilsTests/getTestValidator.ts
+++ b/packages/validator-ajv8/test/utilsTests/getTestValidator.ts
@@ -37,6 +37,12 @@ export default function getTestValidator(
isValid(schema: RJSFSchema, formData: T, rootSchema: RJSFSchema): boolean {
return validator.isValid(schema, formData, rootSchema);
},
+ rawValidation(
+ schema: RJSFSchema,
+ formData?: T
+ ): { errors?: Result[]; validationError?: Error } {
+ return validator.rawValidation(schema, formData);
+ },
// This is intentionally a no-op as we are using the real validator here
setReturnValues() {},
};