[MediaWiki-commits] [Gerrit] mediawiki...mobileapps[master]: Add response schema validation

2016-11-04 Thread jenkins-bot (Code Review)
jenkins-bot has submitted this change and it was merged.

Change subject: Add response schema validation
..


Add response schema validation

Checks responses systematically against the updated schema definitions.

Provides for schema validation checks beyond checking checking the public
x-amples.

Made a couple updates to featured-image since a failure scenario we want
to test is testable now.

Bug: T145075
Change-Id: I0d3f20cd40f18661a135b6999dff47b0888e0cea
---
M package.json
M test/features/app/spec.js
M test/utils/assert.js
3 files changed, 113 insertions(+), 3 deletions(-)

Approvals:
  BearND: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/package.json b/package.json
index 2cfbb34..6acc25d 100644
--- a/package.json
+++ b/package.json
@@ -56,6 +56,7 @@
 "underscore": "^1.8.3"
   },
   "devDependencies": {
+"ajv": "^4.7.7",
 "csv-parse": "^1.1.7",
 "extend": "^3.0.0",
 "grunt": "^1.0.1",
diff --git a/test/features/app/spec.js b/test/features/app/spec.js
index 570fb40..a530fb7 100644
--- a/test/features/app/spec.js
+++ b/test/features/app/spec.js
@@ -2,11 +2,18 @@
 
 
 var preq   = require('preq');
-var assert = require('../../utils/assert.js');
-var server = require('../../utils/server.js');
+var assert = require('../../utils/assert');
+var server = require('../../utils/server');
+var dateUtil = require('../../../lib/dateUtil');
 var URI= require('swagger-router').URI;
 var yaml   = require('js-yaml');
 var fs = require('fs');
+var Ajv= require('ajv');
+
+var date = new Date();
+var yesterday = new Date(Date.now() - dateUtil.ONE_DAY);
+var dateString = date.getUTCFullYear() + '/' + dateUtil.pad(date.getUTCMonth() 
+ 1) + '/' + dateUtil.pad(date.getUTCDate());
+var yesterdayString = yesterday.getUTCFullYear() + '/' + 
dateUtil.pad(yesterday.getUTCMonth() + 1) + '/' + 
dateUtil.pad(yesterday.getUTCDate());
 
 
 function staticSpecLoad() {
@@ -266,7 +273,108 @@
 });
 });
 
