Skip to content

Commit

Permalink
Link to root. Closes #1979
Browse files Browse the repository at this point in the history
  • Loading branch information
hueniverse committed Jul 26, 2019
1 parent d8b42cd commit e666649
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
5 changes: 4 additions & 1 deletion lib/ref.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ exports.create = function (key, options = {}) {
if (context.root) {
Hoek.assert(!separator || key[0] !== separator, 'Cannot specify relative path with root prefix');
ref.ancestor = 'root';
if (!key) {
key = null;
}
}

if (separator &&
Expand All @@ -47,7 +50,7 @@ exports.create = function (key, options = {}) {
}
else {
if (ref.ancestor !== undefined) {
Hoek.assert(!separator || key[0] !== separator, 'Cannot combine prefix with ancestor option');
Hoek.assert(!separator || !key || key[0] !== separator, 'Cannot combine prefix with ancestor option');
}
else {
const [ancestor, slice] = internals.ancestor(key, separator);
Expand Down
4 changes: 2 additions & 2 deletions lib/types/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internals.Link = class extends Any {
}

const ref = this._inners.link[0].ref;
const perspective = state.schemas[ref.ancestor];
const perspective = ref.ancestor === 'root' ? state.schemas[state.schemas.length - 1] : state.schemas[ref.ancestor];
if (!perspective) {
return { value, errors: this.createError('link.depth', value, { ref }, state, prefs) };
}
Expand Down Expand Up @@ -68,7 +68,7 @@ internals.Link = class extends Any {
ref = Cast.ref(ref);

Hoek.assert(ref.type === 'value', 'Invalid reference type');
Hoek.assert(ref.ancestor > 0, 'Link cannot reference itself');
Hoek.assert(ref.ancestor === 'root' || ref.ancestor > 0, 'Link cannot reference itself');

const obj = this.clone();
obj._inners.link = [{ ref }];
Expand Down
42 changes: 42 additions & 0 deletions test/types/link.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,20 @@ describe('link', () => {
expect(schema.validate({ a: [1], b: { c: '2' } }).error).to.be.an.error('"a" must be one of [string, number]');
});

it('links schema cousin nodes (root)', () => {

const schema = Joi.object({
a: [Joi.string(), Joi.number()],
b: {
c: Joi.link('/a')
}
});

expect(schema.validate({ a: 1, b: { c: 2 } }).error).to.not.exist();
expect(schema.validate({ a: '1', b: { c: '2' } }).error).to.not.exist();
expect(schema.validate({ a: [1], b: { c: '2' } }).error).to.be.an.error('"a" must be one of [string, number]');
});

it('validates a recursive schema', () => {

const schema = Joi.object({
Expand Down Expand Up @@ -75,6 +89,34 @@ describe('link', () => {
]);
});

it('validates a recursive schema (root)', () => {

const schema = Joi.object({
name: Joi.string().required(),
keys: Joi.array()
.items(Joi.link('/'))
});

expect(schema.validate({ name: 'foo', keys: [{ name: 'bar' }] }).error).to.not.exist();

Helper.validate(schema, [
[{ name: 'foo' }, true],
[{ name: 'foo', keys: [] }, true],
[{ name: 'foo', keys: [{ name: 'bar' }] }, true],
[{ name: 'foo', keys: [{ name: 'bar', keys: [{ name: 'baz' }] }] }, true],
[{ name: 'foo', keys: [{ name: 'bar', keys: [{ name: 'baz', keys: [{ name: 'qux' }] }] }] }, true],
[{ name: 'foo', keys: [{ name: 'bar', keys: [{ name: 'baz', keys: [{ name: 42 }] }] }] }, false, null, {
message: '"keys[0].keys[0].keys[0].name" must be a string',
details: [{
message: '"keys[0].keys[0].keys[0].name" must be a string',
path: ['keys', 0, 'keys', 0, 'keys', 0, 'name'],
type: 'string.base',
context: { value: 42, label: 'keys[0].keys[0].keys[0].name', key: 'name' }
}]
}]
]);
});

it('errors on invalid reference', () => {

expect(() => Joi.link('.')).to.throw('Link cannot reference itself');
Expand Down

0 comments on commit e666649

Please sign in to comment.