Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 339 lines (283 sloc) 10.719 kB
9821eb6 @victorjonsson initial commit...
authored
1 var filesystem = require('fs'),
2 util = require('util'),
3 querystring = require('querystring');
4
7ae499d @victorjonsson wip...
authored
5
9821eb6 @victorjonsson initial commit...
authored
6 /**
7 * @param {Object} options
8 */
9 function mergeWithDefaultOptions(options) {
66f81a6 @victorjonsson closing in on a beta release
authored
10 if(options.url == undefined)
9821eb6 @victorjonsson initial commit...
authored
11 throw new Error('property url missing from options');
66f81a6 @victorjonsson closing in on a beta release
authored
12 if(options.port == undefined)
13 options.port = 80;
14 if(options.headers == undefined)
15 options.headers = {};
16 if(options.write == undefined)
17 options.write = '';
18 if(options.method == undefined)
19 options.method = 'GET';
7ae499d @victorjonsson wip...
authored
20
21 if(typeof options.write != 'string')
22 options.write = querystring.stringify(options.write);
23
66f81a6 @victorjonsson closing in on a beta release
authored
24 if(options.headers['Content-Length'] == undefined && typeof options.write == 'string')
25 options.headers['Content-Length'] = Buffer.byteLength(options.write, 'utf8');
7ae499d @victorjonsson wip...
authored
26
66f81a6 @victorjonsson closing in on a beta release
authored
27 if(typeof options.url == 'object')
28 options.path = querystring.stringify(options.url);
9821eb6 @victorjonsson initial commit...
authored
29 else
66f81a6 @victorjonsson closing in on a beta release
authored
30 options.path = options.url;
9821eb6 @victorjonsson initial commit...
authored
31
66f81a6 @victorjonsson closing in on a beta release
authored
32 if(options.headers['User-Agent'] == undefined)
33 options['User-Agent'] = 'node dokimon scraper';
7ae499d @victorjonsson wip...
authored
34
35 if(options.timeout == undefined)
36 options.timeout = 8000;
9821eb6 @victorjonsson initial commit...
authored
37 }
38
39
40 /** * * * * * * * * * * * * * * * * * * * * * * * *
41 * @class {TestManager}
42 * @param {Object} config
43 * @param {Function} testFinishCallback - Optional
44 * * * * * * * * * * * * * * * * * * * * * * * * */
45 var TestManager = function(config, testFinishCallback) {
46
47 this.index = 0;
48 this.successes = [];
49 this.fails = [];
50 this.tests = [];
51
52 /**
53 * Wrapper that makes it possible to handle the
54 * message with something other then console.log
55 *
56 * @param {String} message
57 */
58 this.log = function(message) {
59 if(config.log)
60 config.log(message);
61 else
62 console.log(message);
63 };
64
65 /**
7c6efcd @victorjonsson work in progress...
authored
66 * @param {Test[]} tests
9821eb6 @victorjonsson initial commit...
authored
67 */
68 this.setTests = function(tests) {
7c6efcd @victorjonsson work in progress...
authored
69 this.tests = tests;
9821eb6 @victorjonsson initial commit...
authored
70 };
71
72 /**
73 * Runs tests starting from current position of this.index
74 */
75 this.run = function() {
76 if(config.verbose)
77 this.log('Running scripts starting from '+this.index);
78
79 for(var i=this.index; i < this.tests.length; i++) {
80 // blocking request
81 if(this.tests[i].blocking) {
82 if(config.verbose)
7ae499d @victorjonsson wip...
authored
83 this.log('Blocking upcoming tests on index '+i+' for '+this.tests[i].name);
9821eb6 @victorjonsson initial commit...
authored
84
85 this.index = i+1;
86 var self = this;
87 this.tests[i].execute(config.host, this, config.verbose, function() {
88 self.run();
89 });
90 break;
91 }
92 else
93 this.tests[i].execute(config.host, this, config.verbose);
94 }
95 };
96
97 /**
98 * Run a specific test in the test list
99 *
100 * @param {String} testName
101 * @param {Boolean} verbose - Optional
102 */
103 this.runTest = function(testName, verbose) {
104 for(var i=0; i < this.tests.length; i++) {
105 if(this.tests[i].name == testName) {
7ae499d @victorjonsson wip...
authored
106 this.tests[i].execute(config.host, this, config.verbose);
9821eb6 @victorjonsson initial commit...
authored
107 return;
108 }
109 }
110
111 throw new Error('Test not found');
112 };
113
114 /**
115 * @param {Object} success
116 */
117 this.registerSuccessfullTest = function(success) {
118 this.successes.push(success);
119 this.log('* '+success.name + ' successfull');
120 _checkIfFinished(this);
121 };
122
123 /**
124 * @param {Object} fail
125 * @param {Error} err - Optional
126 */
127 this.registerFailedtest = function(fail, err) {
128 this.fails.push(fail);
129 this.log('- '+fail.name + " FAILED! \n"+fail.message);
130 if(err)
131 this.log(err);
7ae499d @victorjonsson wip...
authored
132 this.log('');
9821eb6 @victorjonsson initial commit...
authored
133 _checkIfFinished(this);
134 };
135
136 /**
137 * Get the correct path to script. Throws error if not exists
138 *
139 * @param {String} name
140 * @return {String}
141 */
142 this.scriptNameToPath = function(name) {
143 var testFileName = name.substring(0, config.testdir.length) == config.testdir ? name : config.testdir+'/'+name;
144 if(!_hasDokimonExtension(testFileName))
145 testFileName += TestManager.TEST_EXTENSION;
146
147 return testFileName;
148 };
149
150 /**
151 * Get a list of all available scripts in given directory
152 *
153 * @param {String} path
154 * @return {Array}
155 */
156 this.loadScriptsInDir = function(path) {
157 var scripts = [];
158 filesystem.readdirSync(path).forEach(function(f) {
159 if(_hasDokimonExtension(f))
160 scripts.push(f.substr(0, f.length - TestManager.TEST_EXTENSION.length));
161 });
162 return scripts;
163 };
164
165 /**
166 * Will output test result to client when test i finished
167 *
168 * @access private
169 * @param {TestManager} manager
170 */
171 var _checkIfFinished = function(manager) {
172 if(manager.tests.length == (manager.successes.length + manager.fails.length)) {
173 if(manager.fails.length == 0) {
174 manager.log("\n------------------------------\nEverything is fine :)");
175 manager.log('Executed a total of '+manager.successes.length+' successfull tests');
176 }
177 else {
178 manager.log("\n------------------------------\nAll is not well :(");
179 manager.log(manager.successes.length+' test'+(manager.successes.length > 1 ? 's':'')+' was successfull');
7ae499d @victorjonsson wip...
authored
180 manager.log(manager.fails.length+' test'+(manager.fails.length > 1 ? 's':'')+' failed');
181 for(var i=0; i < manager.fails.length; i++)
182 manager.log(" - "+manager.fails[i].name+" ("+manager.fails[i].message+")");
9821eb6 @victorjonsson initial commit...
authored
183 }
184
185 manager.log("");
186 if(typeof testFinishCallback == 'function')
187 testFinishCallback(manager);
188 }
189 };
190
191 /**
192 * @access private
193 * @param {String} path
194 * @return {Boolean}
195 */
196 var _hasDokimonExtension = function(path) {
197 return path.substr(-1 * TestManager.TEST_EXTENSION.length) == TestManager.TEST_EXTENSION;
198 };
199 };
200
201
202 /**
203 * Extension for scripts containing tests
204 */
205 TestManager.TEST_EXTENSION = '.dokimon';
206
207
208 /** * * * * * * * * * * * * * * * * * * * * * * * *
209 * @class {Test}
210 * @param {String} testName - Name of this test
211 * @param {Object} options - requires url, optional is port:Number, method:String, write:String and headers:Object
212 * @param {Function} callback - function(response, body)
213 * @param {Boolean} blocking - Optional, whether or not this test is supposed to finish before running any other tests
214 * * * * * * * * * * * * * * * * * * * * * * * * */
215 var Test = function(testName, options, callback, blocking) {
216
66f81a6 @victorjonsson closing in on a beta release
authored
217 mergeWithDefaultOptions(options);
9821eb6 @victorjonsson initial commit...
authored
218
219 this.blocking = blocking;
220 this.name = testName;
221
222 /**
7c6efcd @victorjonsson work in progress...
authored
223 * @param {TestManager} manager
9821eb6 @victorjonsson initial commit...
authored
224 * @param {Boolean} verbose - Optional
225 * @param {Function} exeFinishCallback - Optional, will be called when request is finished and test callback is called
226 */
7c6efcd @victorjonsson work in progress...
authored
227 this.execute = function(host, manager, verbose, exeFinishCallback) {
9821eb6 @victorjonsson initial commit...
authored
228
229 options.host = host;
230
231 if(verbose)
232 manager.log("About to request "+host+" for \n"+JSON.stringify(options).replace(/\,\"/g, ",\n\"")+"\n");
233
7ae499d @victorjonsson wip...
authored
234 var self = this;
235
9821eb6 @victorjonsson initial commit...
authored
236 var req = require('http').request(options, function(res) {
237 var collectedBody = '';
238 res.setEncoding('utf8');
239 res.on('data', function (body) {
240 collectedBody += body;
241 });
242 res.on('end', function() {
7ae499d @victorjonsson wip...
authored
243 if(res.headers.Location != undefined) {
244
245 if(res.headers['Set-Cookie'] != undefined)
246 options.headers['Get-Cookie'] = res.headers['Set-Cookie'];
247
248 options.method = 'GET';
249 options.headers['Content-Length'] = Buffer.byteLength('', 'utf8');
250 options.write = '';
251 options.path = res.headers.Location;
252
253 self.execute(options.host, options, verbose, exeFinishCallback);
7c6efcd @victorjonsson work in progress...
authored
254 }
7ae499d @victorjonsson wip...
authored
255 else {
256 try {
257 callback(res, collectedBody, verbose);
258
259 manager.registerSuccessfullTest({name : testName, message:''});
260 if(typeof exeFinishCallback == 'function')
261 exeFinishCallback();
262 }
263 catch(e) {
264 manager.registerFailedtest({name : testName, message:e.message}, e);
265 if(typeof exeFinishCallback == 'function')
266 exeFinishCallback();
267 }
7c6efcd @victorjonsson work in progress...
authored
268 }
9821eb6 @victorjonsson initial commit...
authored
269 });
270 });
271
272 req.on('error', function(e) {
7c6efcd @victorjonsson work in progress...
authored
273 manager.registerFailedtest({name : testName, message:''}, e);
9821eb6 @victorjonsson initial commit...
authored
274 });
275
7ae499d @victorjonsson wip...
authored
276 req.connection.setTimeout(options.timeout, function() {
277 manager.registerFailedtest({name: testName, message : 'Timeout after '+options.timeout+' ms'}, '');
278 req.abort();
279 if(typeof exeFinishCallback == 'function')
280 exeFinishCallback();
281 });
282
9821eb6 @victorjonsson initial commit...
authored
283 req.write(options.write);
284 req.end();
285 };
286 };
287
288
289 /** * * * * * * * * * * * * * * * * * * * * * * * *
290 * @class {TestFormPost}
291 * @param {String} testName - Name of this test
292 * @param {Object} options - requires url, optional is port:Number, method:String, write:String and headers:Object
293 * @param {Function} callback - function(response, body)
294 * @param {Boolean} blocking - Optional, whether or not this test is supposed to finish before running any other tests
295 * * * * * * * * * * * * * * * * * * * * * * * * */
296 var TestFormPost = function(testName, options, callback, blocking) {
7ae499d @victorjonsson wip...
authored
297
298 TestFormPost.super_.call(this, testName, options, callback, blocking);
299
9821eb6 @victorjonsson initial commit...
authored
300 options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
301 if(typeof(options.write) == 'object')
302 options.write = querystring.stringify(options.write);
303
304 options.headers['Content-Length'] = Buffer.byteLength(options.write, 'utf8');
305
7ae499d @victorjonsson wip...
authored
306 options.method = 'POST';
9821eb6 @victorjonsson initial commit...
authored
307 };
308 util.inherits(TestFormPost, Test);
309
310
311 module.exports = {
312
313 /**
314 * @param {Object} config
315 * @return {TestManager}
316 */
317 TestManager : TestManager,
318
319 /**
320 * @return {Test}
321 */
322 Test : Test,
323
324 /**
66f81a6 @victorjonsson closing in on a beta release
authored
325 * @return {TestFormPost}
326 */
327 TestFormPost: TestFormPost,
328
329 /**
9821eb6 @victorjonsson initial commit...
authored
330 * @param {Test} t
331 */
332 runTest : function(t, config, testFinishCallback) {
333 var manager = new TestManager(config, testFinishCallback);
334 manager.setTests([t]);
335 manager.run();
336 },
337
338 TEST_EXTENSION : TestManager.TEST_EXTENSION
339 };
Something went wrong with that request. Please try again.