Repository: jquense/yup
Pull request #1820 (2022-11-02 20:22:53)

Fixes


Patch:
diff --git a/src/Lazy.ts b/src/Lazy.ts
index 6afc3c5..c6d505c 100644
--- a/src/Lazy.ts
+++ b/src/Lazy.ts
@@ -101,9 +101,15 @@ class Lazy<T, TContext = AnyObject, TFlags extends Flags = any>
     return this._resolve(value, options).cast(value, options as any);
   }
 
-  asNestedTest(options: NestedTestConfig) {
-    let value = options.parent[options.index ?? options.key!];
-    return this._resolve(value, options).asNestedTest(options);
+  asNestedTest(config: NestedTestConfig) {
+    let { key, index, parent, options } = config;
+    let value = parent[index ?? key!];
+
+    return this._resolve(value, {
+      ...options,
+      value,
+      parent,
+    }).asNestedTest(config);
   }
 
   validate(value: any, options?: ValidateOptions<TContext>): Promise<T> {
diff --git a/src/schema.ts b/src/schema.ts
index 9dcd54f..92b6964 100644
--- a/src/schema.ts
+++ b/src/schema.ts
@@ -88,7 +88,9 @@ export type RunTest = (
 
 export type TestRunOptions = {
   tests: RunTest[];
-  args?: TestOptions;
+  path?: string | undefined;
+  options: InternalOptions;
+  originalValue: any;
   value: any;
 };
 
@@ -403,32 +405,13 @@ export default abstract class Schema<
     panic: (err: Error, value: unknown) => void,
     next: (err: ValidationError[], value: unknown) => void,
   ): void {
-    let {
-      sync,
-      path,
-      from = [],
-      originalValue = _value,
-      strict = this.spec.strict,
-    } = options;
+    let { path, originalValue = _value, strict = this.spec.strict } = options;
 
     let value = _value;
     if (!strict) {
       value = this._cast(value, { assert: false, ...options });
     }
 
-    // value is cast, we can check if it meets type requirements
-    let args = {
-      value,
-      path,
-      options,
-      originalValue,
-      schema: this,
-      label: this.spec.label,
-      spec: this.spec,
-      sync,
-      from,
-    };
-
     let initialTests = [];
     for (let test of Object.values(this.internalTests)) {
       if (test) initialTests.push(test);
@@ -436,8 +419,10 @@ export default abstract class Schema<
 
     this.runTests(
       {
-        args,
+        path,
         value,
+        originalValue,
+        options,
         tests: initialTests,
       },
       panic,
@@ -449,8 +434,10 @@ export default abstract class Schema<
 
         this.runTests(
           {
-            args,
+            path,
             value,
+            originalValue,
+            options,
             tests: this.tests,
           },
           panic,
@@ -467,12 +454,12 @@ export default abstract class Schema<
    * validations.
    */
   protected runTests(
-    options: TestRunOptions,
+    runOptions: TestRunOptions,
     panic: (err: Error, value: unknown) => void,
     next: (errors: ValidationError[], value: unknown) => void,
   ): void {
     let fired = false;
-    let { tests, args, value } = options;
+    let { tests, value, originalValue, path, options } = runOptions;
 
     let panicOnce = (arg: Error) => {
       if (fired) return;
@@ -491,6 +478,14 @@ export default abstract class Schema<
 
     if (!count) return nextOnce([]);
 
+    let args = {
+      value,
+      originalValue,
+      path,
+      options,
+      schema: this,
+    };
+
     for (let i = 0; i < tests.length; i++) {
       const test = tests[i];
 
diff --git a/src/util/createValidation.ts b/src/util/createValidation.ts
index 9ff261f..dc21e48 100644
--- a/src/util/createValidation.ts
+++ b/src/util/createValidation.ts
@@ -6,7 +6,6 @@ import {
   InternalOptions,
   ExtraParams,
   ISchema,
-  MessageParams,
 } from '../types';
 import Reference from '../Reference';
 import type { AnySchema } from '../schema';
@@ -45,12 +44,9 @@ export type TestFunction<T = unknown, TContext = {}> = (
 export type TestOptions<TSchema extends AnySchema = AnySchema> = {
   value: any;
   path?: string;
-  label?: string;
   options: InternalOptions;
   originalValue: any;
   schema: TSchema;
-  sync?: boolean;
-  spec: MessageParams['spec'];
 };
 
 export type TestConfig<TValue = unknown, TContext = {}> = {
@@ -78,21 +74,12 @@ export default function createValidation(config: {
   skipAbsent?: boolean;
 }) {
   function validate<TSchema extends AnySchema = AnySchema>(
-    {
-      value,
-      path = '',
-      label,
-      options,
-      originalValue,
-      spec,
-      sync,
-      ...rest
-    }: TestOptions<TSchema>,
+    { value, path = '', options, originalValue, schema }: TestOptions<TSchema>,
     panic: PanicCallback,
     next: NextCallback,
   ) {
     const { name, test, params, message, skipAbsent } = config;
-    let { parent, context, abortEarly = rest.schema.spec.abortEarly } = options;
+    let { parent, context, abortEarly = schema.spec.abortEarly } = options;
 
     function resolve<T>(item: T | Reference<T>) {
       return Ref.isRef(item) ? item.getValue(value, parent, context) : item;
@@ -102,9 +89,9 @@ export default function createValidation(config: {
       const nextParams = {
         value,
         originalValue,
-        label,
+        label: schema.spec.label,
         path: overrides.path || path,
-        spec,
+        spec: schema.spec,
         ...params,
         ...overrides.params,
       };
@@ -129,11 +116,12 @@ export default function createValidation(config: {
       path,
       parent,
       type: name,
+      from: options.from,
       createError,
       resolve,
       options,
       originalValue,
-      ...rest,
+      schema,
     };
 
     const handleResult = (validOrError: ReturnType<TestFunction>) => {
@@ -149,7 +137,7 @@ export default function createValidation(config: {
 
     const shouldSkip = skipAbsent && isAbsent(value);
 
-    if (!sync) {
+    if (!options.sync) {
       try {
         Promise.resolve(!shouldSkip ? test.call(ctx, value, ctx) : true).then(
           handleResult,


Test patch:
diff --git a/test/lazy.ts b/test/lazy.ts
index 42973e2..7ebaa3b 100644
--- a/test/lazy.ts
+++ b/test/lazy.ts
@@ -1,4 +1,4 @@
-import { lazy, mixed, AnyObject, MixedSchema } from '../src';
+import { lazy, object, mixed, AnyObject, MixedSchema } from '../src';
 
 describe('lazy', function () {
   it('should throw on a non-schema value', () => {
@@ -28,6 +28,19 @@ describe('lazy', function () {
       expect(mapper).toHaveBeenCalledWith(value, options);
     });
 
+    it('should call with context when nested: #1799', () => {
+      let context = { a: 1 };
+      let value = { lazy: 1 };
+      let options = { context };
+
+      object({
+        lazy: lazy(mapper),
+      }).validate(value, options);
+
+      lazy(mapper).validate(value, options);
+      expect(mapper).toHaveBeenCalledWith(value, options);
+    });
+
     it('should allow meta', () => {
       const meta = { a: 1 };
       const schema = lazy(mapper).meta(meta);
diff --git a/test/mixed.ts b/test/mixed.ts
index 6c6eb69..0ece481 100644
--- a/test/mixed.ts
+++ b/test/mixed.ts
@@ -505,7 +505,7 @@ describe('Mixed Types ', () => {
     });
 
     await first.validate(testFixture);
-    // console.log(finalFrom);
+
     expect(finalFrom[0].value).toEqual(testFixture.second[finalOptions.index]);
     expect(finalFrom[0].schema).toBe(third);
     expect(finalFrom[1].value).toBe(testFixture);