Statistically significant A/B testing results should be color coded in details view
[WebKit.git] / Websites / perf.webkit.org / public / v3 / components / test-group-results-table.js
1
2 class TestGroupResultsTable extends ResultsTable {
3     constructor()
4     {
5         super('test-group-results-table');
6         this._testGroup = null;
7         this._renderedTestGroup = null;
8     }
9
10     didUpdateResults() { this._renderedTestGroup = null; }
11     setTestGroup(testGroup) { this._testGroup = testGroup; }
12
13     heading()
14     {
15         return ComponentBase.createElement('th', {colspan: 2}, 'Configuration');
16     }
17
18     render()
19     {
20         if (this._renderedTestGroup == this._testGroup)
21             return;
22         this._renderedTestGroup = this._testGroup;
23         super.render();
24     }
25
26     buildRowGroups()
27     {
28         var testGroup = this._testGroup;
29         if (!testGroup)
30             return [];
31
32         var rootSets = this._testGroup.requestedRootSets();
33         var groups = rootSets.map(function (rootSet) {
34             var rows = [new ResultsTableRow('Mean', rootSet)];
35             var results = [];
36
37             for (var request of testGroup.requestsForRootSet(rootSet)) {
38                 var result = request.result();
39                 // Call result.rootSet() for each result since the set of revisions used in testing maybe different from requested ones.
40                 var row = new ResultsTableRow(1 + +request.order(), result ? result.rootSet() : null);
41                 rows.push(row);
42                 if (result) {
43                     row.setLink(result.build().url(), result.build().label());
44                     row.setResult(result);
45                     results.push(result);
46                 } else
47                     row.setLink(request.statusUrl(), request.statusLabel());
48             }
49
50             var aggregatedResult = MeasurementAdaptor.aggregateAnalysisResults(results);
51             if (!isNaN(aggregatedResult.value))
52                 rows[0].setResult(aggregatedResult);
53
54             return {heading: testGroup.labelForRootSet(rootSet), rows:rows};
55         });
56
57         var comparisonRows = [];
58         for (var i = 0; i < rootSets.length; i++) {
59             for (var j = i + 1; j < rootSets.length; j++) {
60                 var startConfig = testGroup.labelForRootSet(rootSets[i]);
61                 var endConfig = testGroup.labelForRootSet(rootSets[j]);
62
63                 var result = this._testGroup.compareTestResults(rootSets[i], rootSets[j]);
64                 if (result.changeType == null)
65                     continue;
66
67                 var row = new ResultsTableRow(`${startConfig} to ${endConfig}`, null);
68                 var element = ComponentBase.createElement;
69                 row.setLabelForWholeRow(element('span', {class: 'results-label ' + result.status}, result.fullLabel));
70                 comparisonRows.push(row);
71             }
72         }
73
74         groups.unshift({heading: '', rows: comparisonRows});
75
76         return groups;
77     }
78
79     static cssTemplate()
80     {
81         return super.cssTemplate() + `
82             .results-label {
83                 padding: 0.1rem;
84                 width: 100%;
85                 height: 100%;
86             }
87
88             .results-label .failed {
89                 color: rgb(128, 51, 128);
90             }
91             .results-label .unchanged {
92                 color: rgb(128, 128, 128);
93             }
94             .results-label.worse {
95                 color: rgb(255, 102, 102);
96                 font-weight: bold;
97             }
98             .results-label.better {
99                 color: rgb(102, 102, 255);
100                 font-weight: bold;
101             }
102         `;
103     }
104 }
105
106 ComponentBase.defineElement('test-group-results-table', TestGroupResultsTable);