Add a slowest specs list to HTMLReporterV2
This commit is contained in:
@@ -35,6 +35,7 @@ jasmineRequire.html = function(j$) {
|
||||
j$.private.SymbolsView = jasmineRequire.SymbolsView(j$);
|
||||
j$.private.SummaryTreeView = jasmineRequire.SummaryTreeView(j$);
|
||||
j$.private.FailuresView = jasmineRequire.FailuresView(j$);
|
||||
j$.private.PerformanceView = jasmineRequire.PerformanceView(j$);
|
||||
j$.private.TabBar = jasmineRequire.TabBar(j$);
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.HtmlReporterV2Urls = jasmineRequire.HtmlReporterV2Urls(j$);
|
||||
@@ -992,6 +993,7 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
|
||||
const specListTabId = 'jasmine-specListTab';
|
||||
const failuresTabId = 'jasmine-failuresTab';
|
||||
const perfTabId = 'jasmine-perfTab';
|
||||
|
||||
/**
|
||||
* @class HtmlReporterV2
|
||||
@@ -1063,13 +1065,16 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
this.#tabBar = new j$.private.TabBar(
|
||||
[
|
||||
{ id: specListTabId, label: 'Spec List' },
|
||||
{ id: failuresTabId, label: 'Failures' }
|
||||
{ id: failuresTabId, label: 'Failures' },
|
||||
{ id: perfTabId, label: 'Performance' }
|
||||
],
|
||||
tabId => {
|
||||
if (tabId === specListTabId) {
|
||||
this.#setMenuModeTo('jasmine-spec-list');
|
||||
} else {
|
||||
} else if (tabId === failuresTabId) {
|
||||
this.#setMenuModeTo('jasmine-failure-list');
|
||||
} else {
|
||||
this.#setMenuModeTo('jasmine-performance');
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -1165,9 +1170,13 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
);
|
||||
summary.addResults(this.#stateBuilder.topResults);
|
||||
results.appendChild(summary.rootEl);
|
||||
const perf = new j$.private.PerformanceView();
|
||||
perf.addResults(this.#stateBuilder.topResults);
|
||||
results.appendChild(perf.rootEl);
|
||||
this.#tabBar.showTab(specListTabId);
|
||||
this.#tabBar.showTab(perfTabId);
|
||||
|
||||
if (this.#stateBuilder.anyNonTopSuiteFailures) {
|
||||
this.#tabBar.showTab(specListTabId);
|
||||
this.#tabBar.showTab(failuresTabId);
|
||||
this.#tabBar.selectTab(failuresTabId);
|
||||
} else {
|
||||
@@ -1495,6 +1504,79 @@ jasmineRequire.OverallStatusBar = function(j$) {
|
||||
return OverallStatusBar;
|
||||
};
|
||||
|
||||
jasmineRequire.PerformanceView = function(j$) {
|
||||
const createDom = j$.private.htmlReporterUtils.createDom;
|
||||
const MAX_SLOW_SPECS = 20;
|
||||
|
||||
class PerformanceView {
|
||||
#tbody;
|
||||
|
||||
constructor() {
|
||||
this.#tbody = document.createElement('tbody');
|
||||
this.rootEl = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-performance-view' },
|
||||
createDom('h2', {}, 'Performance'),
|
||||
createDom('h3', {}, 'Slowest Specs'),
|
||||
createDom(
|
||||
'table',
|
||||
{},
|
||||
createDom(
|
||||
'thead',
|
||||
{},
|
||||
createDom(
|
||||
'tr',
|
||||
{},
|
||||
createDom('th', {}, 'Duration'),
|
||||
createDom('th', {}, 'Spec Name')
|
||||
)
|
||||
),
|
||||
this.#tbody
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
addResults(resultsTree) {
|
||||
let specResults = [];
|
||||
getSpecResults(resultsTree, specResults);
|
||||
|
||||
specResults.sort(function(a, b) {
|
||||
if (a.duration < b.duration) {
|
||||
return 1;
|
||||
} else if (a.duration > b.duration) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
specResults = specResults.slice(0, MAX_SLOW_SPECS);
|
||||
|
||||
for (const r of specResults) {
|
||||
this.#tbody.appendChild(
|
||||
createDom(
|
||||
'tr',
|
||||
{},
|
||||
createDom('td', {}, `${r.duration}ms`),
|
||||
createDom('td', {}, r.fullName)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSpecResults(resultsTree, dest) {
|
||||
for (const node of resultsTree.children) {
|
||||
if (node.type === 'suite') {
|
||||
getSpecResults(node, dest);
|
||||
} else if (node.result.status !== 'excluded') {
|
||||
dest.push(node.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PerformanceView;
|
||||
};
|
||||
|
||||
jasmineRequire.ResultsStateBuilder = function(j$) {
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -198,11 +198,17 @@ body {
|
||||
color: white;
|
||||
}
|
||||
.jasmine_html-reporter.jasmine-spec-list .jasmine-bar.jasmine-menu.jasmine-failure-list,
|
||||
.jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures {
|
||||
.jasmine_html-reporter.jasmine-spec-list .jasmine-results .jasmine-failures,
|
||||
.jasmine_html-reporter.jasmine-spec-list .jasmine-performance-view {
|
||||
display: none;
|
||||
}
|
||||
.jasmine_html-reporter.jasmine-failure-list .jasmine-bar.jasmine-menu.jasmine-spec-list,
|
||||
.jasmine_html-reporter.jasmine-failure-list .jasmine-summary {
|
||||
.jasmine_html-reporter.jasmine-failure-list .jasmine-summary,
|
||||
.jasmine_html-reporter.jasmine-failure-list .jasmine-performance-view {
|
||||
display: none;
|
||||
}
|
||||
.jasmine_html-reporter.jasmine-performance .jasmine-results .jasmine-failures,
|
||||
.jasmine_html-reporter.jasmine-performance .jasmine-summary {
|
||||
display: none;
|
||||
}
|
||||
.jasmine_html-reporter .jasmine-results {
|
||||
|
||||
@@ -275,10 +275,11 @@ describe('HtmlReporterV2', function() {
|
||||
reporter.initialize();
|
||||
reporter.jasmineStarted({ totalSpecsDefined: 0 });
|
||||
const tabs = container.querySelectorAll('.jasmine-tab');
|
||||
expect(tabs.length).toEqual(2);
|
||||
expect(tabs.length).toEqual(3);
|
||||
expect(tabs[0].textContent).toEqual('Spec List');
|
||||
expect(tabs[1].textContent).toEqual('Failures');
|
||||
checkHidden(tabs, [true, true]);
|
||||
expect(tabs[2].textContent).toEqual('Performance');
|
||||
checkHidden(tabs, [true, true, true]);
|
||||
|
||||
// Results, even failures, should not show any tabs
|
||||
reporter.specDone({
|
||||
@@ -289,7 +290,7 @@ describe('HtmlReporterV2', function() {
|
||||
failedExpectations: [{}],
|
||||
passedExpectations: []
|
||||
});
|
||||
checkHidden(tabs, [true, true]);
|
||||
checkHidden(tabs, [true, true, true]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -303,9 +304,9 @@ describe('HtmlReporterV2', function() {
|
||||
reportEvents(reporter);
|
||||
});
|
||||
|
||||
it('shows the Spec List and Failures tabs', function() {
|
||||
it('shows all three tabs', function() {
|
||||
const tabs = container.querySelectorAll('.jasmine-tab');
|
||||
checkHidden(tabs, [false, false]);
|
||||
checkHidden(tabs, [false, false, false]);
|
||||
});
|
||||
|
||||
it('selects the Failures tab', function() {
|
||||
@@ -357,9 +358,9 @@ describe('HtmlReporterV2', function() {
|
||||
reportEvents(reporter);
|
||||
});
|
||||
|
||||
it('does not show any tabs', function() {
|
||||
it('shows the Spec List and Performance tabs', function() {
|
||||
const tabs = container.querySelectorAll('.jasmine-tab');
|
||||
checkHidden(tabs, [true, true]);
|
||||
checkHidden(tabs, [false, true, false]);
|
||||
});
|
||||
|
||||
it('shows the spec list view', function() {
|
||||
@@ -443,6 +444,26 @@ describe('HtmlReporterV2', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('shows the slow spec view when the Performance tab is clicked', function() {
|
||||
const reporter = setup();
|
||||
reporter.initialize();
|
||||
reporter.jasmineStarted({ totalSpecsDefined: 0 });
|
||||
reporter.specDone({
|
||||
duration: 1.2,
|
||||
failedExpectations: [],
|
||||
passedExpectations: []
|
||||
});
|
||||
reporter.jasmineDone({});
|
||||
const tabs = container.querySelectorAll('.jasmine-tab');
|
||||
let perfLink = tabs[2].querySelector('a');
|
||||
const reporterNode = container.querySelector('.jasmine_html-reporter');
|
||||
expect(perfLink.textContent).toEqual('Performance');
|
||||
perfLink.click();
|
||||
expect(reporterNode).toHaveClass('jasmine-performance');
|
||||
expect(reporterNode.innerHTML).toContain('<h2>Performance</h2>');
|
||||
expect(reporterNode.innerHTML).toContain('<td>1.2ms</td>');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
69
spec/html/PerformanceViewSpec.js
Normal file
69
spec/html/PerformanceViewSpec.js
Normal file
@@ -0,0 +1,69 @@
|
||||
'use strict';
|
||||
|
||||
describe('PerformanceView', function() {
|
||||
it('shows specs ordered by execution time', function() {
|
||||
const stateBuilder = new privateUnderTest.ResultsStateBuilder();
|
||||
stateBuilder.suiteStarted({});
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec A',
|
||||
duration: 2
|
||||
});
|
||||
stateBuilder.suiteDone({});
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec B',
|
||||
duration: 1
|
||||
});
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec C',
|
||||
duration: 3
|
||||
});
|
||||
const subject = new privateUnderTest.PerformanceView();
|
||||
subject.addResults(stateBuilder.topResults);
|
||||
|
||||
const rows = Array.from(subject.rootEl.querySelectorAll('tbody tr'));
|
||||
const durations = rows.map(r => r.querySelectorAll('td')[0].textContent);
|
||||
const names = rows.map(r => r.querySelectorAll('td')[1].textContent);
|
||||
expect(names).toEqual(['spec C', 'spec A', 'spec B']);
|
||||
expect(durations).toEqual(['3ms', '2ms', '1ms']);
|
||||
});
|
||||
|
||||
it('shows at most 20 specs', function() {
|
||||
const stateBuilder = new privateUnderTest.ResultsStateBuilder();
|
||||
const subject = new privateUnderTest.PerformanceView();
|
||||
|
||||
for (let i = 0; i < 21; i++) {
|
||||
stateBuilder.specDone({
|
||||
fullName: `spec ${i}`,
|
||||
duration: i
|
||||
});
|
||||
}
|
||||
|
||||
subject.addResults(stateBuilder.topResults);
|
||||
|
||||
expect(subject.rootEl.querySelectorAll('tbody tr').length).toEqual(20);
|
||||
expect(subject.textContent).not.toContain('spec 0');
|
||||
});
|
||||
|
||||
it('filters out excluded specs', function() {
|
||||
const stateBuilder = new privateUnderTest.ResultsStateBuilder();
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec A',
|
||||
duration: 2
|
||||
});
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec B',
|
||||
duration: 1,
|
||||
status: 'excluded'
|
||||
});
|
||||
stateBuilder.specDone({
|
||||
fullName: 'spec C',
|
||||
duration: 3
|
||||
});
|
||||
const subject = new privateUnderTest.PerformanceView();
|
||||
subject.addResults(stateBuilder.topResults);
|
||||
|
||||
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']);
|
||||
});
|
||||
});
|
||||
@@ -5,6 +5,7 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
|
||||
const specListTabId = 'jasmine-specListTab';
|
||||
const failuresTabId = 'jasmine-failuresTab';
|
||||
const perfTabId = 'jasmine-perfTab';
|
||||
|
||||
/**
|
||||
* @class HtmlReporterV2
|
||||
@@ -76,13 +77,16 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
this.#tabBar = new j$.private.TabBar(
|
||||
[
|
||||
{ id: specListTabId, label: 'Spec List' },
|
||||
{ id: failuresTabId, label: 'Failures' }
|
||||
{ id: failuresTabId, label: 'Failures' },
|
||||
{ id: perfTabId, label: 'Performance' }
|
||||
],
|
||||
tabId => {
|
||||
if (tabId === specListTabId) {
|
||||
this.#setMenuModeTo('jasmine-spec-list');
|
||||
} else {
|
||||
} else if (tabId === failuresTabId) {
|
||||
this.#setMenuModeTo('jasmine-failure-list');
|
||||
} else {
|
||||
this.#setMenuModeTo('jasmine-performance');
|
||||
}
|
||||
}
|
||||
);
|
||||
@@ -178,9 +182,13 @@ jasmineRequire.HtmlReporterV2 = function(j$) {
|
||||
);
|
||||
summary.addResults(this.#stateBuilder.topResults);
|
||||
results.appendChild(summary.rootEl);
|
||||
const perf = new j$.private.PerformanceView();
|
||||
perf.addResults(this.#stateBuilder.topResults);
|
||||
results.appendChild(perf.rootEl);
|
||||
this.#tabBar.showTab(specListTabId);
|
||||
this.#tabBar.showTab(perfTabId);
|
||||
|
||||
if (this.#stateBuilder.anyNonTopSuiteFailures) {
|
||||
this.#tabBar.showTab(specListTabId);
|
||||
this.#tabBar.showTab(failuresTabId);
|
||||
this.#tabBar.selectTab(failuresTabId);
|
||||
} else {
|
||||
|
||||
72
src/html/PerformanceView.js
Normal file
72
src/html/PerformanceView.js
Normal file
@@ -0,0 +1,72 @@
|
||||
jasmineRequire.PerformanceView = function(j$) {
|
||||
const createDom = j$.private.htmlReporterUtils.createDom;
|
||||
const MAX_SLOW_SPECS = 20;
|
||||
|
||||
class PerformanceView {
|
||||
#tbody;
|
||||
|
||||
constructor() {
|
||||
this.#tbody = document.createElement('tbody');
|
||||
this.rootEl = createDom(
|
||||
'div',
|
||||
{ className: 'jasmine-performance-view' },
|
||||
createDom('h2', {}, 'Performance'),
|
||||
createDom('h3', {}, 'Slowest Specs'),
|
||||
createDom(
|
||||
'table',
|
||||
{},
|
||||
createDom(
|
||||
'thead',
|
||||
{},
|
||||
createDom(
|
||||
'tr',
|
||||
{},
|
||||
createDom('th', {}, 'Duration'),
|
||||
createDom('th', {}, 'Spec Name')
|
||||
)
|
||||
),
|
||||
this.#tbody
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
addResults(resultsTree) {
|
||||
let specResults = [];
|
||||
getSpecResults(resultsTree, specResults);
|
||||
|
||||
specResults.sort(function(a, b) {
|
||||
if (a.duration < b.duration) {
|
||||
return 1;
|
||||
} else if (a.duration > b.duration) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
specResults = specResults.slice(0, MAX_SLOW_SPECS);
|
||||
|
||||
for (const r of specResults) {
|
||||
this.#tbody.appendChild(
|
||||
createDom(
|
||||
'tr',
|
||||
{},
|
||||
createDom('td', {}, `${r.duration}ms`),
|
||||
createDom('td', {}, r.fullName)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getSpecResults(resultsTree, dest) {
|
||||
for (const node of resultsTree.children) {
|
||||
if (node.type === 'suite') {
|
||||
getSpecResults(node, dest);
|
||||
} else if (node.result.status !== 'excluded') {
|
||||
dest.push(node.result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PerformanceView;
|
||||
};
|
||||
@@ -280,15 +280,25 @@ body {
|
||||
}
|
||||
|
||||
// simplify toggle control between the two menu bars
|
||||
// TODO: clean this up once HtmlReporter is removed
|
||||
&.jasmine-spec-list {
|
||||
.jasmine-bar.jasmine-menu.jasmine-failure-list,
|
||||
.jasmine-results .jasmine-failures {
|
||||
.jasmine-results .jasmine-failures,
|
||||
.jasmine-performance-view {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.jasmine-failure-list {
|
||||
.jasmine-bar.jasmine-menu.jasmine-spec-list,
|
||||
.jasmine-summary,
|
||||
.jasmine-performance-view {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.jasmine-performance {
|
||||
.jasmine-results .jasmine-failures,
|
||||
.jasmine-summary {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ jasmineRequire.html = function(j$) {
|
||||
j$.private.SymbolsView = jasmineRequire.SymbolsView(j$);
|
||||
j$.private.SummaryTreeView = jasmineRequire.SummaryTreeView(j$);
|
||||
j$.private.FailuresView = jasmineRequire.FailuresView(j$);
|
||||
j$.private.PerformanceView = jasmineRequire.PerformanceView(j$);
|
||||
j$.private.TabBar = jasmineRequire.TabBar(j$);
|
||||
j$.HtmlReporter = jasmineRequire.HtmlReporter(j$);
|
||||
j$.HtmlReporterV2Urls = jasmineRequire.HtmlReporterV2Urls(j$);
|
||||
|
||||
Reference in New Issue
Block a user