Comparing version 1.0.5 to 1.0.6
{ | ||
"name": "challenge", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "A node.js mocha unit test generator with support for JSON case data.", | ||
@@ -5,0 +5,0 @@ "main": "source/Challenge.js", |
@@ -17,313 +17,319 @@ /** | ||
var libAsync = require('async'); | ||
var libSuperTest = null; | ||
var _BaseJsonPath = argv.jsonPath || path.dirname(module.parent.filename) + '/'; | ||
var Challenge = ( | ||
function ChallengeInitializer(pOptions) | ||
{ | ||
//(Optional) configure test runner, include a Rest client | ||
var libSuperTest = null; | ||
var _BaseJsonPath = argv.jsonPath || path.dirname(module.parent.filename) + '/'; | ||
//Configure test runner, include a Rest client | ||
// @ServerURL | ||
// @BaseJsonPath | ||
initialize: function(pOptions) | ||
for(var key in pOptions) | ||
{ | ||
for(var key in pOptions) | ||
switch(key) | ||
{ | ||
switch(key) | ||
{ | ||
case 'ServerURL': | ||
libSuperTest = require('supertest').agent(pOptions.ServerURL); | ||
break; | ||
case 'BaseJsonPath': | ||
_BaseJsonPath = pOptions.BaseJsonPath; | ||
break; | ||
default: | ||
throw Error('Invalid initialize option: ' + key); | ||
} | ||
case 'ServerURL': | ||
libSuperTest = require('supertest').agent(pOptions.ServerURL); | ||
break; | ||
case 'BaseJsonPath': | ||
_BaseJsonPath = pOptions.BaseJsonPath; | ||
break; | ||
default: | ||
throw Error('Invalid initialize option: ' + key); | ||
} | ||
}, | ||
//main function used to define tests | ||
cases: function(pOptions) | ||
} | ||
var Challenge = ( | ||
{ | ||
var tmpAllCaseData = pOptions; | ||
if (pOptions.constructor !== Array) | ||
//main function used to define tests | ||
cases: function(pOptions) | ||
{ | ||
tmpAllCaseData = []; | ||
var tmpAllCaseData = pOptions; | ||
//load test case data according to options | ||
if (pOptions.groups) | ||
if (pOptions.constructor !== Array) | ||
{ | ||
pOptions.groups.forEach(function(group) | ||
tmpAllCaseData = []; | ||
//load test case data according to options | ||
if (pOptions.groups) | ||
{ | ||
if (!group.name) | ||
throw Error('Group definition missing name!'); | ||
var tmpGroupCases = Challenge.loadTestCases(group); | ||
for(var x=0; x<tmpGroupCases.length; x++) | ||
pOptions.groups.forEach(function(group) | ||
{ | ||
var tmpCase = {}; | ||
if (!group.name) | ||
throw Error('Group definition missing name!'); | ||
tmpCase.groupIndex = x; | ||
tmpCase.groupName = group.name; | ||
tmpCase.data = tmpGroupCases[x]; | ||
var tmpGroupCases = Challenge.loadTestCases(group); | ||
for(var x=0; x<tmpGroupCases.length; x++) | ||
{ | ||
var tmpCase = {}; | ||
tmpAllCaseData.push(tmpCase); | ||
} | ||
}); | ||
} | ||
else if (pOptions.joins) | ||
{ | ||
pOptions.joins.forEach(function(join) | ||
tmpCase.groupIndex = x; | ||
tmpCase.groupName = group.name; | ||
tmpCase.data = tmpGroupCases[x]; | ||
tmpAllCaseData.push(tmpCase); | ||
} | ||
}); | ||
} | ||
else if (pOptions.joins) | ||
{ | ||
if (!join.name) | ||
throw Error('Join definition missing name!'); | ||
pOptions.joins.forEach(function(join) | ||
{ | ||
if (!join.name) | ||
throw Error('Join definition missing name!'); | ||
var tmpJoinCases = Challenge.loadTestCases(join); | ||
for(var x=0; x<tmpJoinCases.length; x++) | ||
{ | ||
if (tmpAllCaseData[x]) | ||
var tmpJoinCases = Challenge.loadTestCases(join); | ||
for(var x=0; x<tmpJoinCases.length; x++) | ||
{ | ||
tmpAllCaseData[x][join.name] = tmpJoinCases[x]; | ||
if (tmpAllCaseData[x]) | ||
{ | ||
tmpAllCaseData[x][join.name] = tmpJoinCases[x]; | ||
} | ||
else | ||
{ | ||
var tmpCase = {}; | ||
tmpCase[join.name] = tmpJoinCases[x]; | ||
tmpAllCaseData.push(tmpCase); | ||
} | ||
} | ||
else | ||
{ | ||
var tmpCase = {}; | ||
tmpCase[join.name] = tmpJoinCases[x]; | ||
tmpAllCaseData.push(tmpCase); | ||
} | ||
} | ||
}); | ||
}); | ||
} | ||
else | ||
{ | ||
tmpAllCaseData = Challenge.loadTestCases(pOptions); | ||
} | ||
} | ||
else | ||
{ | ||
tmpAllCaseData = Challenge.loadTestCases(pOptions); | ||
} | ||
} | ||
var testDefinition = ( | ||
{ | ||
run: function(fTest, fDone) | ||
var testDefinition = ( | ||
{ | ||
libAsync.eachSeries(tmpAllCaseData, fTest, fDone); | ||
}, | ||
test: function(pName, fTest) | ||
{ | ||
for (var i=0; i<tmpAllCaseData.length; i++) | ||
run: function(fTest, fDone) | ||
{ | ||
//keep test case data contextualized with the test function definition | ||
var testClosure = function(testCase) | ||
libAsync.eachSeries(tmpAllCaseData, fTest, fDone); | ||
}, | ||
test: function(pName, fTest) | ||
{ | ||
for (var i=0; i<tmpAllCaseData.length; i++) | ||
{ | ||
return function(fDone) | ||
//keep test case data contextualized with the test function definition | ||
var testClosure = function(testCase) | ||
{ | ||
return fTest(testCase, fDone); | ||
return function(fDone) | ||
{ | ||
return fTest(testCase, fDone); | ||
} | ||
} | ||
} | ||
//define name for test | ||
var tmpTestName = pName + ' case '; | ||
if (tmpAllCaseData[i].groupName) | ||
{ | ||
tmpTestName += util.format('\'%s %s\'', tmpAllCaseData[i].groupName, tmpAllCaseData[i].groupIndex); | ||
} | ||
else | ||
{ | ||
if (typeof(tmpAllCaseData[i]) === 'string') | ||
//define name for test | ||
var tmpTestName = pName + ' case '; | ||
if (tmpAllCaseData[i].groupName) | ||
{ | ||
tmpTestName += util.format('\'%s\'', tmpAllCaseData[i]); | ||
tmpTestName += util.format('\'%s %s\'', tmpAllCaseData[i].groupName, tmpAllCaseData[i].groupIndex); | ||
} | ||
else | ||
{ | ||
//number each test | ||
tmpTestName += i; | ||
} | ||
} | ||
//generate a test around the case data | ||
test | ||
( | ||
tmpTestName, | ||
testClosure(tmpAllCaseData[i]) | ||
); | ||
} | ||
//make this chainable | ||
return testDefinition; | ||
}, | ||
testApi: function(pName, pOptions, fValidation) | ||
{ | ||
return testDefinition.test(pName, function(pCase, fDone) | ||
{ | ||
var tmpOptions = (typeof(pOptions) === 'function') ? pOptions(pCase) : pOptions; | ||
if (!tmpOptions) | ||
throw Error('No request options defined for testApi() method!'); | ||
var postBody = tmpOptions.postBody; | ||
if (!postBody) | ||
{ | ||
if (pCase.data) | ||
if (typeof(tmpAllCaseData[i]) === 'string') | ||
{ | ||
postBody = pCase.data; | ||
tmpTestName += util.format('\'%s\'', tmpAllCaseData[i]); | ||
} | ||
else | ||
{ | ||
postBody = pCase; | ||
//number each test | ||
tmpTestName += i; | ||
} | ||
} | ||
//generate a test around the case data | ||
test | ||
( | ||
tmpTestName, | ||
testClosure(tmpAllCaseData[i]) | ||
); | ||
} | ||
tmpOptions.url = tmpOptions.url || ''; | ||
//make this chainable | ||
return testDefinition; | ||
}, | ||
testApi: function(pName, pOptions, fValidation) | ||
{ | ||
return testDefinition.test(pName, function(pCase, fDone) | ||
{ | ||
var tmpOptions = (typeof(pOptions) === 'function') ? pOptions(pCase) : pOptions; | ||
if (!tmpOptions) | ||
throw Error('No request options defined for testApi() method!'); | ||
var tmpRequest = null; | ||
var tmpfPrevalidator = null; //function to perform simple (pre)validation for convenience, or in case no validator is specified | ||
switch(tmpOptions.method) | ||
{ | ||
case 'GET': //Read | ||
tmpRequest = libSuperTest | ||
.get(tmpOptions.url); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
var postBody = tmpOptions.postBody; | ||
if (!postBody) | ||
{ | ||
if (pCase.data) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(typeof(pResponse.body)) | ||
.to.equal('object'); //TODO: this is pretty generic. Maybe work off single vs. Array | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
return fNext(); | ||
postBody = pCase.data; | ||
} | ||
break; | ||
case 'PUT': //Update | ||
tmpRequest = libSuperTest | ||
.put(tmpOptions.url) | ||
.send(postBody); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
else | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
postBody = pCase; | ||
} | ||
} | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
tmpOptions.url = tmpOptions.url || ''; | ||
//TODO: check ID field | ||
var tmpRequest = null; | ||
var tmpfPrevalidator = null; //function to perform simple (pre)validation for convenience, or in case no validator is specified | ||
return fNext(); | ||
} | ||
break; | ||
case 'POST': //Create | ||
tmpRequest = libSuperTest | ||
.post(tmpOptions.url) | ||
.send(postBody); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
switch(tmpOptions.method) | ||
{ | ||
case 'GET': //Read | ||
tmpRequest = libSuperTest | ||
.get(tmpOptions.url); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
//TODO: check ID field | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(typeof(pResponse.body)) | ||
.to.equal('object'); //TODO: this is pretty generic. Maybe work off single vs. Array | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
return fNext(); | ||
} | ||
break; | ||
case 'DEL': | ||
case 'DELETE': //Delete | ||
tmpRequest = libSuperTest | ||
.del(tmpOptions.url); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
return fNext(); | ||
} | ||
break; | ||
case 'PUT': //Update | ||
tmpRequest = libSuperTest | ||
.put(tmpOptions.url) | ||
.send(postBody); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body.Success) | ||
.to.equal(true); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
return fNext(); | ||
} | ||
break; | ||
default: | ||
throw Error(util.format('Request method \'%s\' not supported!', tmpOptions.method)); | ||
} | ||
//TODO: check ID field | ||
//Send the request, run the specified validation method | ||
tmpRequest.end( | ||
function (pError, pResponse) | ||
{ | ||
if (!fValidation) | ||
return fNext(); | ||
} | ||
break; | ||
case 'POST': //Create | ||
tmpRequest = libSuperTest | ||
.post(tmpOptions.url) | ||
.send(postBody); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body) | ||
.to.not.have.property('Error'); | ||
//TODO: check ID field | ||
return fNext(); | ||
} | ||
break; | ||
case 'DEL': | ||
case 'DELETE': //Delete | ||
tmpRequest = libSuperTest | ||
.del(tmpOptions.url); | ||
tmpfPrevalidator = function(pError, pResponse, pCase, fNext) | ||
{ | ||
if (pError) | ||
return fNext(pError); | ||
Expect(pResponse.statusCode) | ||
.to.equal(200); //expect 200 OK | ||
Expect(pResponse.body) | ||
.to.be.an('object'); | ||
Expect(pResponse.body.Success) | ||
.to.equal(true); | ||
return fNext(); | ||
} | ||
break; | ||
default: | ||
throw Error(util.format('Request method \'%s\' not supported!', tmpOptions.method)); | ||
} | ||
//Send the request, run the specified validation method | ||
tmpRequest.end( | ||
function (pError, pResponse) | ||
{ | ||
return tmpfPrevalidator(pError, pResponse, pCase, fDone); | ||
} | ||
else | ||
{ | ||
if (tmpOptions.preValidate) | ||
if (!fValidation) | ||
{ | ||
tmpfPrevalidator(pError, pResponse, pCase, function(err) | ||
{ | ||
return fValidation(err, pResponse, pCase, fDone); | ||
}); | ||
return tmpfPrevalidator(pError, pResponse, pCase, fDone); | ||
} | ||
else | ||
{ | ||
return fValidation(pError, pResponse, pCase, fDone); | ||
if (tmpOptions.preValidate) | ||
{ | ||
tmpfPrevalidator(pError, pResponse, pCase, function(err) | ||
{ | ||
return fValidation(err, pResponse, pCase, fDone); | ||
}); | ||
} | ||
else | ||
{ | ||
return fValidation(pError, pResponse, pCase, fDone); | ||
} | ||
} | ||
} | ||
} | ||
); | ||
}); | ||
} | ||
}); | ||
); | ||
}); | ||
} | ||
}); | ||
return testDefinition; | ||
}, | ||
return testDefinition; | ||
}, | ||
//Load JSON data as test cases, filter according to options | ||
loadTestCases: function(pOptions) | ||
{ | ||
if (!pOptions.loadFrom) | ||
throw Error('No path specified to load test JSON!'); | ||
//Load JSON data as test cases, filter according to options | ||
loadTestCases: function(pOptions) | ||
{ | ||
if (!pOptions.loadFrom) | ||
throw Error('No path specified to load test JSON!'); | ||
var pJsonPath = pOptions.loadFrom; | ||
var pJsonPath = pOptions.loadFrom; | ||
if (pJsonPath && pJsonPath[0] !== '/') | ||
pJsonPath = _BaseJsonPath + pJsonPath; | ||
//use require to load and cache json files | ||
var tmpTestJson = require(pJsonPath); | ||
if (pJsonPath && pJsonPath[0] !== '/') | ||
pJsonPath = _BaseJsonPath + pJsonPath; | ||
//use require to load and cache json files | ||
var tmpTestJson = require(pJsonPath); | ||
if (tmpTestJson.constructor !== Array) | ||
throw Error('JSON data for test cases is not valid! ' + pJsonPath); | ||
if (tmpTestJson.constructor !== Array) | ||
throw Error('JSON data for test cases is not valid! ' + pJsonPath); | ||
//make a copy of it, so that any modifications don't change the original | ||
tmpTestJson = JSON.parse(JSON.stringify(tmpTestJson)); //TODO: optimize this | ||
//make a copy of it, so that any modifications don't change the original | ||
tmpTestJson = JSON.parse(JSON.stringify(tmpTestJson)); //TODO: optimize this | ||
if (pOptions.index) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(pOptions.index, 1); | ||
if (pOptions.index) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(pOptions.index, 1); | ||
} | ||
if (pOptions.max) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(0, pOptions.max); | ||
} | ||
if (pOptions.range) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(pOptions.range[0], pOptions.range[1]-pOptions.range[0]+1); | ||
} | ||
return tmpTestJson; | ||
} | ||
if (pOptions.max) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(0, pOptions.max); | ||
} | ||
if (pOptions.range) | ||
{ | ||
tmpTestJson = tmpTestJson.splice(pOptions.range[0], pOptions.range[1]-pOptions.range[0]+1); | ||
} | ||
}); | ||
return tmpTestJson; | ||
} | ||
return Challenge; | ||
} | ||
module.exports = ( | ||
{ | ||
new: ChallengeInitializer | ||
}); | ||
module.exports = Challenge; |
@@ -13,4 +13,2 @@ /** | ||
var Challenge = require('../source/Challenge'); | ||
var _TestWebServerPort = 8080; | ||
@@ -75,13 +73,5 @@ | ||
{ | ||
Challenge = require('../source/Challenge').new({ServerURL: pBaseUrl}); | ||
test | ||
( | ||
'Challenge should initialize with support for REST request test generation', | ||
function() | ||
{ | ||
Challenge.initialize({ServerURL: pBaseUrl}); | ||
} | ||
); | ||
//Utilize chaining feature, run two tests on each endpoint (GET,POST,PUT,DEL) | ||
@@ -88,0 +78,0 @@ Challenge |
@@ -13,3 +13,3 @@ /** | ||
var Challenge = require('../source/Challenge'); | ||
var Challenge = require('../source/Challenge').new(); | ||
@@ -16,0 +16,0 @@ suite |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
18235
529