Skip to content

Commit

Permalink
test: compileAsync tests using promises, #249
Browse files Browse the repository at this point in the history
  • Loading branch information
epoberezkin committed Oct 17, 2016
1 parent f4a5f10 commit 2b2e644
Showing 1 changed file with 125 additions and 66 deletions.
191 changes: 125 additions & 66 deletions spec/async.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,23 @@ describe('compileAsync method', function() {
});


it('should compile schemas loading missing schemas with options.loadSchema function', function (done) {
it('should compile schemas loading missing schemas with options.loadSchema function', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "object.json" }
}
};
return ajv.compileAsync(schema).then(function (validate) {
should.equal(loadCallCount, 2);
validate .should.be.a('function');
validate({ a: { b: 2 } }) .should.equal(true);
validate({ a: { b: 1 } }) .should.equal(false);
});
});


it('should compile schemas loading missing schemas and return function via callback', function (done) {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
Expand All @@ -73,33 +89,30 @@ describe('compileAsync method', function() {
});


it('should correctly load schemas when missing reference has JSON path', function (done) {
it('should correctly load schemas when missing reference has JSON path', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "object.json#/properties/b" }
}
};
ajv.compileAsync(schema, function (err, validate) {
return ajv.compileAsync(schema).then(function (validate) {
should.equal(loadCallCount, 2);
should.not.exist(err);
validate .should.be.a('function');
validate({ a: 2 }) .should.equal(true);
validate({ a: 1 }) .should.equal(false);
done();
});
});


it('should correctly compile with remote schemas that have mutual references', function (done) {
it('should correctly compile with remote schemas that have mutual references', function() {
var schema = {
"id": "http://example.com/root.json",
"properties": {
"tree": { "$ref": "tree.json" }
}
};
ajv.compileAsync(schema, function (err, validate) {
should.not.exist(err);
return ajv.compileAsync(schema).then(function (validate) {
validate .should.be.a('function');
var validData = { tree: [
{ name: 'a', subtree: [ { name: 'a.a' } ] },
Expand All @@ -110,32 +123,29 @@ describe('compileAsync method', function() {
] };
validate(validData) .should.equal(true);
validate(invalidData) .should.equal(false);
done();
});
});


it('should correctly compile with remote schemas that reference the compiled schema', function (done) {
it('should correctly compile with remote schemas that reference the compiled schema', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "recursive.json" }
}
};
ajv.compileAsync(schema, function (err, validate) {
return ajv.compileAsync(schema).then(function (validate) {
should.equal(loadCallCount, 1);
should.not.exist(err);
validate .should.be.a('function');
var validData = { a: { b: { a: { b: {} } } } };
var invalidData = { a: { b: { a: {} } } };
validate(validData) .should.equal(true);
validate(invalidData) .should.equal(false);
done();
});
});


it('should resolve reference containing "properties" segment with the same property (issue #220)', function (done) {
it('should resolve reference containing "properties" segment with the same property (issue #220)', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
Expand All @@ -144,39 +154,37 @@ describe('compileAsync method', function() {
}
}
};
ajv.compileAsync(schema, function (err, validate) {
should.not.exist(err);
return ajv.compileAsync(schema).then(function (validate) {
should.equal(loadCallCount, 2);
validate .should.be.a('function');
validate({ a: 'foo' }) .should.equal(true);
validate({ a: 42 }) .should.equal(false);
done();
});
});


it('should return compiled schema on the next tick if there are no references (#51)', function (done) {
it('should return compiled schema on the next tick if there are no references (#51)', function() {
var schema = {
"id": "http://example.com/int2plus.json",
"type": "integer",
"minimum": 2
};
var beforeCallback1;
ajv.compileAsync(schema, function (err, validate) {
var p1 = ajv.compileAsync(schema).then(function (validate) {
beforeCallback1 .should.equal(true);
spec(err, validate);
spec(validate);
var beforeCallback2;
ajv.compileAsync(schema, function (_err, _validate) {
var p2 = ajv.compileAsync(schema).then(function (_validate) {
beforeCallback2 .should.equal(true);
spec(_err, _validate);
done();
spec(_validate);
});
beforeCallback2 = true;
return p2;
});
beforeCallback1 = true;
return p1;

function spec(err, validate) {
should.not.exist(err);
function spec(validate) {
should.equal(loadCallCount, 0);
validate .should.be.a('function');
var validData = 2;
Expand All @@ -187,33 +195,24 @@ describe('compileAsync method', function() {
});


it('should queue calls so only one compileAsync executes at a time (#52)', function (done) {
it('should queue calls so only one compileAsync executes at a time (#52)', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "object.json" }
}
};

var completedCount = 0;
ajv.compileAsync(schema, spec);
ajv.compileAsync(schema, spec);
ajv.compileAsync(schema, spec);
return Promise.all[
ajv.compileAsync(schema).then(spec),
ajv.compileAsync(schema).then(spec),
ajv.compileAsync(schema).then(spec)
];

function spec(err, validate) {
should.not.exist(err);
function spec(validate) {
validate .should.be.a('function');
validate({ a: { b: 2 } }) .should.equal(true);
validate({ a: { b: 1 } }) .should.equal(false);
completed();
}

function completed() {
completedCount++;
if (completedCount == 3) {
should.equal(loadCallCount, 2);
done();
}
}
});

Expand Down Expand Up @@ -244,11 +243,7 @@ describe('compileAsync method', function() {
"type": "integer",
"minimum": "invalid"
};
ajv.compileAsync(invalidSchema, function (err, validate) {
should.exist(err);
should.not.exist(validate);
done();
});
ajv.compileAsync(invalidSchema, shouldFail(done));
});

it('if loaded schema is invalid', function (done) {
Expand All @@ -258,11 +253,7 @@ describe('compileAsync method', function() {
"a": { "$ref": "invalid.json" }
}
};
ajv.compileAsync(schema, function (err, validate) {
should.exist(err);
should.not.exist(validate);
done();
});
ajv.compileAsync(schema, shouldFail(done));
});

it('if required schema is loaded but the reference cannot be resolved', function (done) {
Expand All @@ -272,11 +263,7 @@ describe('compileAsync method', function() {
"a": { "$ref": "object.json#/definitions/not_found" }
}
};
ajv.compileAsync(schema, function (err, validate) {
should.exist(err);
should.not.exist(validate);
done();
});
ajv.compileAsync(schema, shouldFail(done));
});

it('if loadSchema returned error', function (done) {
Expand All @@ -287,11 +274,7 @@ describe('compileAsync method', function() {
}
};
ajv = new Ajv({ loadSchema: badLoadSchema });
ajv.compileAsync(schema, function (err, validate) {
should.exist(err);
should.not.exist(validate);
done();
});
ajv.compileAsync(schema, shouldFail(done));

function badLoadSchema() {
return Promise.reject(new Error('cant load'));
Expand All @@ -301,23 +284,99 @@ describe('compileAsync method', function() {
it('if schema compilation throws some other exception', function (done) {
ajv.addKeyword('badkeyword', { compile: badCompile });
var schema = { badkeyword: true };
ajv.compileAsync(schema, function (err, validate) {
ajv.compileAsync(schema, shouldFail(done));

function badCompile(/* schema */) {
throw new Error('cant compile keyword schema');
}
});

function shouldFail(done) {
return function (err, validate) {
should.exist(err);
should.not.exist(validate);
done();
});
};
}
});


describe('should return error via promise', function() {
it('if passed schema is invalid', function() {
var invalidSchema = {
"id": "http://example.com/int2plus.json",
"type": "integer",
"minimum": "invalid"
};
return shouldReject(ajv.compileAsync(invalidSchema));
});

it('if loaded schema is invalid', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "invalid.json" }
}
};
return shouldReject(ajv.compileAsync(schema));
});

it('if required schema is loaded but the reference cannot be resolved', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "object.json#/definitions/not_found" }
}
};
return shouldReject(ajv.compileAsync(schema));
});

it('if loadSchema returned error', function() {
var schema = {
"id": "http://example.com/parent.json",
"properties": {
"a": { "$ref": "object.json" }
}
};
ajv = new Ajv({ loadSchema: badLoadSchema });
return shouldReject(ajv.compileAsync(schema));

function badLoadSchema() {
return Promise.reject(new Error('cant load'));
}
});

it('if schema compilation throws some other exception', function() {
ajv.addKeyword('badkeyword', { compile: badCompile });
var schema = { badkeyword: true };
return shouldReject(ajv.compileAsync(schema));

function badCompile(/* schema */) {
throw new Error('cant compile keyword schema');
}
});

function shouldReject(p) {
return p.then(
function(validate) {
should.not.exist(validate);
throw new Error('Promise has resolved; it should have rejected');
},
function(err) {
should.exist(err);
}
);
}
});


function loadSchema(uri) {
loadCallCount++;
return SCHEMAS[uri]
? Promise.resolve(SCHEMAS[uri])
: Promise.reject(new Error('404'));
return new Promise(function (resolve, reject) {
setTimeout(function() {
if (SCHEMAS[uri]) resolve(SCHEMAS[uri]);
else reject(new Error('404'));
}, 10);
});
}
});

0 comments on commit 2b2e644

Please sign in to comment.