Index: Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js |
diff --git a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js b/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js |
deleted file mode 100644 |
index 05e597eb493ec4d21c59f4d4b16faf174224404c..0000000000000000000000000000000000000000 |
--- a/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js |
+++ /dev/null |
@@ -1,474 +0,0 @@ |
-/* |
- * Copyright (C) 2011 Google Inc. All rights reserved. |
- * |
- * Redistribution and use in source and binary forms, with or without |
- * modification, are permitted provided that the following conditions |
- * are met: |
- * 1. Redistributions of source code must retain the above copyright |
- * notice, this list of conditions and the following disclaimer. |
- * 2. Redistributions in binary form must reproduce the above copyright |
- * notice, this list of conditions and the following disclaimer in the |
- * documentation and/or other materials provided with the distribution. |
- * |
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' |
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS |
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
- * THE POSSIBILITY OF SUCH DAMAGE. |
- */ |
- |
-var ui = ui || {}; |
-ui.results = ui.results || {}; |
- |
-(function(){ |
- |
-var kResultsPrefetchDelayMS = 500; |
- |
-// FIXME: Rather than using table, should we be using something fancier? |
-ui.results.Comparison = base.extends('table', { |
- init: function() |
- { |
- this.className = 'comparison'; |
- this.innerHTML = '<thead><tr><th>Expected</th><th>Actual</th><th>Diff</th></tr></thead>' + |
- '<tbody><tr><td class="expected result-container"></td><td class="actual result-container"></td><td class="diff result-container"></td></tr></tbody>'; |
- }, |
- _selectorForKind: function(kind) |
- { |
- switch (kind) { |
- case results.kExpectedKind: |
- return '.expected'; |
- case results.kActualKind: |
- return '.actual'; |
- case results.kDiffKind: |
- return '.diff'; |
- } |
- return '.unknown'; |
- }, |
- update: function(kind, result) |
- { |
- var selector = this._selectorForKind(kind); |
- $(selector, this).empty().append(result); |
- return result; |
- }, |
-}); |
- |
-// We'd really like TextResult and ImageResult to extend a common Result base |
-// class, but we can't seem to do that because they inherit from different |
-// HTMLElements. We could have them inherit from <div>, but that seems lame. |
- |
-ui.results.TextResult = base.extends('iframe', { |
- init: function(url) |
- { |
- this.className = 'text-result'; |
- this.src = url; |
- } |
-}); |
- |
-ui.results.ImageResult = base.extends('img', { |
- init: function(url) |
- { |
- this.className = 'image-result'; |
- this.src = url; |
- } |
-}); |
- |
-ui.results.AudioResult = base.extends('audio', { |
- init: function(url) |
- { |
- this.className = 'audio-result'; |
- this.src = url; |
- this.controls = 'controls'; |
- } |
-}); |
- |
-function constructorForResultType(type) |
-{ |
- if (type == results.kImageType) |
- return ui.results.ImageResult; |
- if (type == results.kAudioType) |
- return ui.results.AudioResult; |
- return ui.results.TextResult; |
-} |
- |
-ui.results.ResultsGrid = base.extends('div', { |
- init: function() |
- { |
- this.className = 'results-grid'; |
- }, |
- _addResult: function(comparison, constructor, resultsURLsByKind, kind) |
- { |
- var url = resultsURLsByKind[kind]; |
- if (!url) |
- return; |
- comparison.update(kind, new constructor(url)); |
- }, |
- addComparison: function(resultType, resultsURLsByKind) |
- { |
- var comparison = new ui.results.Comparison(); |
- var constructor = constructorForResultType(resultType); |
- |
- this._addResult(comparison, constructor, resultsURLsByKind, results.kExpectedKind); |
- this._addResult(comparison, constructor, resultsURLsByKind, results.kActualKind); |
- this._addResult(comparison, constructor, resultsURLsByKind, results.kDiffKind); |
- |
- this.appendChild(comparison); |
- return comparison; |
- }, |
- addRow: function(resultType, url) |
- { |
- var constructor = constructorForResultType(resultType); |
- var view = new constructor(url); |
- this.appendChild(view); |
- return view; |
- }, |
- addResults: function(resultsURLs) |
- { |
- var resultsURLsByTypeAndKind = {}; |
- |
- resultsURLsByTypeAndKind[results.kImageType] = {}; |
- resultsURLsByTypeAndKind[results.kAudioType] = {}; |
- resultsURLsByTypeAndKind[results.kTextType] = {}; |
- |
- resultsURLs.forEach(function(url) { |
- resultsURLsByTypeAndKind[results.resultType(url)][results.resultKind(url)] = url; |
- }); |
- |
- $.each(resultsURLsByTypeAndKind, function(resultType, resultsURLsByKind) { |
- if ($.isEmptyObject(resultsURLsByKind)) |
- return; |
- if (results.kUnknownKind in resultsURLsByKind) { |
- // This is something like "crash" that isn't a comparison. |
- this.addRow(resultType, resultsURLsByKind[results.kUnknownKind]); |
- return; |
- } |
- this.addComparison(resultType, resultsURLsByKind); |
- }.bind(this)); |
- |
- if (!this.children.length) |
- this.textContent = 'No results to display.' |
- } |
-}); |
- |
-ui.results.ResultsDetails = base.extends('div', { |
- init: function(delegate, failureInfo) |
- { |
- this.className = 'results-detail'; |
- this._delegate = delegate; |
- this._failureInfo = failureInfo; |
- this._haveShownOnce = false; |
- }, |
- show: function() { |
- if (this._haveShownOnce) |
- return; |
- this._haveShownOnce = true; |
- this._delegate.fetchResultsURLs(this._failureInfo, function(resultsURLs) { |
- var resultsGrid = new ui.results.ResultsGrid(); |
- resultsGrid.addResults(resultsURLs); |
- |
- $(this).empty().append( |
- new ui.actions.List([ |
- new ui.actions.Previous(), |
- new ui.actions.Next() |
- ])).append(resultsGrid); |
- |
- |
- }.bind(this)); |
- }, |
-}); |
- |
-function isAnyReftest(testName, resultsByTest) |
-{ |
- return Object.keys(resultsByTest[testName]).map(function(builder) { |
- return resultsByTest[testName][builder]; |
- }).some(function(resultNode) { |
- return resultNode.reftest_type && resultNode.reftest_type.length; |
- }); |
-} |
- |
-ui.results.FlakinessData = base.extends('iframe', { |
- init: function() |
- { |
- this.className = 'flakiness-iframe'; |
- this.src = ui.urlForEmbeddedFlakinessDashboard(); |
- this.addEventListener('load', function() { |
- window.addEventListener('message', this._handleMessage.bind(this)); |
- }); |
- }, |
- _handleMessage: function(event) { |
- if (!this.contentWindow) |
- return; |
- |
- // Check for null event.origin so that the unittests can get past this point. |
- // FIXME: Is this safe? In practice, there's no meaningful harm that can come from |
- // a malicious page sending us heightChanged commands, so it doesn't really matter. |
- if (event.origin !== 'null' && event.origin != 'http://test-results.appspot.com') { |
- console.log('Invalid origin: ' + event.origin); |
- return; |
- } |
- |
- if (event.data.command != 'heightChanged') { |
- console.log('Unknown postMessage command: ' + event.data); |
- return; |
- } |
- |
- this.style.height = event.data.height + 'px'; |
- } |
-}); |
- |
-ui.results.TestSelector = base.extends('div', { |
- init: function(delegate, resultsByTest) |
- { |
- this.className = 'test-selector'; |
- this._delegate = delegate; |
- |
- var topPanel = document.createElement('div'); |
- topPanel.className = 'top-panel'; |
- this.appendChild(topPanel); |
- |
- this._appendResizeHandle(); |
- |
- var bottomPanel = document.createElement('div'); |
- bottomPanel.className = 'bottom-panel'; |
- this.appendChild(bottomPanel); |
- |
- this._flakinessData = new ui.results.FlakinessData(); |
- this.appendChild(this._flakinessData); |
- |
- var testNames = Object.keys(resultsByTest); |
- testNames.sort().forEach(function(testName) { |
- var nonLinkTitle = document.createElement('a'); |
- nonLinkTitle.classList.add('non-link-title'); |
- nonLinkTitle.textContent = testName; |
- |
- var linkTitle = document.createElement('a'); |
- linkTitle.classList.add('link-title'); |
- linkTitle.setAttribute('href', ui.urlForFlakinessDashboard([testName])) |
- linkTitle.textContent = testName; |
- |
- var header = document.createElement('h3'); |
- header.appendChild(nonLinkTitle); |
- header.appendChild(linkTitle); |
- header.addEventListener('click', this._showResults.bind(this, header, false)); |
- topPanel.appendChild(header); |
- }, this); |
- |
- // If we have a small amount of content, don't show the resize handler. |
- // Otherwise, set the minHeight so that the percentage height of the |
- // topPanel is not too small. |
- if (testNames.length <= 4) |
- this.removeChild(this.querySelector('.resize-handle')); |
- else |
- topPanel.style.minHeight = '100px'; |
- }, |
- _appendResizeHandle: function() |
- { |
- var resizeHandle = document.createElement('div'); |
- resizeHandle.className = 'resize-handle'; |
- this.appendChild(resizeHandle); |
- |
- resizeHandle.addEventListener('mousedown', function(event) { |
- this._is_resizing = true; |
- event.preventDefault(); |
- }.bind(this)); |
- |
- var cancelResize = function(event) { this._is_resizing = false; }.bind(this); |
- this.addEventListener('mouseup', cancelResize); |
- // FIXME: Use addEventListener once WebKit adds support for mouseleave/mouseenter. |
- $(window).bind('mouseleave', cancelResize); |
- |
- this.addEventListener('mousemove', function(event) { |
- if (!this._is_resizing) |
- return; |
- var mouseY = event.clientY + document.body.scrollTop - this.offsetTop; |
- var percentage = 100 * mouseY / this.offsetHeight; |
- document.querySelector('.top-panel').style.maxHeight = percentage + '%'; |
- }.bind(this)) |
- }, |
- _showResults: function(header, scrollInfoView) |
- { |
- if (!header) |
- return false; |
- |
- var activeHeader = this.querySelector('.active') |
- if (activeHeader) |
- activeHeader.classList.remove('active'); |
- header.classList.add('active'); |
- |
- var testName = this.currentTestName(); |
- this._flakinessData.src = ui.urlForEmbeddedFlakinessDashboard([testName]); |
- |
- var bottomPanel = this.querySelector('.bottom-panel') |
- bottomPanel.innerHTML = ''; |
- bottomPanel.appendChild(this._delegate.contentForTest(testName)); |
- |
- var topPanel = this.querySelector('.top-panel'); |
- if (scrollInfoView) { |
- topPanel.scrollTop = header.offsetTop; |
- if (header.offsetTop - topPanel.scrollTop < header.offsetHeight) |
- topPanel.scrollTop = topPanel.scrollTop - header.offsetHeight; |
- } |
- |
- var resultsDetails = this.querySelectorAll('.results-detail'); |
- if (resultsDetails.length) |
- resultsDetails[0].show(); |
- setTimeout(function() { |
- Array.prototype.forEach.call(resultsDetails, function(resultsDetail) { |
- resultsDetail.show(); |
- }); |
- }, kResultsPrefetchDelayMS); |
- |
- return true; |
- }, |
- nextResult: function() |
- { |
- if (this.querySelector('.builder-selector').nextResult()) |
- return true; |
- return this.nextTest(); |
- }, |
- previousResult: function() |
- { |
- if (this.querySelector('.builder-selector').previousResult()) |
- return true; |
- return this.previousTest(); |
- }, |
- nextTest: function() |
- { |
- return this._showResults(this.querySelector('.active').nextSibling, true); |
- }, |
- previousTest: function() |
- { |
- var succeeded = this._showResults(this.querySelector('.active').previousSibling, true); |
- if (succeeded) |
- this.querySelector('.builder-selector').lastResult(); |
- return succeeded; |
- }, |
- firstResult: function() |
- { |
- this._showResults(this.querySelector('h3'), true); |
- }, |
- currentTestName: function() |
- { |
- return this.querySelector('.active .non-link-title').textContent; |
- } |
-}); |
- |
-ui.results.BuilderSelector = base.extends('div', { |
- init: function(delegate, testName, resultsByBuilder) |
- { |
- this.className = 'builder-selector'; |
- this._delegate = delegate; |
- |
- var tabStrip = this.appendChild(document.createElement('ul')); |
- |
- Object.keys(resultsByBuilder).sort().forEach(function(builderName) { |
- var builderHash = base.underscoredBuilderName(builderName); |
- |
- var link = document.createElement('a'); |
- $(link).attr('href', "#" + builderHash).text(ui.displayNameForBuilder(builderName)); |
- tabStrip.appendChild(document.createElement('li')).appendChild(link); |
- |
- var content = this._delegate.contentForTestAndBuilder(testName, builderName); |
- content.id = builderHash; |
- this.appendChild(content); |
- }, this); |
- |
- $(this).tabs(); |
- }, |
- nextResult: function() |
- { |
- var nextIndex = $(this).tabs('option', 'selected') + 1; |
- if (nextIndex >= $(this).tabs('length')) |
- return false |
- $(this).tabs('option', 'selected', nextIndex); |
- return true; |
- }, |
- previousResult: function() |
- { |
- var previousIndex = $(this).tabs('option', 'selected') - 1; |
- if (previousIndex < 0) |
- return false; |
- $(this).tabs('option', 'selected', previousIndex); |
- return true; |
- }, |
- firstResult: function() |
- { |
- $(this).tabs('option', 'selected', 0); |
- }, |
- lastResult: function() |
- { |
- $(this).tabs('option', 'selected', $(this).tabs('length') - 1); |
- } |
-}); |
- |
-ui.results.View = base.extends('div', { |
- init: function(delegate) |
- { |
- this.className = 'results-view'; |
- this._delegate = delegate; |
- }, |
- contentForTest: function(testName) |
- { |
- var rebaselineAction; |
- if (isAnyReftest(testName, this._resultsByTest)) |
- rebaselineAction = $('<div class="non-action-button">Reftests cannot be rebaselined. Email webkit-gardening@chromium.org if unsure how to fix this.</div>'); |
- else |
- rebaselineAction = new ui.actions.List([new ui.actions.Rebaseline().makeDefault()]); |
- $(rebaselineAction).addClass('rebaseline-action'); |
- |
- var builderSelector = new ui.results.BuilderSelector(this, testName, this._resultsByTest[testName]); |
- $(builderSelector).append(rebaselineAction).append($('<br style="clear:both">')); |
- $(builderSelector).bind('tabsselect', function(event, ui) { |
- // We will probably have pre-fetched the tab already, but we need to make sure. |
- ui.panel.show(); |
- }); |
- return builderSelector; |
- }, |
- contentForTestAndBuilder: function(testName, builderName) |
- { |
- var failureInfo = results.failureInfoForTestAndBuilder(this._resultsByTest, testName, builderName); |
- return new ui.results.ResultsDetails(this, failureInfo); |
- }, |
- setResultsByTest: function(resultsByTest) |
- { |
- $(this).empty(); |
- this._resultsByTest = resultsByTest; |
- this._testSelector = new ui.results.TestSelector(this, resultsByTest); |
- this.appendChild(this._testSelector); |
- }, |
- fetchResultsURLs: function(failureInfo, callback) |
- { |
- this._delegate.fetchResultsURLs(failureInfo, callback) |
- }, |
- nextResult: function() |
- { |
- return this._testSelector.nextResult(); |
- }, |
- previousResult: function() |
- { |
- return this._testSelector.previousResult(); |
- }, |
- nextTest: function() |
- { |
- return this._testSelector.nextTest(); |
- }, |
- previousTest: function() |
- { |
- return this._testSelector.previousTest(); |
- }, |
- firstResult: function() |
- { |
- this._testSelector.firstResult() |
- }, |
- currentTestName: function() |
- { |
- return this._testSelector.currentTestName() |
- } |
-}); |
- |
-})(); |