-describe('routes', function() {
+describe('validate responses against schema', function() {
+var ajv = new Ajv({});
+
+var assertValidSchema = function(uri, schemaPath) {
+return preq.get({ uri: uri })
+.then(function(res) {
+if (!ajv.validate(schemaPath, res.body)) {
+throw new assert.AssertionError({ message: 
ajv.errorsText() });
+}
+});
+};
+
+var assertValidSchemaAggregated = function(uri) {
+return preq.get({ uri: uri, query: { aggregated: true } })
+.then(function(res) {
+if (!!res.body) {
+throw new assert.AssertionError({ message: 'Response 
should be empty!' });
+}
+});
+};
+
+var assertBadRequest = function(uri) {
+return preq.get({ uri: uri })
+.then(function(res) {
+assert.fail("This request should fail!");
+})
+.catch(function(err) {
+if (!ajv.validate('#/definitions/problem', err.body)) {
+throw new assert.AssertionError({ message: 
ajv.errorsText() });
+}
+});
+};
+
+Object.keys(spec.definitions).forEach(function(defName) {
+ajv.addSchema(spec.definitions[defName], '#/definitions/' + 
defName);
+});
+
+//Valid non-aggregated requests
+
+it('featured article response should conform to schema', function() {
+var uri = server.config.uri + 'en.wikipedia.org/v1/page/featured/' 
+ dateString;
+return assertValidSchema(uri, '#/definitions/article_title');
+});
+
+it('featured image response should conform to schema', function() {
+var uri = server.config.uri + 
'en.wikipedia.org/v1/media/image/featured/' + dateString;
+return assertValidSchema(uri, '#/definitions/image');
+});
+
+it('most-read response should conform to schema', function() {
+var uri = server.config.uri + 
'en.wikipedia.org/v1/page/most-read/' + yesterdayString;
+return assertValidSchema(uri, '#/definitions/mostread');
+});
+
+it('news response should conform to schema', function() {
+var uri = server.config.uri + 'en.wikipedia.org/v1/page/news';
+return assertValidSchema(uri, '#/definitions/news');
+});
+
+it('random response should conform to schema', function() {
+var uri = server.config.uri + 
'en.wikipedia.org/v1/page/random/title';
+return assertValidSchema(uri, '#/definitions/random');
+});
+
+//Bad requests return empty response for aggregated=true
+
+it('featured article response should conform to schema (invalid 
language, aggregated=true)', function() {
+return assertValidSchemaAggregated(server.con

[MediaWiki-commits] [Gerrit] mediawiki...mobileapps[master]: Add response schema validation

2016-10-14 Thread Mholloway (Code Review)
Mholloway has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/315996

Change subject: Add response schema validation
..

Add response schema validation

Checks responses systematically against the updated schema definitions.

Provides for schema validation checks beyond checking checking the public
x-amples.

Made a couple updates to featured-image since a failure scenario we want
to test is testable now.

Bug: T145075
Change-Id: I0d3f20cd40f18661a135b6999dff47b0888e0cea
---
M lib/feed/featured-image.js
M package.json
M spec.yaml
M test/features/app/spec.js
M test/features/featured-image/pagecontent.js
M test/utils/assert.js
6 files changed, 234 insertions(+), 10 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/mobileapps 
refs/changes/96/315996/1

diff --git a/lib/feed/featured-image.js b/lib/feed/featured-image.js
index f6bc226..0c04409 100644
--- a/lib/feed/featured-image.js
+++ b/lib/feed/featured-image.js
@@ -107,7 +107,7 @@
 
 if (!dateUtil.validate(dateUtil.hyphenDelimitedDateString(req))) {
 if (aggregated) {
-return BBPromise.resolve({});
+return BBPromise.resolve({ empty: true });
 }
 dateUtil.throwDateError();
 }
diff --git a/package.json b/package.json
index 00ea2eb..8dc74dc 100644
--- a/package.json
+++ b/package.json
@@ -56,7 +56,8 @@
 "underscore": "^1.8.3"
   },
   "devDependencies": {
-"csv-parse": "1.1.7",
+"ajv": "^4.7.7",
+"csv-parse": "^1.1.7",
 "extend": "^3.0.0",
 "grunt": "^1.0.1",
 "grunt-jscs": "^3.0.1",
diff --git a/spec.yaml b/spec.yaml
index aa9ef92..da9148b 100644
--- a/spec.yaml
+++ b/spec.yaml
@@ -98,6 +98,12 @@
 $ref: '#/definitions/article_title'
 '204':
   description: Empty response (for feed content aggregation requests 
from RESTBase)
+  schema:
+$ref: '#/definitions/empty'
+'501':
+  description: Unsupported language
+  schema:
+$ref: '#/definitions/problem'
 default:
   description: Error
   schema:
@@ -513,13 +519,17 @@
 required:
   - type
 properties:
+  status:
+type: integer
   type:
 type: string
   title:
 type: string
   detail:
 type: string
-  instance:
+  method:
+type: string
+  uri:
 type: string
 
   article_title:
@@ -632,9 +642,20 @@
 description: Full-size image
 $ref: '#/definitions/thumbnail'
   description:
-descrtiption: Description of an image
+description: Description of an image
 $ref: '#/definitions/image_description'
 required:
   - title
   - thumbnail
   - image
+
+  empty:
+type: object
+properties:
+  type:
+type: string
+description: description of original content type (buffer)
+  data:
+type: array
+description: Buffer contents
+additionalProperties: false
diff --git a/test/features/app/spec.js b/test/features/app/spec.js
index 570fb40..635f588 100644
--- a/test/features/app/spec.js
+++ b/test/features/app/spec.js
@@ -2,11 +2,17 @@
 
 
 var preq   = require('preq');
-var assert = require('../../utils/assert.js');
-var server = require('../../utils/server.js');
+var assert = require('../../utils/assert');
+var server = require('../../utils/server');
+var dateUtil = require('../../../lib/dateUtil');
 var URI= require('swagger-router').URI;
 var yaml   = require('js-yaml');
 var fs = require('fs');
+var Ajv = require('ajv');
+var date = new Date();
+var yesterday = new Date(Date.now() - dateUtil.ONE_DAY);
+var dateString = date.getUTCFullYear() + '/' + dateUtil.pad(date.getUTCMonth() 
+ 1) + '/' + dateUtil.pad(date.getUTCDate());
+var yesterdayString = yesterday.getUTCFullYear() + '/' + 
dateUtil.pad(yesterday.getUTCMonth() + 1) + '/' + 
dateUtil.pad(yesterday.getUTCDate());
 
 
 function staticSpecLoad() {
@@ -266,7 +272,202 @@
 });
 });
 
-describe('routes', function() {
+describe('validate responses against schema', function() {
+var ajv = new Ajv({});
+
+Object.keys(spec.definitions).forEach(function(defName) {
+ajv.addSchema(spec.definitions[defName], '#/definitions/' + 
defName);
+});
+
+it('featured article response should conform to schema', function() {
+return preq.get({ uri: server.config.uri + 
'en.wikipedia.org/v1/page/featured/' + dateString })
+.then(function(res) {
+if (!ajv.validate('#/definitions/article_title', res.body)) {
+throw new assert.AssertionError({
+message: ajv.errorsText()
+});
+}
+});
+});
+
+it('featured article request should fail for invalid language when not 
in aggregated request', func