Changeset 94580 in webkit


Ignore:
Timestamp:
Sep 6, 2011 11:02:50 AM (13 years ago)
Author:
abarth@webkit.org
Message:

Use a hierarchial structure for the garden-o-matic results view
https://bugs.webkit.org/show_bug.cgi?id=67620

Reviewed by Dimitri Glazkov.

This patch re-organizes the results view to use a hierachial structure
for selection. At the top-level are sections for each test. Expanding
the test section shows a tab selector for builders.

This structure prepares us for wiring up various actions to this view.

  • BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js:

(.):

  • BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js:

():

  • BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js:

(.):

  • BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results_unittests.js:
  • BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css:

(.results-view>.toolbar):
(.results-view>.toolbar ul.actions):
(.results-view>.toolbar ul.actions li):
(.results-grid table):
(.results-grid table td, .results-view table th):
(.results-grid table th):
(.results-grid .text-result):
(.results-grid .image-result):

Location:
trunk/Tools
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js

    r94540 r94580  
    3333        this._view = view;
    3434        this._resultsByTest = resultsByTest;
    35 
    36         this._view.setTestList(Object.keys(this._resultsByTest));
    3735        this._view.setResultsByTest(resultsByTest);
    38 
    39         this._view.addAction(new ui.actions.Rebaseline().makeDefault());
    40         this._view.addAction(new ui.actions.Previous());
    41         this._view.addAction(new ui.actions.Next());
    42 
    43         $(this._view).bind('testselected', this.onTestSelected.bind(this));
    44         $(this._view).bind('builderselected', this.onBuilderSelected.bind(this));
    45         $(this._view).bind('rebaseline', this.onRebaseline.bind(this));
    46     },
    47     showTest: function(testName)
    48     {
    49         var builderNameList = Object.keys(this._resultsByTest[testName]);
    50         this._view.setBuilderList(builderNameList)
    51         this._view.showResults(results.failureInfoForTestAndBuilder(this._resultsByTest, testName, builderNameList[0]));
    52     },
    53     onTestSelected: function()
    54     {
    55         this.showTest(this._view.currentTestName());
    56     },
    57     onBuilderSelected: function() {
    58         this._view.showResults(results.failureInfoForTestAndBuilder(this._resultsByTest, this._view.currentTestName(), this._view.currentBuilderName()));
    59     },
    60     onRebaseline: function() {
    61         var testName = this._view.currentTestName();
    62         var builderName = this._view.currentBuilderName();
    63         model.queueForRebaseline({
    64             'testName': testName,
    65             'builderName': builderName
    66         });
     36        // FIXME: Wire up some actions.
    6737    },
    6838});
     
    11585
    11686        var controller = new controllers.ResultsDetails(resultsView, failuresByTest);
    117         controller.showTest(testNameList[0]);
    11887
    11988        // FIXME: This doesn't belong here.
  • trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js

    r94486 r94580  
    463463};
    464464
    465 function resultsDirectoryForBuilder(builderName)
     465results.directoryForBuilder = function(builderName)
    466466{
    467467    return builderName.replace(/[ .()]/g, '_');
     
    470470function resultsDirectoryURL(builderName)
    471471{
    472     return kLayoutTestResultsServer + resultsDirectoryForBuilder(builderName) + kLayoutTestResultsPath;
     472    return kLayoutTestResultsServer + results.directoryForBuilder(builderName) + kLayoutTestResultsPath;
    473473}
    474474
  • trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js

    r94539 r94580  
    2929(function(){
    3030
     31var kResultsPrefetchDelayMS = 500;
     32
    3133// FIXME: Rather than using table, should we be using something fancier?
    3234ui.results.Comparison = base.extends('table', {
     
    138140
    139141ui.results.ResultsDetails = base.extends('div', {
    140     init: function(delegate)
     142    init: function(delegate, failureInfo)
    141143    {
    142144        this.className = 'results-detail';
    143145        this._delegate = delegate;
    144     },
    145     show: function(failureInfo) {
    146         this._delegate.fetchResultsURLs(failureInfo, function(resultsURLs) {
     146        this._failureInfo = failureInfo;
     147        this._haveShownOnce = false;
     148    },
     149    show: function() {
     150        if (this._haveShownOnce)
     151            return;
     152        this._haveShownOnce = true;
     153        this._delegate.fetchResultsURLs(this._failureInfo, function(resultsURLs) {
    147154            var resultsGrid = new ui.results.ResultsGrid();
    148155            resultsGrid.addResults(resultsURLs);
     
    152159});
    153160
    154 var Selector = base.extends('select', {
    155     init: function()
    156     {
    157         this._eventName = null;
    158         $(this).change(function() {
    159             if (this._eventName)
    160                 $(this).trigger(this._eventName);
    161         }.bind(this));
    162     },
    163     setItemList: function(itemList)
    164     {
    165         $(this).empty();
    166         itemList.forEach(function(item) {
    167             var element = document.createElement('option');
    168             element.textContent = item.displayName;
    169             element.value = item.name;
    170             this.appendChild(element);
    171         }.bind(this));
    172         $(this).show();
    173     },
    174     select: function(itemName) {
    175         var index = -1;
    176         for (var i = 0; i < this.options.length; ++i) {
    177             if (this.options[i].value == itemName) {
    178                 index = i;
    179                 break;
    180             }
    181         }
    182         if (index == -1)
    183             return;
    184         this.selectedIndex = index;
    185     },
    186     selectedItem: function() {
    187         if (this.selectedIndex == -1)
    188             return;
    189         return this.options[this.selectedIndex].value;
    190     }
    191 });
    192 
    193 ui.results.TestSelector = base.extends(Selector, {
    194     init: function()
     161ui.results.TestSelector = base.extends('div', {
     162    init: function(delegate, resultsByTest)
    195163    {
    196164        this.className = 'test-selector';
    197         this._eventName = 'testselected';
    198     },
    199     setTestList: function(testNameList)
    200     {
    201         this.setItemList(testNameList.map(function(testName) {
    202             return {
    203                 'displayName': testName,
    204                 'name': testName
    205             };
    206         }));
    207     }
    208 });
    209 
    210 ui.results.BuilderSelector = base.extends(Selector, {
    211     init: function()
     165        this._delegate = delegate;
     166
     167        Object.keys(resultsByTest).forEach(function (testName) {
     168            var link = document.createElement('a');
     169            $(link).attr('href', '#').text(testName);
     170            this.appendChild(document.createElement('h3')).appendChild(link);
     171            this.appendChild(this._delegate.contentForTest(testName));
     172        }, this);
     173
     174        $(this).accordion({
     175            collapsible: true,
     176            autoHeight: false,
     177        });
     178        $(this).accordion("activate", false);
     179    }
     180});
     181
     182ui.results.BuilderSelector = base.extends('div', {
     183    init: function(delegate, testName, resultsByBuilder)
    212184    {
    213185        this.className = 'builder-selector';
    214         this._eventName = 'builderselected';
    215     },
    216     setBuilderList: function(builderNameList) {
    217         this.setItemList(builderNameList.map(function(builderName) {
    218             return {
    219                 'displayName': ui.displayNameForBuilder(builderName),
    220                 'name': builderName
    221             };
    222         }));
    223     }
    224 });
    225 
    226 ui.results.ResultsSelector = base.extends('table', {
    227     init: function()
    228     {
    229         this.className = 'results-selector';
    230     },
    231     setResultsByTest: function(resultsByTest)
    232     {
    233         var buildersByTest = base.mapDictionary(resultsByTest, Object.keys);
    234 
    235         var testNameList = Object.keys(buildersByTest);
    236         var builderNameList = base.uniquifyArray(base.flattenArray(base.values(buildersByTest)));
    237         builderNameList.sort();
    238 
    239         var titles = this.createTHead().insertRow();
    240         // Note the reverse iteration because insertCell() inserts at the beginning of the row.
    241         for (var i = builderNameList.length - 1; i >= 0; --i) {
    242             titles.insertCell().textContent = builderNameList[i];
    243         }
    244         titles.insertCell(); // For the test names.
    245 
    246         this._body = this.appendChild(document.createElement('tbody'));
    247 
    248         testNameList.forEach(function(testName) {
    249             var row = this._body.insertRow();
    250             for (var i = builderNameList.length - 1; i >= 0; --i) {
    251                 var cell = row.insertCell();
    252                 var builderName = builderNameList[i];
    253                 if (buildersByTest[testName].indexOf(builderName) != -1) {
    254                     cell.className = 'result';
    255                     cell.textContent = resultsByTest[testName][builderName].actual;
    256                 }
    257             }
    258             var cell = row.insertCell()
    259             cell.className = 'test-name';
    260             cell.textContent = testName;
    261         }.bind(this));
    262     },
     186        this._delegate = delegate;
     187
     188        var tabStrip = this.appendChild(document.createElement('ul'));
     189
     190        Object.keys(resultsByBuilder).forEach(function(builderName) {
     191            var builderDirectory = results.directoryForBuilder(builderName);
     192
     193            var link = document.createElement('a');
     194            $(link).attr('href', "#" + builderDirectory).text(ui.displayNameForBuilder(builderName));
     195            tabStrip.appendChild(document.createElement('li')).appendChild(link);
     196
     197            var content = this._delegate.contentForTestAndBuilder(testName, builderName);
     198            content.id = builderDirectory;
     199            this.appendChild(content);
     200        }, this);
     201
     202        $(this).tabs();
     203    }
    263204});
    264205
     
    267208    {
    268209        this.className = 'results-view';
    269         this.innerHTML = '<div class="toolbar"></div><div class="content"></div>';
    270 
    271         this._testSelector = new ui.results.TestSelector();
    272         this._builderSelector = new ui.results.BuilderSelector();
    273         this._resultsSelector = new ui.results.ResultsSelector();
    274         this._resultsDetails = new ui.results.ResultsDetails(delegate);
    275         this._actionList = new ui.actions.List();
    276 
    277         $('.toolbar', this).append(this._testSelector).append(this._builderSelector).append(this._resultsSelector).append(this._actionList);
    278         $('.content', this).append(this._resultsDetails);
    279     },
    280     addAction: function(action)
    281     {
    282         this._actionList.add(action);
    283     },
    284     setTestList: function(testNameList)
    285     {
    286         this._testSelector.setTestList(testNameList);
    287     },
    288     setBuilderList: function(buildNameList)
    289     {
    290         this._builderSelector.setBuilderList(buildNameList);
     210        this._delegate = delegate;
     211    },
     212    contentForTest: function(testName)
     213    {
     214        var builderSelector = new ui.results.BuilderSelector(this, testName, this._resultsByTest[testName]);
     215        $(builderSelector).bind('tabsselect', function(event, ui) {
     216            // We will probably have pre-fetched the tab already, but we need to make sure.
     217            ui.panel.show();
     218        });
     219        return builderSelector;
     220    },
     221    contentForTestAndBuilder: function(testName, builderName)
     222    {
     223        var failureInfo = results.failureInfoForTestAndBuilder(this._resultsByTest, testName, builderName);
     224        return new ui.results.ResultsDetails(this, failureInfo);
    291225    },
    292226    setResultsByTest: function(resultsByTest)
    293227    {
    294         this._resultsSelector.setResultsByTest(resultsByTest);
    295     },
    296     currentTestName: function()
    297     {
    298         return this._testSelector.selectedItem();
    299     },
    300     currentBuilderName: function()
    301     {
    302         return this._builderSelector.selectedItem();
    303     },
    304     showResults: function(failureInfo)
    305     {
    306         this._testSelector.select(failureInfo.testName);
    307         this._builderSelector.select(failureInfo.builderName);
    308         this._resultsDetails.show(failureInfo);
     228        $(this).empty();
     229        this._resultsByTest = resultsByTest;
     230
     231        var testSelector = new ui.results.TestSelector(this, resultsByTest);
     232        $(testSelector).bind("accordionchangestart", function(event, ui) {
     233            // Prefetch the first results from the network.
     234            var resultsDetails = $('.results-detail', ui.newContent);
     235            if (resultsDetails.length)
     236                resultsDetails[0].show();
     237            // Prefetch the rest kResultsPrefetchDelayMS later.
     238            setTimeout(function() {
     239                resultsDetails.each(function() {
     240                    this.show();
     241                });
     242            }, kResultsPrefetchDelayMS);
     243        });
     244        this.appendChild(testSelector);
     245    },
     246    fetchResultsURLs: function(failureInfo, callback)
     247    {
     248        this._delegate.fetchResultsURLs(failureInfo, callback)
    309249    }
    310250});
  • trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results_unittests.js

    r94487 r94580  
    4747}
    4848
    49 test("View", 6, function() {
    50     var resultsView = new ui.results.View({
    51         fetchResultsURLs: $.noop
    52     });
    53     var controller = new controllers.ResultsDetails(resultsView, kExampleResultsByTest);
    54     controller.showTest("scrollbars/custom-scrollbar-with-incomplete-style.html");
    55     equal(resultsView.currentTestName(), "scrollbars/custom-scrollbar-with-incomplete-style.html");
    56     equal(resultsView.currentBuilderName(), "Mock Builder");
    57     resultsView.showResults({
    58         "testName": "userscripts/another-test.html",
    59         "builderName": "Mock Builder",
    60     });
    61     equal(resultsView.currentTestName(), "userscripts/another-test.html");
    62     equal(resultsView.currentBuilderName(), "Mock Builder");
    63     resultsView.showResults({
    64         "testName": "scrollbars/custom-scrollbar-with-incomplete-style.html",
    65         "builderName": "Mock Linux",
    66     });
    67     equal(resultsView.currentTestName(), "scrollbars/custom-scrollbar-with-incomplete-style.html");
    68     equal(resultsView.currentBuilderName(), "Mock Linux");
    69 });
    70 
    71 test("ResultsSelector", 1, function() {
    72     var resultsSelector = new ui.results.ResultsSelector();
    73     resultsSelector.setResultsByTest(kExampleResultsByTest);
    74     equal($(resultsSelector).wrap('<div>').parent().html(),
    75         '<table class="results-selector">' +
    76             '<thead>' +
    77                 '<tr><td></td><td>Mock Builder</td><td>Mock Linux</td></tr>' +
    78             '</thead>' +
    79             '<tbody>' +
    80                 '<tr>' +
    81                     '<td class="test-name">userscripts/another-test.html</td>' +
    82                     '<td class="result">TEXT</td>' +
    83                     '<td></td>' +
    84                 '</tr>' +
    85                 '<tr>' +
    86                     '<td class="test-name">scrollbars/custom-scrollbar-with-incomplete-style.html</td>' +
    87                     '<td class="result">CRASH</td>' +
    88                     '<td class="result">CRASH</td>' +
    89                 '</tr>' +
    90             '</tbody>' +
    91         '</table>');
    92 });
    93 
     49// FIXME: Add some unit tests.
    9450
    9551})();
  • trunk/Tools/BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css

    r94200 r94580  
    2424 */
    2525
    26 .results-view table {
     26.results-view>.toolbar {
     27    padding-bottom: 15px;
     28}
     29
     30    .results-view>.toolbar ul.actions {
     31        float: right;
     32        margin: 0;
     33        padding: 0;
     34        list-style: none;
     35        display: inline-block;
     36    }
     37
     38    .results-view>.toolbar ul.actions li {
     39        display: inline-block;
     40    }
     41
     42.results-grid table {
    2743    table-layout: fixed;
    2844    width: 100%;
     
    3046}
    3147
    32 .results-view table td, .results-view table th {
     48.results-grid table td, .results-view table th {
    3349    overflow: hidden;
    3450    vertical-align: top;
    3551}
    3652
    37 .results-view table th {
     53.results-grid table th {
    3854    padding: 3px;
    3955    border-bottom: 1px solid #AAA;
    4056}
    4157
    42 .results-view .toolbar {
    43     padding-bottom: 15px;
    44 }
    45 
    46 .results-view .test-selector {
    47     width: 400px;
    48     margin-right: 6px;
    49 }
    50 
    51 .results-view .actions {
    52     float: right;
    53 }
    54 
    55 .results-view .toolbar ul.actions {
    56     margin: 0;
    57     padding: 0;
    58     list-style: none;
    59     display: inline-block;
    60 }
    61 
    62 .results-view .toolbar ul.actions li {
    63     display: inline-block;
    64 }
    65 
    66 .results-view .text-result {
     58.results-grid .text-result {
    6759    border: none;
    6860    width: 100%;
     
    7062}
    7163
    72 .results-view .image-result {
     64.results-grid .image-result {
    7365    width: 100%;
    7466    height: auto;
  • trunk/Tools/ChangeLog

    r94579 r94580  
     12011-09-06  Adam Barth  <abarth@webkit.org>
     2
     3        Use a hierarchial structure for the garden-o-matic results view
     4        https://bugs.webkit.org/show_bug.cgi?id=67620
     5
     6        Reviewed by Dimitri Glazkov.
     7
     8        This patch re-organizes the results view to use a hierachial structure
     9        for selection.  At the top-level are sections for each test.  Expanding
     10        the test section shows a tab selector for builders.
     11
     12        This structure prepares us for wiring up various actions to this view.
     13
     14        * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/controllers.js:
     15        (.):
     16        * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/results.js:
     17        ():
     18        * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results.js:
     19        (.):
     20        * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/scripts/ui/results_unittests.js:
     21        * BuildSlaveSupport/build.webkit.org-config/public_html/TestFailures/styles/results.css:
     22        (.results-view>.toolbar):
     23        (.results-view>.toolbar ul.actions):
     24        (.results-view>.toolbar ul.actions li):
     25        (.results-grid table):
     26        (.results-grid table td, .results-view table th):
     27        (.results-grid table th):
     28        (.results-grid .text-result):
     29        (.results-grid .image-result):
     30
    1312011-09-06  Adam Barth  <abarth@webkit.org>
    232
Note: See TracChangeset for help on using the changeset viewer.