box-view-api
Version:
Box View API, node.js client library
343 lines (320 loc) • 11 kB
JavaScript
// Sets up a *global* framework for testing.
//
// This is included in the mocha.opts file as a --require,
// so that individual test specs don't have to explicitly require the framework.
var _ = require('underscore');
var chai = require('chai');
expect = chai.expect;
var boxViewResponses = require('./boxViewResponses');
var boxViewDetails = (function(){
// if the boxViewDetails.js exists, use the values in that
// otherwise use default (dummy) ones.
try { return require('./boxViewDetails'); }
catch (e) { return null; }
})() || {
validApiKey: 'replace-with-a-valid-api-key',
dummyApiKey: 'leave-this-dummy-api-key-alone'
};
var DocumentAPI = require('index').DocumentAPI;
var document = new DocumentAPI(boxViewDetails.validApiKey);
function checkProps(objFn, props, strict) {
it('should be an object', (function (_ofn) {
return function () {
expect(_ofn()).to.be.an('object');
};
})(objFn));
function checkPropType(getter, name, type, value) {
it('should have a property called "' + name + '"', (function (_ofn, _pn, _t) {
return function () {
expect(_ofn()).to.have.a.property(_pn);
};
})(getter, name, type));
describe('.'+name, function() {
it('should be of type "' + type + '"', (function (_ofn, _pn, _t) {
return function () {
if (_t.indexOf('?') === 0) {
_t = _t.substring(1);
if (_ofn()[_pn] === null) {
// it's ok for something to be null if it's type string starts with a '?'
return;
}
}
expect(_ofn()[_pn]).to.be.a(_t);
};
})(getter, name, type));
if (value) {
it('should be equal to "' + value + '"', (function (_ofn, _pn, _v) {
return function () {
expect(_ofn()[_pn]).to.equal(_v);
};
})(getter, name, value));
}
});
// it('.' + name + ' should be of type "' + type + '"', (function (_ofn, _pn, _t) {
// return function () {
// if (_t.indexOf('?') === 0) {
// _t = _t.substring(1);
// if (_ofn()[_pn] === null) {
// // it's ok for something to be null if it's type string starts with a '?'
// return;
// }
// }
// expect(_ofn()[_pn]).to.be.a(_t);
// };
// })(getter, name, type));
}
for (var p in props) {
if (typeof props[p] === 'object') {
it('should have a property called "' + p + '", which is an object with more properties', (function (_ofn, _pn, _po) {
return function () {
expect(_ofn()).to.have.a.property(_pn);
expect(_ofn()[_pn]).to.be.an('object');
};
})(objFn, p, props[p]));
describe('.' + p, (function (_ofn, _pn, _po) {
return function () {
checkProps(function () {
return _ofn()[_pn];
}, _po, strict);
};
})(objFn, p, props[p]));
}
else {
switch (props[p]) {
case 'object':
case 'string':
case 'boolean':
case 'number':
case 'array':
case 'function':
case '?object':
case '?string':
checkPropType(objFn, p, props[p]);
break;
case 'undefined':
it('should not have a property called "' + p + '"', (function (_ofn, _pn, _t) {
return function () {
expect(_ofn()).to.not.have.a.property(_pn);
};
})(objFn, p, props[p]));
break;
default:
if (props[p].indexOf('$') === 0) {
checkPropType(objFn, p, 'string', props[p].substr(1));
}
else {
it('should have a property called "' + p + '"', (function (_ofn, _pn, _t) {
return function () {
expect(_ofn()).to.have.a.property(_pn);
};
})(objFn, p, props[p]));
it('.' + p + ' should be of type "' + props[p] + '"', (function (_ofn, _pn, _t) {
return function () {
expect(_ofn()[_pn]).to.be.an.instanceOf(_t);
};
})(objFn, p, props[p]));
}
break;
}
}
}
var keys;
if (strict) {
keys = Object.keys(props);
if (keys && keys.length > 0) {
it('should have no other properties', function () {
expect(objFn()).to.have.keys(keys);
});
}
else {
it('should have no properties', function() {
expect(Object.keys(objFn()).length).to.equal(0);
});
}
}
}
var tempUuid = {
uuids: [],
add: function(uuid) {
tempUuid.uuids.push(uuid);
},
remove: function(uuid) {
var i;
while((i = tempUuid.uuids.indexOf(uuid)) >= 0 ) {
tempUuid.uuids.splice(i, 1);
}
},
purge: function (cb, failed) {
failed = failed || [];
cb = cb || function(){};
if (tempUuid.uuids && tempUuid.uuids.length > 0) {
document.remove(tempUuid.uuids[0], function(e, r, b) {
if (b === false || b.error) {
failed.push(tempUuid.uuids[0]);
}
tempUuid.remove(tempUuid.uuids[0]);
tempUuid.purge(cb, failed);
});
}
else {
cb(null, failed);
}
},
fromUrl: function(url, name, cb) {
cb = cb || function(){};
document.uploadUrl(url, name, function(e, r, b) {
if (!e && b && b.uuid) {
tempUuid.add(b.uuid);
}
cb(e, r, b);
});
},
fromFile: function(filepath, cb) {
cb = cb || function(){};
document.uploadFile(filepath, function(e, r, b) {
if (!e && b && b.uuid) {
tempUuid.add(b.uuid);
}
cb(e, r, b);
});
},
waitFor: function(id, cb) {
cb = cb || function(){};
document.poll(id, cb);
}
};
function commonChecks(it, e, r, b) {
it('should get a truthy response', function() {
framework.assert(r(), 'Expected response to be truthy, not: '+r());
});
it('should have truthy response headers', function() {
framework.assert(r().headers, 'Expected response headers to be truthy, not: '+r().headers);
});
it('should have a truthy response body', function() {
framework.assert(b(), 'Expected body to be truthy, not: '+b());
});
it('should get a falsey error', function () {
framework.assert(!e(), 'Expected error to be falsey, not: ' + e());
});
}
function statusCodeChecks(it, statusCode) {
return function (e, r, b) {
it('should get a ' + statusCode + ' response code', function () {
framework.assert(r().statusCode === statusCode, 'Expected status code to be ' + statusCode + ', not ' + r().statusCode);
});
commonChecks(it, e, r, b);
};
}
function contentTypeChecks(e, r, b, mimeType, invert) {
mimeType = mimeType || 'application/json';
if (invert) {
it('should have a content-type response header which is not '+mimeType, function () {
var contentType = r().headers['content-type'];
framework.assert((typeof contentType === 'string') && contentType.toLowerCase().indexOf(mimeType) < 0, 'Expected content type not to be '+mimeType);
});
}
else {
it('should have a content-type response header of '+ mimeType, function () {
var contentType = r().headers['content-type'];
framework.assert((typeof contentType === 'string') && contentType.toLowerCase().indexOf(mimeType) >= 0, 'Expected content type to be ' + mimeType + ', not: ' + contentType);
});
}
}
function jsonContentTypeChecks(e, r, b, notJson) {
return contentTypeChecks(e, r, b, 'application/json', notJson);
}
function instanceMethodTests(getInstance, method, goodParams, badParams) {
var index;
for (index = 0; index < goodParams.length; index++) {
it('should not throw an error when called with ' + goodParams[index].name, (function (i) {
return function () {
getInstance()[method].apply(getInstance(), goodParams[i].args);
};
})(index));
}
for (index = 0; index < badParams.length; index++) {
it('should throw an error when called with ' + badParams[index].name, (function (i) {
return function () {
framework.throwsError(function () {
getInstance()[method].apply(getInstance(), badParams[i].args);
});
};
})(index));
}
}
framework = module.exports = {
assert: require('assert'),
url: require('url'),
path: require('path'),
qs: require('querystring'),
inspect: require('util').inspect,
exec: require('child_process').exec,
fsUtils: require('index').fsUtils,
throwsError: function(fn, message) {
if (typeof fn !== 'function') {
throw new Error('Invalid use of framework: Expected a function to be supplied');
}
message = message || 'Expected an error to be thrown';
var err;
try {
fn();
}
catch (e) {
err = e;
}
framework.assert(err, message);
},
isArray: _.isArray,
tempUuid: tempUuid,
tempFile: function(fname) {
return framework.path.resolve('test/results', fname);
},
timeouts: {
poll: 40000,
response: 5000
},
statusCodeChecks: statusCodeChecks,
contentTypeChecks: contentTypeChecks,
jsonContentTypeChecks: jsonContentTypeChecks,
restTests: function() {
return {
_200Checks: statusCodeChecks(it, 200),
_201Checks: statusCodeChecks(it, 201),
_202Checks: statusCodeChecks(it, 202),
_204Checks: statusCodeChecks(it, 204),
_400Checks: statusCodeChecks(it, 400),
_404Checks: statusCodeChecks(it, 404),
_JsonContentChecks: function(e, r, b, notJson) {
if (notJson) {
it('should have a content-type response header which is not application/json', function() {
var contentType = r().headers['content-type'];
framework.assert((typeof contentType === 'string') && contentType.toLowerCase().indexOf('application/json') < 0, 'Expected content type not to be application/json');
});
}
else {
it('should have a content-type response header of application/json', function() {
var contentType = r().headers['content-type'];
framework.assert((typeof contentType === 'string') && contentType.toLowerCase().indexOf('application/json') >= 0, 'Expected content type to be application/json, not: '+contentType);
});
}
}
};
},
values: {
invalidParamList: [
{ name: 'undefined', value: undefined },
{ name: 'null', value: null },
{ name: 'number', value: 1 },
{ name: 'boolean, true', value: true },
{ name: 'boolean, false', value: false },
{ name: 'object', value: {} },
{ name: 'function', value: function (){} },
{ name: 'empty array', value: [] },
{ name: 'empty string', value: '' }
]
},
instanceMethodTests: instanceMethodTests,
checkProps: checkProps,
boxView: boxViewDetails,
boxViewResponses: boxViewResponses
};