Skip to content

Commit

Permalink
Pass joi instance when it's not attached to any
Browse files Browse the repository at this point in the history
Fixes #1311
  • Loading branch information
Marsup committed Oct 8, 2017
1 parent 8e13b5f commit 491ab9d
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 17 deletions.
35 changes: 18 additions & 17 deletions lib/index.js
Expand Up @@ -47,68 +47,68 @@ internals.root = function () {

Hoek.assert(arguments.length === 0, 'Joi.any() does not allow arguments.');

return internals.applyDefaults.call(this, any);
return internals.applyDefaults.call(this || root, any);
};

root.alternatives = root.alt = function () {

const alternatives = internals.applyDefaults.call(this, internals.alternatives);
const alternatives = internals.applyDefaults.call(this || root, internals.alternatives);
return arguments.length ? alternatives.try.apply(alternatives, arguments) : alternatives;
};

root.array = function () {

Hoek.assert(arguments.length === 0, 'Joi.array() does not allow arguments.');

return internals.applyDefaults.call(this, internals.array);
return internals.applyDefaults.call(this || root, internals.array);
};

root.boolean = root.bool = function () {

Hoek.assert(arguments.length === 0, 'Joi.boolean() does not allow arguments.');

return internals.applyDefaults.call(this, internals.boolean);
return internals.applyDefaults.call(this || root, internals.boolean);
};

root.binary = function () {

Hoek.assert(arguments.length === 0, 'Joi.binary() does not allow arguments.');

return internals.applyDefaults.call(this, internals.binary);
return internals.applyDefaults.call(this || root, internals.binary);
};

root.date = function () {

Hoek.assert(arguments.length === 0, 'Joi.date() does not allow arguments.');

return internals.applyDefaults.call(this, internals.date);
return internals.applyDefaults.call(this || root, internals.date);
};

root.func = function () {

Hoek.assert(arguments.length === 0, 'Joi.func() does not allow arguments.');

return internals.applyDefaults.call(this, internals.func);
return internals.applyDefaults.call(this || root, internals.func);
};

root.number = function () {

Hoek.assert(arguments.length === 0, 'Joi.number() does not allow arguments.');

return internals.applyDefaults.call(this, internals.number);
return internals.applyDefaults.call(this || root, internals.number);
};

root.object = function () {

const object = internals.applyDefaults.call(this, internals.object);
const object = internals.applyDefaults.call(this || root, internals.object);
return arguments.length ? object.keys.apply(object, arguments) : object;
};

root.string = function () {

Hoek.assert(arguments.length === 0, 'Joi.string() does not allow arguments.');

return internals.applyDefaults.call(this, internals.string);
return internals.applyDefaults.call(this || root, internals.string);
};

