diff --git a/lib/jasmine-core/jasmine-html.js b/lib/jasmine-core/jasmine-html.js
index 104e3d0f..b7029468 100644
--- a/lib/jasmine-core/jasmine-html.js
+++ b/lib/jasmine-core/jasmine-html.js
@@ -1509,14 +1509,17 @@ jasmineRequire.PerformanceView = function(j$) {
const MAX_SLOW_SPECS = 20;
class PerformanceView {
+ #summary;
#tbody;
constructor() {
this.#tbody = document.createElement('tbody');
+ this.#summary = document.createElement('div');
this.rootEl = createDom(
'div',
{ className: 'jasmine-performance-view' },
createDom('h2', {}, 'Performance'),
+ this.#summary,
createDom('h3', {}, 'Slowest Specs'),
createDom(
'table',
@@ -1537,9 +1540,13 @@ jasmineRequire.PerformanceView = function(j$) {
}
addResults(resultsTree) {
- let specResults = [];
+ const specResults = [];
getSpecResults(resultsTree, specResults);
+ if (specResults.length === 0) {
+ return;
+ }
+
specResults.sort(function(a, b) {
if (a.duration < b.duration) {
return 1;
@@ -1549,6 +1556,25 @@ jasmineRequire.PerformanceView = function(j$) {
return 0;
}
});
+
+ this.#populateSumary(specResults);
+ this.#populateTable(specResults);
+ }
+
+ #populateSumary(specResults) {
+ const total = specResults.map(r => r.duration).reduce((a, b) => a + b, 0);
+ const mean = total / specResults.length;
+ const median = specResults[Math.floor(specResults.length / 2)].duration;
+ this.#summary.appendChild(
+ document.createTextNode(`Mean spec run time: ${mean.toFixed(0)}ms`)
+ );
+ this.#summary.appendChild(document.createElement('br'));
+ this.#summary.appendChild(
+ document.createTextNode(`Median spec run time: ${median}ms`)
+ );
+ }
+
+ #populateTable(specResults) {
specResults = specResults.slice(0, MAX_SLOW_SPECS);
for (const r of specResults) {
diff --git a/lib/jasmine-core/jasmine.css b/lib/jasmine-core/jasmine.css
index 167639d0..24cf47dd 100644
--- a/lib/jasmine-core/jasmine.css
+++ b/lib/jasmine-core/jasmine.css
@@ -337,4 +337,15 @@ body {
.jasmine-tab + .jasmine-tab:before {
content: " | ";
+}
+
+.jasmine-performance-view h2, .jasmine-performance-view h3 {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+.jasmine-performance-view table {
+ border-spacing: 5px;
+}
+.jasmine-performance-view th, .jasmine-performance-view td {
+ text-align: left;
}
\ No newline at end of file
diff --git a/spec/html/PerformanceViewSpec.js b/spec/html/PerformanceViewSpec.js
index 3da3e359..63e5f873 100644
--- a/spec/html/PerformanceViewSpec.js
+++ b/spec/html/PerformanceViewSpec.js
@@ -44,6 +44,42 @@ describe('PerformanceView', function() {
expect(subject.textContent).not.toContain('spec 0');
});
+ it('shows mean and median run times for an odd number of specs', function() {
+ const stateBuilder = new privateUnderTest.ResultsStateBuilder();
+ const subject = new privateUnderTest.PerformanceView();
+
+ stateBuilder.specDone({ duration: 1 });
+ stateBuilder.specDone({ duration: 2 });
+ stateBuilder.specDone({ duration: 5 });
+ subject.addResults(stateBuilder.topResults);
+
+ expect(subject.rootEl.textContent).toContain('Mean spec run time: 3ms');
+ expect(subject.rootEl.textContent).toContain('Median spec run time: 2ms');
+ });
+
+ it('shows mean and median run times for an even number of specs', function() {
+ const stateBuilder = new privateUnderTest.ResultsStateBuilder();
+ const subject = new privateUnderTest.PerformanceView();
+
+ stateBuilder.specDone({ duration: 1 });
+ stateBuilder.specDone({ duration: 3 });
+ stateBuilder.specDone({ duration: 10 });
+ stateBuilder.specDone({ duration: 2 });
+ subject.addResults(stateBuilder.topResults);
+
+ expect(subject.rootEl.textContent).toContain('Mean spec run time: 4ms');
+ expect(subject.rootEl.textContent).toContain('Median spec run time: 2ms');
+ });
+
+ it('copes with 0 specs', function() {
+ const stateBuilder = new privateUnderTest.ResultsStateBuilder();
+ const subject = new privateUnderTest.PerformanceView();
+
+ expect(function() {
+ subject.addResults(stateBuilder.topResults);
+ }).not.toThrow();
+ });
+
it('filters out excluded specs', function() {
const stateBuilder = new privateUnderTest.ResultsStateBuilder();
stateBuilder.specDone({
@@ -65,5 +101,7 @@ describe('PerformanceView', function() {
const rows = Array.from(subject.rootEl.querySelectorAll('tbody tr'));
const names = rows.map(r => r.querySelectorAll('td')[1].textContent);
expect(names).toEqual(['spec C', 'spec A']);
+ expect(subject.rootEl.textContent).toContain('Mean spec run time: 3ms');
+ expect(subject.rootEl.textContent).toContain('Median spec run time: 2ms');
});
});
diff --git a/src/html/PerformanceView.js b/src/html/PerformanceView.js
index fddc5eff..5f1f2948 100644
--- a/src/html/PerformanceView.js
+++ b/src/html/PerformanceView.js
@@ -3,14 +3,17 @@ jasmineRequire.PerformanceView = function(j$) {
const MAX_SLOW_SPECS = 20;
class PerformanceView {
+ #summary;
#tbody;
constructor() {
this.#tbody = document.createElement('tbody');
+ this.#summary = document.createElement('div');
this.rootEl = createDom(
'div',
{ className: 'jasmine-performance-view' },
createDom('h2', {}, 'Performance'),
+ this.#summary,
createDom('h3', {}, 'Slowest Specs'),
createDom(
'table',
@@ -31,9 +34,13 @@ jasmineRequire.PerformanceView = function(j$) {
}
addResults(resultsTree) {
- let specResults = [];
+ const specResults = [];
getSpecResults(resultsTree, specResults);
+ if (specResults.length === 0) {
+ return;
+ }
+
specResults.sort(function(a, b) {
if (a.duration < b.duration) {
return 1;
@@ -43,6 +50,25 @@ jasmineRequire.PerformanceView = function(j$) {
return 0;
}
});
+
+ this.#populateSumary(specResults);
+ this.#populateTable(specResults);
+ }
+
+ #populateSumary(specResults) {
+ const total = specResults.map(r => r.duration).reduce((a, b) => a + b, 0);
+ const mean = total / specResults.length;
+ const median = specResults[Math.floor(specResults.length / 2)].duration;
+ this.#summary.appendChild(
+ document.createTextNode(`Mean spec run time: ${mean.toFixed(0)}ms`)
+ );
+ this.#summary.appendChild(document.createElement('br'));
+ this.#summary.appendChild(
+ document.createTextNode(`Median spec run time: ${median}ms`)
+ );
+ }
+
+ #populateTable(specResults) {
specResults = specResults.slice(0, MAX_SLOW_SPECS);
for (const r of specResults) {
diff --git a/src/html/_HTMLReporter.scss b/src/html/_HTMLReporter.scss
index d6a285fb..e804397f 100644
--- a/src/html/_HTMLReporter.scss
+++ b/src/html/_HTMLReporter.scss
@@ -482,3 +482,18 @@ body {
.jasmine-tab + .jasmine-tab:before {
content: ' | ';
}
+
+.jasmine-performance-view {
+ h2, h3 {
+ margin-top: 1em;
+ margin-bottom: 1em;
+ }
+
+ table {
+ border-spacing: 5px;
+ }
+
+ th, td {
+ text-align: left;
+ }
+}