3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
7 <link rel="import" href="/tvcm/unittest.html">
8 <link rel="import" href="/tvcm/unittest/suite_loader.html">
9 <link rel="import" href="/tvcm/unittest/test_runner.html">
10 <link rel="import" href="/tvcm/unittest/html_test_results.html">
11 <link rel="stylesheet" href="/tvcm/unittest/common.css">
13 x-base-interactive-test-runner {
14 display: -webkit-flex;
15 -webkit-flex-direction: column;
18 x-base-interactive-test-runner > * {
19 -webkit-flex: 0 0 auto;
21 x-base-interactive-test-runner > #title {
25 x-base-interactive-test-runner {
26 font-family: sans-serif;
29 x-base-interactive-test-runner > h1 {
30 margin: 5px 0px 10px 0px;
33 x-base-interactive-test-runner > #stats {
36 x-base-interactive-test-runner > #controls {
41 x-base-interactive-test-runner > #controls > ul {
42 list-style-type: none;
47 x-base-interactive-test-runner > #controls > ul > li {
54 x-base-interactive-test-runner > #shortform-results {
55 word-break: break-all;
59 x-base-interactive-test-runner > #results-container {
60 -webkit-flex: 1 1 auto;
67 <template id="x-base-interactive-test-runner-template">
68 <h1 id="title">Tests</h1>
69 <div id="stats"></div>
73 <div style="clear: both;"></div>
77 <input type="radio" name="test-type-to-run" value="unit" />
81 <input type="radio" name="test-type-to-run" value="perf" />
86 <input type="checkbox" id="short-format" /> Short format
89 <div id="shortform-results">
91 <div id="results-container">
98 tvcm.exportTo('tvcm.unittest', function() {
99 var THIS_DOC = document.currentScript.ownerDocument;
104 var InteractiveTestRunner = tvcm.ui.define('x-base-interactive-test-runner');
106 InteractiveTestRunner.prototype = {
107 __proto__: HTMLUnknownElement.prototype,
109 decorate: function() {
110 this.allTests_ = undefined;
112 this.suppressStateChange_ = false;
114 this.testFilterString_ = '';
115 this.testTypeToRun_ = tvcm.unittest.TestTypes.UNITTEST;
116 this.shortFormat_ = false;
117 this.testSuiteName_ = '';
119 this.rerunPending_ = false;
120 this.runner_ = undefined;
121 this.results_ = undefined;
123 this.onResultsStatsChanged_ = this.onResultsStatsChanged_.bind(this);
124 this.onTestFailed_ = this.onTestFailed_.bind(this);
125 this.onTestPassed_ = this.onTestPassed_.bind(this);
128 this.appendChild(tvcm.instantiateTemplate(
129 '#x-base-interactive-test-runner-template', THIS_DOC));
132 'input[name=test-type-to-run][value=unit]').checked = true;
133 var testTypeToRunEls = tvcm.asArray(this.querySelectorAll(
134 'input[name=test-type-to-run]'));
136 testTypeToRunEls.forEach(
138 inputEl.addEventListener(
139 'click', this.onTestTypeToRunClick_.bind(this));
142 var shortFormatEl = this.querySelector('#short-format');
143 shortFormatEl.checked = this.shortFormat_;
144 shortFormatEl.addEventListener(
145 'click', this.onShortFormatClick_.bind(this));
146 this.updateShortFormResultsDisplay_();
148 // Oh, DOM, how I love you. Title is such a convenient property name and I
149 // refuse to change my worldview because of tooltips.
150 this.__defineSetter__(
153 this.querySelector('#title').textContent = title;
158 return this.allTests_;
161 set allTests(allTests) {
162 this.allTests_ = allTests;
163 this.scheduleRerun_();
167 return this.testLinks_;
169 set testLinks(testLinks) {
170 this.testLinks_ = testLinks;
171 var linksEl = this.querySelector('#links');
172 linksEl.textContent = '';
173 this.testLinks_.forEach(function(l) {
174 var link = document.createElement('a');
175 link.href = l.linkPath;
176 link.textContent = l.title;
178 var li = document.createElement('li');
179 li.appendChild(link);
181 linksEl.appendChild(li);
185 get testFilterString() {
186 return this.testFilterString_;
189 set testFilterString(testFilterString) {
190 this.testFilterString_ = testFilterString;
191 this.scheduleRerun_();
192 if (!this.suppressStateChange_)
193 tvcm.dispatchSimpleEvent(this, 'statechange');
197 return this.shortFormat_;
200 set shortFormat(shortFormat) {
201 this.shortFormat_ = shortFormat;
202 this.querySelector('#short-format').checked = shortFormat;
204 this.results_.shortFormat = shortFormat;
205 if (!this.suppressStateChange_)
206 tvcm.dispatchSimpleEvent(this, 'statechange');
209 onShortFormatClick_: function(e) {
210 this.shortFormat_ = this.querySelector('#short-format').checked;
211 this.updateShortFormResultsDisplay_();
212 this.updateResultsGivenShortFormat_();
213 if (!this.suppressStateChange_)
214 tvcm.dispatchSimpleEvent(this, 'statechange');
217 updateShortFormResultsDisplay_: function() {
218 var display = this.shortFormat_ ? '' : 'none';
219 this.querySelector('#shortform-results').style.display = display;
222 updateResultsGivenShortFormat_: function() {
226 if (this.testFilterString_.length || this.testSuiteName_.length)
227 this.results_.showHTMLOutput = true;
229 this.results_.showHTMLOutput = false;
230 this.results_.showPendingAndPassedTests = this.shortFormat_;
233 get testTypeToRun() {
234 return this.testTypeToRun_;
237 set testTypeToRun(testTypeToRun) {
238 this.testTypeToRun_ = testTypeToRun;
240 if (testTypeToRun == tvcm.unittest.TestTypes.UNITTEST)
241 sel = 'input[name=test-type-to-run][value=unit]';
243 sel = 'input[name=test-type-to-run][value=perf]';
244 this.querySelector(sel).checked = true;
245 this.scheduleRerun_();
246 if (!this.suppressStateChange_)
247 tvcm.dispatchSimpleEvent(this, 'statechange');
250 onTestTypeToRunClick_: function(e) {
251 if (e.target.value == 'unit')
252 this.testTypeToRun_ = tvcm.unittest.TestTypes.UNITTEST;
253 else // e.value == 'perf'
254 this.testTypeToRun_ = tvcm.unittest.TestTypes.PERFTEST;
255 this.scheduleRerun_();
256 if (!this.suppressStateChange_)
257 tvcm.dispatchSimpleEvent(this, 'statechange');
260 onTestPassed_: function() {
261 this.querySelector('#shortform-results').textContent += '.';
264 onTestFailed_: function() {
265 this.querySelector('#shortform-results').textContent += 'F';
268 onResultsStatsChanged_: function() {
269 var statsEl = this.querySelector('#stats');
270 var stats = this.results_.getStats();
271 var numTestsOverall = this.runner_.testCases.length;
272 var numTestsThatRan = stats.numTestsThatPassed + stats.numTestsThatFailed;
274 '<span>' + numTestsThatRan + '/' + numTestsOverall +
275 '</span> tests run, ' +
276 '<span class="unittest-failed">' + stats.numTestsThatFailed +
277 '</span> failures, ' +
278 ' in ' + stats.totalRunTime.toFixed(2) + 'ms.';
281 scheduleRerun_: function() {
282 if (this.rerunPending_)
285 this.rerunPending_ = true;
286 this.runner_.beginToStopRunning();
287 var doRerun = function() {
288 this.rerunPending_ = false;
289 this.scheduleRerun_();
291 this.runner_.runCompletedPromise.then(
295 this.beginRunning_();
298 beginRunning_: function() {
299 var resultsContainer = this.querySelector('#results-container');
301 this.results_.removeEventListener('testpassed',
303 this.results_.removeEventListener('testfailed',
305 this.results_.removeEventListener('statschange',
306 this.onResultsStatsChanged_);
307 delete this.results_.getHRefForTestCase;
308 resultsContainer.removeChild(this.results_);
311 this.results_ = new tvcm.unittest.HTMLTestResults();
312 this.results_.getHRefForTestCase = this.getHRefForTestCase.bind(this);
313 this.updateResultsGivenShortFormat_();
315 this.results_.shortFormat = this.shortFormat_;
316 this.results_.addEventListener('testpassed',
318 this.results_.addEventListener('testfailed',
320 this.results_.addEventListener('statschange',
321 this.onResultsStatsChanged_);
322 resultsContainer.appendChild(this.results_);
324 var tests = this.allTests_.filter(function(test) {
325 var i = test.fullyQualifiedName.indexOf(this.testFilterString_);
328 if (test.testType != this.testTypeToRun_)
333 this.runner_ = new tvcm.unittest.TestRunner(this.results_, tests);
334 this.runner_.beginRunning();
336 this.runner_.runCompletedPromise.then(
337 this.runCompleted_.bind(this),
338 this.runCompleted_.bind(this));
341 setState: function(state, opt_suppressStateChange) {
342 this.suppressStateChange_ = true;
343 if (state.testFilterString !== undefined)
344 this.testFilterString = state.testFilterString;
346 this.testFilterString = '';
348 if (state.shortFormat === undefined)
349 this.shortFormat = false;
351 this.shortFormat = state.shortFormat;
353 if (state.testTypeToRun === undefined)
354 this.testTypeToRun = tvcm.unittest.TestTypes.UNITTEST;
356 this.testTypeToRun = state.testTypeToRun;
358 this.testSuiteName_ = state.testSuiteName || '';
360 if (!opt_suppressStateChange)
361 this.suppressStateChange_ = false;
363 this.onShortFormatClick_();
364 this.scheduleRerun_();
365 this.suppressStateChange_ = false;
368 getDefaultState: function() {
370 testFilterString: '',
373 testTypeToRun: tvcm.unittest.TestTypes.UNITTEST
377 getState: function() {
379 testFilterString: this.testFilterString_,
380 testSuiteName: this.testSuiteName_,
381 shortFormat: this.shortFormat_,
382 testTypeToRun: this.testTypeToRun_
386 getHRefForTestCase: function(testCases) {
390 runCompleted_: function() {
391 this.runner_ = undefined;
392 if (this.results_.getStats().numTestsThatFailed > 0) {
393 this.querySelector('#shortform-results').textContent +=
394 '[THERE WERE FAILURES]';
396 this.querySelector('#shortform-results').textContent += '[DONE]';
402 InteractiveTestRunner: InteractiveTestRunner