blob: 61b9a110a0aecf906f93a8a14ecb7711052f2e60 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->
<link rel="import" href="/base/unittest.html">
<link rel="import" href="/base/unittest/suite_loader.html">
<link rel="import" href="/base/unittest/test_runner.html">
<link rel="import" href="/base/unittest/html_test_results.html">
<link rel="stylesheet" href="/base/unittest/common.css">
<style>
x-base-interactive-test-runner {
display: -webkit-flex;
-webkit-flex-direction: column;
}
x-base-interactive-test-runner > * {
-webkit-flex: 0 0 auto;
}
x-base-interactive-test-runner > #title {
font-size: 16pt;
}
x-base-interactive-test-runner {
font-family: sans-serif;
}
x-base-interactive-test-runner > h1 {
margin: 5px 0px 10px 0px;
}
x-base-interactive-test-runner > #stats {
}
x-base-interactive-test-runner > #controls {
display: block;
margin-bottom: 5px;
}
x-base-interactive-test-runner > #controls > ul {
list-style-type: none;
padding: 0;
margin: 0;
}
x-base-interactive-test-runner > #controls > ul > li {
float: left;
margin-right: 10px;
padding-top: 5px;
padding-bottom: 5px;
}
x-base-interactive-test-runner > #shortform-results {
word-break: break-all;
height; 40px;
}
x-base-interactive-test-runner > #results-container {
-webkit-flex: 1 1 auto;
min-height: 0;
overflow: auto;
padding: 0 4px 0 4px;
}
</style>
<template id="x-base-interactive-test-runner-template">
<h1 id="title">Tests</h1>
<div id="stats"></div>
<div id="controls">
<ul id="links">
</ul>
<div style="clear: both;"></div>
<div>
<span>
<input type="radio" name="test-type-to-run" value="unit" />
Run unit tests
</span>
<span>
<input type="radio" name="test-type-to-run" value="perf" />
Run perf tests
</span>
<span>
<input type="radio" name="test-type-to-run" value="all" />
Run all tests
</span>
</div>
<span>
<input type="checkbox" id="short-format" /> Short format
</span>
</div>
<div id="shortform-results">
</div>
<div id="results-container">
</div>
</template>
<script>
'use strict';
tr.exportTo('tr.b.unittest', function() {
var THIS_DOC = document.currentScript.ownerDocument;
var ALL_TEST_TYPES = 'all';
/**
* @constructor
*/
var InteractiveTestRunner = tr.b.ui.define('x-base-interactive-test-runner');
InteractiveTestRunner.prototype = {
__proto__: HTMLUnknownElement.prototype,
decorate: function() {
this.allTests_ = undefined;
this.suppressStateChange_ = false;
this.testFilterString_ = '';
this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
this.shortFormat_ = false;
this.testSuiteName_ = '';
this.rerunPending_ = false;
this.runner_ = undefined;
this.results_ = undefined;
this.headless_ = false;
this.onResultsStatsChanged_ = this.onResultsStatsChanged_.bind(this);
this.onTestFailed_ = this.onTestFailed_.bind(this);
this.onTestPassed_ = this.onTestPassed_.bind(this);
this.appendChild(tr.b.instantiateTemplate(
'#x-base-interactive-test-runner-template', THIS_DOC));
this.querySelector(
'input[name=test-type-to-run][value=unit]').checked = true;
var testTypeToRunEls = tr.b.asArray(this.querySelectorAll(
'input[name=test-type-to-run]'));
testTypeToRunEls.forEach(
function(inputEl) {
inputEl.addEventListener(
'click', this.onTestTypeToRunClick_.bind(this));
}, this);
var shortFormatEl = this.querySelector('#short-format');
shortFormatEl.checked = this.shortFormat_;
shortFormatEl.addEventListener(
'click', this.onShortFormatClick_.bind(this));
this.updateShortFormResultsDisplay_();
// Oh, DOM, how I love you. Title is such a convenient property name and I
// refuse to change my worldview because of tooltips.
this.__defineSetter__(
'title',
function(title) {
this.querySelector('#title').textContent = title;
});
},
get allTests() {
return this.allTests_;
},
set allTests(allTests) {
this.allTests_ = allTests;
this.scheduleRerun_();
},
get testLinks() {
return this.testLinks_;
},
set testLinks(testLinks) {
this.testLinks_ = testLinks;
var linksEl = this.querySelector('#links');
linksEl.textContent = '';
this.testLinks_.forEach(function(l) {
var link = document.createElement('a');
link.href = l.linkPath;
link.textContent = l.title;
var li = document.createElement('li');
li.appendChild(link);
linksEl.appendChild(li);
}, this);
},
get testFilterString() {
return this.testFilterString_;
},
set testFilterString(testFilterString) {
this.testFilterString_ = testFilterString;
this.scheduleRerun_();
if (!this.suppressStateChange_)
tr.b.dispatchSimpleEvent(this, 'statechange');
},
get shortFormat() {
return this.shortFormat_;
},
set shortFormat(shortFormat) {
this.shortFormat_ = shortFormat;
this.querySelector('#short-format').checked = shortFormat;
if (this.results_)
this.results_.shortFormat = shortFormat;
if (!this.suppressStateChange_)
tr.b.dispatchSimpleEvent(this, 'statechange');
},
onShortFormatClick_: function(e) {
this.shortFormat_ = this.querySelector('#short-format').checked;
this.updateShortFormResultsDisplay_();
this.updateResultsGivenShortFormat_();
if (!this.suppressStateChange_)
tr.b.dispatchSimpleEvent(this, 'statechange');
},
updateShortFormResultsDisplay_: function() {
var display = this.shortFormat_ ? '' : 'none';
this.querySelector('#shortform-results').style.display = display;
},
updateResultsGivenShortFormat_: function() {
if (!this.results_)
return;
if (this.testFilterString_.length || this.testSuiteName_.length)
this.results_.showHTMLOutput = true;
else
this.results_.showHTMLOutput = false;
this.results_.showPendingAndPassedTests = this.shortFormat_;
},
get testTypeToRun() {
return this.testTypeToRun_;
},
set testTypeToRun(testTypeToRun) {
this.testTypeToRun_ = testTypeToRun;
var sel;
switch (testTypeToRun) {
case tr.b.unittest.TestTypes.UNITTEST:
sel = 'input[name=test-type-to-run][value=unit]';
break;
case tr.b.unittest.TestTypes.PERFTEST:
sel = 'input[name=test-type-to-run][value=perf]';
break;
case ALL_TEST_TYPES:
sel = 'input[name=test-type-to-run][value=all]';
break;
default:
throw new Error('Invalid test type to run: ' + testTypeToRun);
}
this.querySelector(sel).checked = true;
this.scheduleRerun_();
if (!this.suppressStateChange_)
tr.b.dispatchSimpleEvent(this, 'statechange');
},
onTestTypeToRunClick_: function(e) {
switch (e.target.value) {
case 'unit':
this.testTypeToRun_ = tr.b.unittest.TestTypes.UNITTEST;
break;
case 'perf':
this.testTypeToRun_ = tr.b.unittest.TestTypes.PERFTEST;
break;
case 'all':
this.testTypeToRun_ = ALL_TEST_TYPES;
break;
default:
throw new Error('Inalid test type: ' + e.target.value);
}
this.scheduleRerun_();
if (!this.suppressStateChange_)
tr.b.dispatchSimpleEvent(this, 'statechange');
},
onTestPassed_: function() {
this.querySelector('#shortform-results').textContent += '.';
},
onTestFailed_: function() {
this.querySelector('#shortform-results').textContent += 'F';
},
onResultsStatsChanged_: function() {
var statsEl = this.querySelector('#stats');
var stats = this.results_.getStats();
var numTestsOverall = this.runner_.testCases.length;
var numTestsThatRan = stats.numTestsThatPassed + stats.numTestsThatFailed;
statsEl.innerHTML =
'<span>' + numTestsThatRan + '/' + numTestsOverall +
'</span> tests run, ' +
'<span class="unittest-failed">' + stats.numTestsThatFailed +
'</span> failures, ' +
' in ' + stats.totalRunTime.toFixed(2) + 'ms.';
},
scheduleRerun_: function() {
if (this.rerunPending_)
return;
if (this.runner_) {
this.rerunPending_ = true;
this.runner_.beginToStopRunning();
var doRerun = function() {
this.rerunPending_ = false;
this.scheduleRerun_();
}.bind(this);
this.runner_.runCompletedPromise.then(
doRerun, doRerun);
return;
}
this.beginRunning_();
},
beginRunning_: function() {
var resultsContainer = this.querySelector('#results-container');
if (this.results_) {
this.results_.removeEventListener('testpassed',
this.onTestPassed_);
this.results_.removeEventListener('testfailed',
this.onTestFailed_);
this.results_.removeEventListener('statschange',
this.onResultsStatsChanged_);
delete this.results_.getHRefForTestCase;
resultsContainer.removeChild(this.results_);
}
this.results_ = new tr.b.unittest.HTMLTestResults();
this.results_.headless = this.headless_;
this.results_.getHRefForTestCase = this.getHRefForTestCase.bind(this);
this.updateResultsGivenShortFormat_();
this.results_.shortFormat = this.shortFormat_;
this.results_.addEventListener('testpassed',
this.onTestPassed_);
this.results_.addEventListener('testfailed',
this.onTestFailed_);
this.results_.addEventListener('statschange',
this.onResultsStatsChanged_);
resultsContainer.appendChild(this.results_);
var tests = this.allTests_.filter(function(test) {
var i = test.fullyQualifiedName.indexOf(this.testFilterString_);
if (i == -1)
return false;
if (this.testTypeToRun_ !== ALL_TEST_TYPES &&
test.testType !== this.testTypeToRun_)
return false;
return true;
}, this);
this.runner_ = new tr.b.unittest.TestRunner(this.results_, tests);
this.runner_.beginRunning();
this.runner_.runCompletedPromise.then(
this.runCompleted_.bind(this),
this.runCompleted_.bind(this));
},
setState: function(state, opt_suppressStateChange) {
this.suppressStateChange_ = true;
if (state.testFilterString !== undefined)
this.testFilterString = state.testFilterString;
else
this.testFilterString = '';
if (state.shortFormat === undefined)
this.shortFormat = false;
else
this.shortFormat = state.shortFormat;
if (state.testTypeToRun === undefined)
this.testTypeToRun = tr.b.unittest.TestTypes.UNITTEST;
else
this.testTypeToRun = state.testTypeToRun;
this.testSuiteName_ = state.testSuiteName || '';
this.headless_ = state.headless || false;
if (!opt_suppressStateChange)
this.suppressStateChange_ = false;
this.onShortFormatClick_();
this.scheduleRerun_();
this.suppressStateChange_ = false;
},
getDefaultState: function() {
return {
testFilterString: '',
testSuiteName: '',
shortFormat: false,
testTypeToRun: tr.b.unittest.TestTypes.UNITTEST
};
},
getState: function() {
return {
testFilterString: this.testFilterString_,
testSuiteName: this.testSuiteName_,
shortFormat: this.shortFormat_,
testTypeToRun: this.testTypeToRun_
};
},
getHRefForTestCase: function(testCases) {
return undefined;
},
runCompleted_: function() {
this.runner_ = undefined;
if (this.results_.getStats().numTestsThatFailed > 0) {
this.querySelector('#shortform-results').textContent +=
'[THERE WERE FAILURES]';
} else {
this.querySelector('#shortform-results').textContent += '[DONE]';
}
}
};
return {
InteractiveTestRunner: InteractiveTestRunner
};
});
</script>