123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- var should = require('chai').should();
- var request = require('request');
- var Q = require('q');
- var config = {
- "authorizedKeys": {
- "1234567890": "contact@gaelmetais.com"
- }
- };
- var serverUrl = 'http://localhost:8387';
- var wwwUrl = 'http://localhost:8388';
- describe('api', function() {
- var syncRunResultUrl;
- var asyncRunId;
- var screenshotUrl;
- it('should refuse a query with an invalid key', function(done) {
- this.timeout(5000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: wwwUrl + '/simple-page.html',
- waitForResponse: false
- },
- json: true,
- headers: {
- 'X-Api-Key': 'invalid'
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 401) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should fail without an URL when asynchronous', function(done) {
- this.timeout(15000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: ''
- },
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 400) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should fail without an URL when synchronous', function(done) {
- this.timeout(15000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: '',
- waitForResponse: true
- },
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 400) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should launch a synchronous run', function(done) {
- this.timeout(15000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: wwwUrl + '/simple-page.html',
- waitForResponse: true,
- screenshot: true,
- device: 'tablet',
- waitForSelector: '*',
- cookie: 'foo=bar',
- authUser: 'joe',
- authPass: 'secret'
- },
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 302) {
- response.headers.should.have.a.property('location').that.is.a('string');
- syncRunResultUrl = response.headers.location;
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the rules only', function(done) {
- this.timeout(15000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: wwwUrl + '/simple-page.html',
- waitForResponse: true,
- partialResult: 'rules'
- },
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 302) {
- response.headers.should.have.a.property('location').that.is.a('string');
- response.headers.location.should.contain('/rules');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should retrieve the results for the synchronous run', function(done) {
- this.timeout(15000);
- request({
- method: 'GET',
- url: serverUrl + syncRunResultUrl,
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.should.have.a.property('runId').that.is.a('string');
- body.should.have.a.property('params').that.is.an('object');
- body.should.have.a.property('scoreProfiles').that.is.an('object');
- body.should.have.a.property('rules').that.is.an('object');
- body.should.have.a.property('toolsResults').that.is.an('object');
- // javascriptExecutionTree should only be filled if option jsTimeline is true
- body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
- body.javascriptExecutionTree.should.deep.equal({});
- // Check if settings are correctly sent and retrieved
- body.params.options.should.have.a.property('device').that.equals('tablet');
- body.params.options.should.have.a.property('waitForSelector').that.equals('*');
- body.params.options.should.have.a.property('cookie').that.equals('foo=bar');
- body.params.options.should.have.a.property('authUser').that.equals('joe');
- body.params.options.should.have.a.property('authPass').that.equals('secret');
- // Check if the screenshot temporary file was correctly removed
- body.params.options.should.not.have.a.property('screenshot');
- // Check if the screenshot buffer was correctly removed
- body.should.not.have.a.property('screenshotBuffer');
- // Check if the screenshot url is here
- body.should.have.a.property('screenshotUrl');
- body.screenshotUrl.should.equal('/api/results/' + body.runId + '/screenshot.jpg');
- screenshotUrl = body.screenshotUrl;
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should launch a run without waiting for the response', function(done) {
- this.timeout(5000);
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: wwwUrl + '/simple-page.html',
- waitForResponse: false,
- jsTimeline: true
- },
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- asyncRunId = body.runId;
- asyncRunId.should.be.a('string');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should respond run status: running', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/runs/' + asyncRunId,
- json: true,
- headers: {
- 'X-Api-Key': Object.keys(config.authorizedKeys)[0]
- }
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.runId.should.equal(asyncRunId);
- body.status.should.deep.equal({
- statusCode: 'running'
- });
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should accept up to 10 anonymous runs to the API', function(done) {
- this.timeout(5000);
- function launchRun() {
- var deferred = Q.defer();
- request({
- method: 'POST',
- url: serverUrl + '/api/runs',
- body: {
- url: wwwUrl + '/simple-page.html',
- waitForResponse: false
- },
- json: true
- }, function(error, response, body) {
- lastRunId = body.runId;
- if (error) {
- deferred.reject(error);
- } else {
- deferred.resolve(response, body);
- }
- });
- return deferred.promise;
- }
- launchRun()
- .then(launchRun)
- .then(launchRun)
- .then(launchRun)
- .then(launchRun)
- .then(function(response, body) {
-
- // Here should still be ok
- response.statusCode.should.equal(200);
- launchRun()
- .then(launchRun)
- .then(launchRun)
- .then(launchRun)
- .then(launchRun)
- .then(launchRun)
- .then(function(response, body) {
- // It should fail now
- response.statusCode.should.equal(429);
- done();
- })
- .fail(function(error) {
- done(error);
- });
- }).fail(function(error) {
- done(error);
- });
-
- });
- it('should respond 404 to unknown runId', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/runs/unknown',
- json: true
- }, function(error, response, body) {
- if (!error && response.statusCode === 404) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should respond 404 to unknown result', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/unknown',
- json: true
- }, function(error, response, body) {
- if (!error && response.statusCode === 404) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
-
- it('should respond status complete to the first run', function(done) {
- this.timeout(12000);
- function checkStatus() {
- request({
- method: 'GET',
- url: serverUrl + '/api/runs/' + asyncRunId,
- json: true
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.runId.should.equal(asyncRunId);
-
- if (body.status.statusCode === 'running') {
- setTimeout(checkStatus, 250);
- } else if (body.status.statusCode === 'complete') {
- done();
- } else {
- done(body.status.statusCode);
- }
- } else {
- done(error || response.statusCode);
- }
- });
- }
- checkStatus();
- });
- it('should find the result of the async run', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId,
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.should.have.a.property('runId').that.equals(asyncRunId);
- body.should.have.a.property('params').that.is.an('object');
- body.params.url.should.equal(wwwUrl + '/simple-page.html');
- body.should.have.a.property('scoreProfiles').that.is.an('object');
- body.scoreProfiles.should.have.a.property('generic').that.is.an('object');
- body.scoreProfiles.generic.should.have.a.property('globalScore').that.is.a('number');
- body.scoreProfiles.generic.should.have.a.property('categories').that.is.an('object');
- body.should.have.a.property('rules').that.is.an('object');
- body.should.have.a.property('toolsResults').that.is.an('object');
- body.toolsResults.should.have.a.property('phantomas').that.is.an('object');
- body.should.have.a.property('javascriptExecutionTree').that.is.an('object');
- body.javascriptExecutionTree.should.have.a.property('data').that.is.an('object');
- body.javascriptExecutionTree.data.should.have.a.property('type').that.equals('main');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the generic score object', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/generalScores',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.should.have.a.property('globalScore').that.is.a('number');
- body.should.have.a.property('categories').that.is.an('object');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the generic score object also', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/generalScores/generic',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- body.should.have.a.property('globalScore').that.is.a('number');
- body.should.have.a.property('categories').that.is.an('object');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should not find an unknown score object', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/generalScores/unknown',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 404) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the rules', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/rules',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
-
- var firstRule = body[Object.keys(body)[0]];
- firstRule.should.have.a.property('policy').that.is.an('object');
- firstRule.should.have.a.property('value').that.is.a('number');
- firstRule.should.have.a.property('bad').that.is.a('boolean');
- firstRule.should.have.a.property('abnormal').that.is.a('boolean');
- firstRule.should.have.a.property('score').that.is.a('number');
- firstRule.should.have.a.property('abnormalityScore').that.is.a('number');
-
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the javascript execution tree', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/javascriptExecutionTree',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
-
- body.should.have.a.property('data').that.is.an('object');
- body.data.should.have.a.property('type').that.equals('main');
-
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should return the phantomas results', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/' + asyncRunId + '/toolsResults/phantomas',
- json: true,
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
-
- body.should.have.a.property('metrics').that.is.an('object');
- body.should.have.a.property('offenders').that.is.an('object');
-
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should retrieve the screenshot', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + screenshotUrl
- }, function(error, response, body) {
- if (!error && response.statusCode === 200) {
- response.headers['content-type'].should.equal('image/jpeg');
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- it('should fail on a unexistant screenshot', function(done) {
- this.timeout(5000);
- request({
- method: 'GET',
- url: serverUrl + '/api/results/000000/screenshot.jpg'
- }, function(error, response, body) {
- if (!error && response.statusCode === 404) {
- done();
- } else {
- done(error || response.statusCode);
- }
- });
- });
- });
|