Skip to content

Commit

Permalink
feat: allow access to parent schema (and unlimited ancestors!) in tes…
Browse files Browse the repository at this point in the history
…t context (#556)

* Allow access to parent schema in test context

* Removed the fact that I reformatted this line

* Remove the change in the test

* Remove change in test

* Hardened test cases

* Much better api, solves far more than just accessing parent schema, allows access to unlimited ancestors

* Updated to array API for accessing

* Fix incorrect splice - the goal was to simply prepend the current schema context to the from array

* Don't like this, but it's the only way I could confirm the correct context in the array.

* Make `from` effectively immutable between tests

* Remove test comment

* Refactor test to simplify

Co-authored-by: adam <adam.jenkins@smartsti.com>
  • Loading branch information
akmjenkins and adam authored May 20, 2020
1 parent b4e5a00 commit db35920
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/array.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ inherits(ArraySchema, MixedSchema, {
path,
strict: true,
parent: value,
index: idx,
originalValue: originalValue[idx],
};

Expand Down
6 changes: 5 additions & 1 deletion src/mixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ const proto = (SchemaType.prototype = {
originalValue,
sync,
};

if (options.from) {
validationParams.from = options.from;
}

let initialTests = [];

if (this._typeError) initialTests.push(this._typeError(validationParams));
Expand Down Expand Up @@ -576,7 +581,6 @@ for (const method of ['validate', 'validateSync'])
value,
options.context,
);

return schema[method](parent && parent[parentPath], {
...options,
parent,
Expand Down
11 changes: 10 additions & 1 deletion src/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ inherits(ObjectSchema, MixedSchema, {
let originalValue =
opts.originalValue != null ? opts.originalValue : _value;

let from = [{ schema: this, value: originalValue }, ...(opts.from || [])];

endEarly = this._option('abortEarly', opts);
recursive = this._option('recursive', opts);

opts = { ...opts, __validating: true, originalValue };
opts = { ...opts, __validating: true, originalValue, from };

return MixedSchema.prototype._validate
.call(this, _value, opts)
Expand All @@ -146,6 +148,12 @@ inherits(ObjectSchema, MixedSchema, {
return value;
}

from = originalValue
? [...from]
: [
{ schema: this, value: originalValue || value },
...(opts.from || []),
];
originalValue = originalValue || value;

let validations = this._nodes.map(key => {
Expand All @@ -158,6 +166,7 @@ inherits(ObjectSchema, MixedSchema, {
let innerOptions = {
...opts,
path,
from,
parent: value,
originalValue: originalValue[key],
};
Expand Down
40 changes: 40 additions & 0 deletions test/mixed.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,46 @@ describe('Mixed Types ', () => {
called.should.equal(true);
});

it('tests should be able to access nested parent', async () => {
let finalFrom,finalOptions;
let testFixture = {
firstField: 'test',
second: [
{
thirdField: 'test3',
},
{
thirdField: 'test4',
},
],
};

let third = object({
thirdField: mixed().test({
test() {
finalFrom = this.from;
finalOptions = this.options;
return true;
},
}),
});

let second = array().of(third);

let first = object({
firstField: mixed(),
second,
});

await first.validate(testFixture);

finalFrom[0].value.should.eql(testFixture.second[finalOptions.index]);
finalFrom[0].schema.should.equal(third);
finalFrom[1].value.should.equal(testFixture);
finalFrom[1].schema.should.equal(first);

});

it('tests can return an error', () => {
let inst = mixed().test({
message: 'invalid ${path}',
Expand Down

0 comments on commit db35920

Please sign in to comment.