root.ref = function () {
Expand Down Expand Up @@ -246,10 +246,11 @@ internals.root = function () {
const extensions = Hoek.flatten(Array.prototype.slice.call(arguments));
Hoek.assert(extensions.length > 0, 'You need to provide at least one extension');

this.assert(extensions, root.extensionsSchema);
const currentJoi = this || root;
currentJoi.assert(extensions, root.extensionsSchema);

const joi = Object.create(this.any());
Object.assign(joi, this);
const joi = Object.create(currentJoi.any());
Object.assign(joi, currentJoi);

for (let i = 0; i < extensions.length; ++i) {
let extension = extensions[i];
Expand All @@ -258,9 +259,9 @@ internals.root = function () {
extension = extension(joi);
}

this.assert(extension, root.extensionSchema);
currentJoi.assert(extension, root.extensionSchema);

const base = (extension.base || this.any()).clone(); // Cloning because we're going to override language afterwards
const base = (extension.base || currentJoi.any()).clone(); // Cloning because we're going to override language afterwards
const ctor = base.constructor;
const type = class extends ctor { // eslint-disable-line no-loop-func

Expand Down Expand Up @@ -332,7 +333,7 @@ internals.root = function () {
const ruleArgs = rule.params ?
(rule.params instanceof Any ? rule.params._inner.children.map((k) => k.key) : Object.keys(rule.params)) :
[];
const validateArgs = rule.params ? Cast.schema(this, rule.params) : null;
const validateArgs = rule.params ? Cast.schema(currentJoi, rule.params) : null;

type.prototype[rule.name] = function () { // eslint-disable-line no-loop-func

Expand Down Expand Up @@ -395,7 +396,7 @@ internals.root = function () {
const instance = new type();
joi[extension.name] = function () {

return internals.applyDefaults.call(this, instance);
return internals.applyDefaults.call(this || joi, instance);
};
}

Expand Down
18 changes: 18 additions & 0 deletions test/index.js
Expand Up @@ -3237,6 +3237,24 @@ describe('Joi', () => {
});
});

it('can be called on its own', (done) => {

const extend = Joi.extend;
const customJoi = extend({
name: 'myType'
});

expect(Joi.myType).to.not.exist();
expect(customJoi.myType).to.be.a.function();

const myType = customJoi.myType;
const schema = myType();
expect(schema._type).to.equal('myType');
expect(schema.isJoi).to.be.true();

done();
});

it('defines a custom type with a default base', (done) => {

const customJoi = Joi.extend({
Expand Down
7 changes: 7 additions & 0 deletions test/types/alternatives.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('alternatives', () => {

it('can be called on its own', (done) => {

const alternatives = Joi.alternatives;
expect(() => alternatives()).not.to.throw();
done();
});

it('fails when no alternatives are provided', (done) => {

Joi.alternatives().validate('a', (err, value) => {
Expand Down
7 changes: 7 additions & 0 deletions test/types/any.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('any', () => {

it('can be called on its own', (done) => {

const any = Joi.any;
expect(() => any()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/array.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('array', () => {

it('can be called on its own', (done) => {

const array = Joi.array;
expect(() => array()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/binary.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('binary', () => {

it('can be called on its own', (done) => {

const binary = Joi.binary;
expect(() => binary()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/boolean.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('boolean', () => {

it('can be called on its own', (done) => {

const boolean = Joi.boolean;
expect(() => boolean()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/date.js
Expand Up @@ -46,6 +46,13 @@ describe('date', () => {
done();
});

it('can be called on its own', (done) => {

const date = Joi.date;
expect(() => date()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/function.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('func', () => {

it('can be called on its own', (done) => {

const func = Joi.func;
expect(() => func()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/lazy.js
Expand Up @@ -23,6 +23,13 @@ const expect = Lab.expect;

describe('lazy', () => {

it('can be called on its own', (done) => {

const lazy = Joi.lazy;
expect(() => lazy(() => {})).not.to.throw();
done();
});

describe('set()', () => {

it('should require a function', (done) => {
Expand Down
7 changes: 7 additions & 0 deletions test/types/number.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('number', () => {

it('can be called on its own', (done) => {

const number = Joi.number;
expect(() => number()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down
7 changes: 7 additions & 0 deletions test/types/object.js
Expand Up @@ -22,6 +22,13 @@ const expect = Lab.expect;

describe('object', () => {

it('can be called on its own', (done) => {

const object = Joi.object;
expect(() => object()).not.to.throw();
done();
});

it('converts a json string to an object', (done) => {

Joi.object().validate('{"hi":true}', (err, value) => {
Expand Down
7 changes: 7 additions & 0 deletions test/types/string.js
Expand Up @@ -25,6 +25,13 @@ process.env.TZ = 'utc'; // Needed for timezone sensitive tests

describe('string', () => {

it('can be called on its own', (done) => {

const string = Joi.string;
expect(() => string()).not.to.throw();
done();
});

it('should throw an exception if arguments were passed.', (done) => {

expect(
Expand Down

0 comments on commit 491ab9d

Please sign in to comment.