Skip to content

Commit 87f7bf5

Browse files
committed
extracting utils functions from main code into its own module + tests
1 parent ef90cad commit 87f7bf5

File tree

7 files changed

+78
-48
lines changed

7 files changed

+78
-48
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ Things to do:
2121
- remove dependency from express and connect
2222
- storing of client timings on first result postback (there's a todo in the `results` function about where to do this)
2323
- document more things
24-
- tests for everything
25-
- add examples for every frameworks
24+
- better unit test code coverage for everything
25+
- add examples for every web frameworks
2626
- add examples for every provider
2727
- add more providers (mongodb, mysql, redis)
28-
- remove old ids from global storage
28+
- remove old ids from global storage (when?)
2929
- add eslint to travis

examples/express/server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ app.get('/', function (req, res) {
1717

1818
app.get('/multi-query', function (req, res) {
1919
pg.connect(connString, function (err, client, done) {
20-
client.query('SELECT pg_sleep(1)', [], function (err, result) {
21-
client.query('SELECT $1::int AS number', ['2'], function (err, result) {
20+
client.query('SELECT pg_sleep(1)', [], function (err) {
21+
client.query('SELECT $1::int AS number', ['2'], function (err) {
2222
done();
2323
res.render('multi-query');
2424
});

lib/miniprofiler.js

Lines changed: 11 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ var os = require('os');
1414
var path = require('path');
1515
var qs = require('querystring');
1616
var url = require('url');
17+
var utils = require('./utils.js');
18+
var uuid = require('node-uuid');
1719

1820
_.templateSettings = {
1921
interpolate: /\{(.+?)\}/g
@@ -122,13 +124,6 @@ var includes = {
122124
share: _.template(fs.readFileSync(path.join(includesDir, 'share.html')).toString())
123125
};
124126

125-
// FUNCTIONS
126-
if (typeof String.prototype.startsWith != 'function') {
127-
String.prototype.startsWith = function (str){
128-
return this.slice(0, str.length) == str;
129-
};
130-
}
131-
132127
function middleware(f) {
133128
if(!f) f = function() { return true; };
134129
return function(req, res, next) {
@@ -227,7 +222,7 @@ function addProfilingInstrumentation(toInstrument) {
227222
throw new Error('toInstrument must be set');
228223
}
229224

230-
if(!isObject(toInstrument)) {
225+
if(!utils.isObject(toInstrument)) {
231226
throw new Error('toInstrument must be an object');
232227
}
233228

@@ -254,7 +249,7 @@ function startProfiling(request, enabled) {
254249
currentRequestExtension.startTime = process.hrtime();
255250
currentRequestExtension.stopTime = null;
256251
currentRequestExtension.stepGraph = makeStep(request.path, currentRequestExtension.startTime, null);
257-
currentRequestExtension.id = makeGuid();
252+
currentRequestExtension.id = uuid.v4();
258253
currentRequestExtension.customTimings = {};
259254
}
260255
currentRequestExtension.timeQuery = function() {
@@ -363,9 +358,9 @@ function timeQuery(extension, type, query, executeFunction) {
363358
}
364359

365360
var customTiming = {
366-
id: makeGuid(),
361+
id: uuid.v4(),
367362
executeType: type,
368-
commandString: htmlEscape(query),
363+
commandString: utils.htmlEscape(query),
369364
startTime: time,
370365
startDate: startDate,
371366
callStack: new Error().stack
@@ -374,7 +369,7 @@ function timeQuery(extension, type, query, executeFunction) {
374369

375370
for(var i = 0; i < params.length; i++){
376371
var param = params[i];
377-
if(isFunction(params[i])){
372+
if(utils.isFunction(params[i])){
378373
params[i] = function() {
379374
customTiming.stopTime = process.hrtime();
380375

@@ -390,15 +385,6 @@ function timeQuery(extension, type, query, executeFunction) {
390385
return ret;
391386
}
392387

393-
function htmlEscape(str) {
394-
return String(str)
395-
.replace(/&/g, '&amp;')
396-
.replace(/"/g, '&quot;')
397-
.replace(/'/g, '&#39;')
398-
.replace(/</g, '&lt;')
399-
.replace(/>/g, '&gt;');
400-
}
401-
402388
function unstep(name, request, failed) {
403389
var time = process.hrtime();
404390

@@ -415,14 +401,6 @@ function unstep(name, request, failed) {
415401
extension.stepGraph = extension.stepGraph.parent;
416402
}
417403

418-
function makeGuid() {
419-
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript
420-
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
421-
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
422-
return v.toString(16);
423-
});
424-
}
425-
426404
function describePerformance(root, request) {
427405
var ret = {};
428406

@@ -461,7 +439,7 @@ function callStack(stack) {
461439
}
462440

463441
function describeTimings(timing, root){
464-
var id = makeGuid();
442+
var id = uuid.v4();
465443
var name = timing.name;
466444
var elapsedMs = diff(timing.startTime, timing.stopTime);
467445
var sinceRootMs = diff(root.startTime, timing.startTime);
@@ -513,15 +491,6 @@ function makeStep(name, time, parent){
513491
return { name: name, startTime: time, stopTime: null, parent: parent, steps: [], customTimings: {} };
514492
}
515493

516-
function isObject(val) {
517-
return Function.prototype.call.bind(Object.prototype.toString)(val) == '[object Object]';
518-
}
519-
520-
function isFunction(func) {
521-
var getType = {};
522-
return getType.toString.call(func) === '[object Function]';
523-
}
524-
525494
function instrument(func, defaultName) {
526495
var name = func.name || defaultName || 'Unnamed';
527496

@@ -533,7 +502,7 @@ function instrument(func, defaultName) {
533502
if(args) {
534503
for(var i = 0; i < args.length; i++){
535504
var arg = args[i];
536-
if(arg && isFunction(arg)){
505+
if(arg && utils.isFunction(arg)){
537506
args[i] = instrument(arg, name+' arg #'+i);
538507
}
539508
}
@@ -579,13 +548,13 @@ function addProfilingImpl(toInstrument) {
579548
continue;
580549
}
581550

582-
if(isObject(toWrap)) {
551+
if(utils.isObject(toWrap)) {
583552
addProfilingImpl(toWrap);
584553

585554
continue;
586555
}
587556

588-
if(isFunction(toWrap)) {
557+
if(utils.isFunction(toWrap)) {
589558
var wrappedFunc = instrument(toWrap, prop);
590559

591560
toInstrument[prop] = wrappedFunc;

lib/utils.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
if (typeof String.prototype.startsWith != 'function') {
2+
String.prototype.startsWith = function (str){
3+
return this.slice(0, str.length) == str;
4+
};
5+
}
6+
7+
module.exports = {
8+
9+
isObject: function(val) {
10+
return Function.prototype.call.bind(Object.prototype.toString)(val) == '[object Object]';
11+
},
12+
13+
isFunction: function(func) {
14+
var getType = {};
15+
return getType.toString.call(func) === '[object Function]';
16+
},
17+
18+
htmlEscape: function(str) {
19+
return String(str)
20+
.replace(/&/g, '&amp;')
21+
.replace(/"/g, '&quot;')
22+
.replace(/'/g, '&#39;')
23+
.replace(/</g, '&lt;')
24+
.replace(/>/g, '&gt;');
25+
}
26+
27+
};

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"license": "Apache-2.0",
1717
"readmeFilename": "README.md",
1818
"dependencies": {
19+
"node-uuid": "^1.4.7",
1920
"underscore": "1.5.2"
2021
},
2122
"devDependencies": {

tests/static-assets-test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ describe('MiniProfiler Static Assets Tests', function() {
1010
'includes.css',
1111
'includes.tmpl',
1212
'includes.js'
13-
]
13+
];
1414

1515
files.forEach((file) => {
1616
it(`Should return ${file} file`, function(done) {

tests/utils-test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var expect = require('chai').expect;
2+
var utils = require('../lib/utils.js');
3+
4+
describe('Utils Tests', function() {
5+
[
6+
[ 'apple', 'ap' ],
7+
[ 'Apple', 'Ap' ]
8+
].forEach((testCase) => {
9+
it(`${testCase[0]} should start with ${testCase[1]}`, function() {
10+
expect(testCase[0].startsWith(testCase[1])).to.be.true;
11+
});
12+
});
13+
14+
[
15+
[ 'Apple', 'ap' ],
16+
[ 'apple', 'at' ]
17+
].forEach((testCase) => {
18+
it(`${testCase[0]} should not start with ${testCase[1]}`, function() {
19+
expect(testCase[0].startsWith(testCase[1])).to.be.false;
20+
});
21+
});
22+
23+
[
24+
[ 'a=1&b=2', 'a=1&amp;b=2' ],
25+
[ '"Hello"', '&quot;Hello&quot;' ],
26+
[ `'World'`, '&#39;World&#39;' ],
27+
[ '<title/>', '&lt;title/&gt;' ]
28+
].forEach((testCase) => {
29+
it(`${testCase[0]} should escape to ${testCase[1]}`, function() {
30+
expect(utils.htmlEscape(testCase[0])).to.be.equal(testCase[1]);
31+
});
32+
});
33+
});

0 commit comments

Comments
 (0)