Comparing version 1.5.1 to 2.0.0
@@ -19,24 +19,20 @@ const wd = require('wd'); | ||
return session | ||
.sleep(500) | ||
.setWindowSize(1024, 768).catch(() => {}) | ||
.setWindowSize(1024, 768).catch(() => { | ||
return session.sleep(100).setWindowSize(1024, 768).catch(() => {}); | ||
}) | ||
.get(opts.url) | ||
.then(() => { | ||
return Promise.resolve() | ||
.then(() => { | ||
if (opts.scroll || opts.reporter === 'fps') { | ||
return session.execute('var dir=-1;function f () { window.scrollBy(0,dir*=-1); window.requestAnimationFrame(f); } window.requestAnimationFrame(f);'); | ||
} | ||
}) | ||
.then(() => { | ||
if (typeof opts.inject === 'function') { | ||
return opts.inject(session); | ||
} | ||
}) | ||
.then(() => { | ||
return session.waitFor(wd.asserters.jsCondition(`document.readyState==='complete'`), 120000) | ||
.catch(() => { | ||
console.error('Page loading timed out after 120s'); | ||
}); | ||
}) | ||
.then(() => { | ||
if (opts.scroll || opts.reporter === 'fps') { | ||
return session.execute('var dir=-1;function f () { window.scrollBy(0,dir*=-1); window.requestAnimationFrame(f); } window.requestAnimationFrame(f);'); | ||
} | ||
}) | ||
.then(() => { | ||
if (typeof opts.inject === 'function') { | ||
return opts.inject(session); | ||
} | ||
}) | ||
.then(() => { | ||
return session.waitFor(wd.asserters.jsCondition(`document.readyState==='complete'`), 120000) | ||
.catch(() => { | ||
console.error('Page loading timed out after 120s'); | ||
return session; | ||
@@ -43,0 +39,0 @@ }); |
const statistics = require('statistics'); | ||
const mapValues = require('lodash.mapValues'); | ||
@@ -55,3 +56,3 @@ function metrics (set) { | ||
const results = timings.map(t => t[key]).filter(t => t); | ||
const stats = results.reduce(statistics); | ||
const stats = results.length ? results.reduce(statistics) : {}; | ||
return { | ||
@@ -68,5 +69,4 @@ mean: stats.mean, | ||
m = m || metrics; | ||
return data.map((d) => { | ||
return mapValues(data, (d) => { | ||
const timings = d.map(m); | ||
return Object.keys(timings[0]) | ||
@@ -73,0 +73,0 @@ .reduce((list, key) => { |
@@ -11,6 +11,8 @@ const babar = require('babar'); | ||
module.exports = function (data, options) { | ||
return data.map((d, i) => { | ||
module.exports = function (data, metric) { | ||
const options = Object.keys(data).map(u => ({ caption: `${u} - ${metric}` })); | ||
return Object.keys(data).map((key, i) => { | ||
const d = data[key][metric].raw; | ||
return chart(d, options[i]); | ||
}); | ||
}; |
const babar = require('babar'); | ||
function chart (data) { | ||
function chart (data, url) { | ||
return babar(data.map((fps, i) => { | ||
return [i, fps]; | ||
}), { caption: 'scrolling fps', height: 10 }); | ||
}), { caption: `scrolling fps - ${url}`, height: 15 }); | ||
} | ||
@@ -32,5 +32,6 @@ | ||
module.exports = function (data) { | ||
return data.map(d => { | ||
return d.map(run => chart(fps(run))); | ||
return Object.keys(data).map((key) => { | ||
const d = data[key]; | ||
return d.map(run => chart(fps(run), key)); | ||
}); | ||
}; |
@@ -6,44 +6,65 @@ 'use strict'; | ||
const Table = require('cli-table'); | ||
const union = require('lodash.union'); | ||
function getMetrics (result) { | ||
return union.apply(null, Object.keys(result).map(key => Object.keys(result[key]))); | ||
} | ||
function table (result, headings) { | ||
let head, rows; | ||
headings = headings || []; | ||
if (result.length === 1) { | ||
headings = headings || Object.keys(result) || []; | ||
const metrics = getMetrics(result); | ||
const urls = Object.keys(result); | ||
if (urls.length === 1) { | ||
result = result[urls[0]]; | ||
head = ['metric', 'mean', 'min', 'max']; | ||
rows = Object.keys(result[0]) | ||
.map((metric) => [ | ||
rows = metrics.map((metric) => { | ||
const stddev = typeof result[metric].stddev === 'number' ? `(+/-${result[metric].stddev.toFixed(3)})` : ''; | ||
let mean = result[metric].mean; | ||
if (!mean && result[metric].raw.length === 1) { | ||
mean = result[metric].raw[0]; | ||
} | ||
return [ | ||
metric, | ||
`${result[0][metric].mean.toFixed(3)} (+/-${result[0][metric].stddev.toFixed(2)})`, | ||
result[0][metric].min.toFixed(3), | ||
result[0][metric].max.toFixed(3) | ||
]); | ||
} else if (result.length === 2) { | ||
`${mean.toFixed(3)} ${stddev}`, | ||
result[metric].min.toFixed(3), | ||
result[metric].max.toFixed(3) | ||
]; | ||
}); | ||
} else { | ||
head = ['metric']; | ||
result.forEach((r, i) => head.push(headings[i] || i)); | ||
head.push('p < 0.05'); | ||
rows = Object.keys(result[0]) | ||
.map((metric) => { | ||
const row = result.map((res) => { | ||
return res[metric] && res[metric].mean; | ||
}); | ||
const min = Math.min.apply(Math, row); | ||
const max = Math.max.apply(Math, row); | ||
urls.forEach((r, i) => head.push(headings[i] || i)); | ||
if (urls.length === 2) { | ||
head.push('p < 0.05'); | ||
} | ||
rows = metrics.map((metric) => { | ||
const row = urls.map((url) => { | ||
return result[url][metric] && result[url][metric].mean; | ||
}); | ||
const min = Math.min.apply(Math, row); | ||
const max = Math.max.apply(Math, row); | ||
const colored = row.reduce((r, m, i) => { | ||
let value = typeof m === 'number' ? m.toFixed(3) : '-'; | ||
const stddev = typeof result[i][metric].stddev === 'number' ? result[i][metric].stddev.toFixed(2) : '-'; | ||
if (m === min) { | ||
value = chalk.green(value); | ||
} else if (m === max) { | ||
value = chalk.red(value); | ||
} | ||
r.push(`${value} (±${stddev})`); | ||
return r; | ||
}, [metric]); | ||
if (result[0][metric] && result[1][metric] && result[0][metric].raw.length > 1 && result[1][metric].raw.length > 1) { | ||
const tt = ttest(result[0][metric].raw, result[1][metric].raw, { varEqual: true }); | ||
const colored = urls.reduce((r, url) => { | ||
const m = result[url][metric]; | ||
let value = typeof m.mean === 'number' ? m.mean.toFixed(3) : '-'; | ||
const stddev = typeof m.stddev === 'number' ? m.stddev.toFixed(3) : '-'; | ||
if (m === min) { | ||
value = chalk.green(value); | ||
} else if (m === max) { | ||
value = chalk.red(value); | ||
} | ||
r.push(`${value} (±${stddev})`); | ||
return r; | ||
}, [metric]); | ||
// if doing a two-up comparison, add a column for p-values | ||
if (urls.length === 2) { | ||
const result0 = result[urls[0]][metric]; | ||
const result1 = result[urls[1]][metric]; | ||
if (result0 && result1 && result0.raw.length > 1 && result1.raw.length > 1) { | ||
const tt = ttest(result0.raw, result1.raw, { varEqual: true }); | ||
if (!tt.valid()) { | ||
colored.push(tt.pValue().toFixed(3) + ' ' + chalk.green('✔')); | ||
colored.push(`${tt.pValue().toFixed(3)} ${chalk.green('✔')}`); | ||
} else { | ||
colored.push(tt.pValue().toFixed(3) + ' ' + chalk.red('✘')); | ||
colored.push(`${tt.pValue().toFixed(3)} ${chalk.red('✘')}`); | ||
} | ||
@@ -53,4 +74,5 @@ } else { | ||
} | ||
return colored; | ||
}); | ||
} | ||
return colored; | ||
}); | ||
} | ||
@@ -57,0 +79,0 @@ |
@@ -38,5 +38,11 @@ 'use strict'; | ||
}, []) | ||
.then(zip); | ||
.then(zip) | ||
.then((results) => { | ||
return opts.url.reduce((set, url, i) => { | ||
set[url] = results[i]; | ||
return set; | ||
}, {}); | ||
}); | ||
} | ||
module.exports = runner; |
{ | ||
"name": "timeliner", | ||
"version": "1.5.1", | ||
"version": "2.0.0", | ||
"description": "Automated Browser Timeline Analyser", | ||
@@ -28,2 +28,4 @@ "main": "index.js", | ||
"cli-table": "^0.3.1", | ||
"lodash.mapvalues": "^4.6.0", | ||
"lodash.union": "^4.6.0", | ||
"minimist": "^1.2.0", | ||
@@ -30,0 +32,0 @@ "statistics": "^3.3.0", |
@@ -81,7 +81,7 @@ # timeliner | ||
*CLI only* - set the reporter to be used to output results - supported values: `table` (default), `chart|<metric>`, `basic`, `fps`, `json` | ||
*CLI only* - set the reporter to be used to output results - supported values: `table` (default), `chart:<metric>`, `basic`, `fps`, `json` | ||
If the `chart|<metric>` reporter is used, then `<metric>` must be a metric name present in the result set. e.g. `chart|load` will output a chart showing the value of the load metric for each run. | ||
If the `chart:<metric>` reporter is used, then `<metric>` must be a metric name present in the result set. e.g. `chart:load` will output a chart showing the value of the load metric for each run. | ||
Multiple reporters can also be specified by separating with a comma. e.g. `chart|load,table` will output load time charts, and a table of all metrics. | ||
Multiple reporters can also be specified by separating with a comma. e.g. `chart:load,table` will output load time charts, and a table of all metrics. | ||
@@ -88,0 +88,0 @@ ### `progress` |
Sorry, the diff of this file is not supported yet
28275
25
528
13
+ Addedlodash.mapvalues@^4.6.0
+ Addedlodash.union@^4.6.0
+ Addedlodash.mapvalues@4.6.0(transitive)