github.com/web-platform-tests/wpt.fyi@v0.0.0-20240530210107-70cf978996f1/webapp/components/wpt-bsf.js (about) 1 /** 2 * Copyright 2020 The WPT Dashboard Project. All rights reserved. 3 * Use of this source code is governed by a BSD-style license that can be 4 * found in the LICENSE file. 5 */ 6 7 import '../node_modules/@google-web-components/google-chart/google-chart.js'; 8 import '../node_modules/@polymer/polymer/lib/elements/dom-if.js'; 9 import '../node_modules/@polymer/polymer/lib/elements/dom-repeat.js'; 10 import { 11 html, 12 PolymerElement 13 } from '../node_modules/@polymer/polymer/polymer-element.js'; 14 import { LoadingState } from './loading-state.js'; 15 16 class WPTBSF extends LoadingState(PolymerElement) { 17 static get template() { 18 return html` 19 <style> 20 .bsf { 21 display: inline-flex; 22 } 23 .left { 24 width: 20%; 25 margin-top: 10px; 26 margin-left: 10px; 27 font-size: 13px; 28 } 29 .chart { 30 height: 350px; 31 width: 800px; 32 } 33 .sha { 34 display: inline-flex; 35 height: 25px; 36 margin-top: 0px; 37 } 38 h5 { 39 margin-top: 20px; 40 margin-left: 8px; 41 } 42 .channel { 43 display: inline-flex; 44 height: 35px; 45 margin-top: 0px; 46 } 47 .link { 48 text-decoration: none; 49 font-size: 12px; 50 } 51 .unselected { 52 background-color: white; 53 } 54 .selected{ 55 background-color: var(--paper-blue-100); 56 } 57 paper-button { 58 color: black; 59 text-transform: none; 60 } 61 </style> 62 <div class="bsf"> 63 <div class="left"> 64 <h5>Browser-specific failures are the number of WPT tests which fail in exactly one browser. This graph shows the BSF scores for Chrome, Firefox and Safari.</h5> 65 <h5>Channel</h5> 66 <div class="channel"> 67 <paper-button class\$="[[experimentalButtonClass(isExperimental)]]" onclick="[[clickExperimental]]">Experimental</paper-button> 68 <paper-button class\$="[[stableButtonClass(isExperimental)]]" onclick="[[clickStable]]">Stable</paper-button> 69 </div> 70 <h5>Last updated WPT revision</h5> 71 <div class="sha"> 72 <a class="link" href="[[githubHref]]" target="_blank"><paper-button>[[shortSHA]]</paper-button></a> 73 </div> 74 <h5>Click + drag on graph to zoom, right click to un-zoom</h5> 75 </div> 76 <google-chart type="line" 77 class="chart" 78 data="[[data]]" 79 options="[[chartOptions]]" 80 onmouseenter="[[enterChart]]" 81 onmouseleave="[[exitChart]]"></google-chart> 82 </div> 83 `; 84 } 85 86 static get is() { 87 return 'wpt-bsf'; 88 } 89 90 static get properties() { 91 return { 92 data: Array, 93 sha: String, 94 isInteracting: { 95 type: Boolean, 96 }, 97 shortSHA: { 98 type: String, 99 computed: 'computeShortSHA(sha)', 100 }, 101 githubHref: { 102 type: String, 103 computed: 'computeGitHubHref(sha)', 104 }, 105 isExperimental: { 106 type: Boolean, 107 value: true, 108 }, 109 chartOptions: { 110 type: Object, 111 value: { 112 width: 800, 113 height: 350, 114 chartArea: { 115 height: '80%', 116 }, 117 hAxis: { 118 title: 'Date', 119 format: 'MMM-YYYY', 120 }, 121 vAxis: { 122 title: 'Tests that fail in exactly 1 browser', 123 }, 124 explorer: { 125 actions: ['dragToZoom', 'rightClickToReset'], 126 axis: 'horizontal', 127 keepInBounds: true, 128 maxZoomIn: 4.0, 129 }, 130 colors: ['#fbc013', '#fc7a3a', '#148cda'], 131 } 132 }, 133 }; 134 } 135 136 constructor() { 137 super(); 138 this.clickStable = () => { 139 if (!this.isExperimental) { 140 return; 141 } 142 this.isExperimental = false; 143 this.loadBSFData(); 144 }; 145 this.clickExperimental = () => { 146 if (this.isExperimental) { 147 return; 148 } 149 this.isExperimental = true; 150 this.loadBSFData(); 151 }; 152 this.enterChart = () => { 153 this.isInteracting = true; 154 const event = new CustomEvent('interactingchanged', { 155 detail: { value: this.isInteracting } 156 }); 157 this.dispatchEvent(event); 158 }; 159 this.exitChart = () => { 160 this.isInteracting = false; 161 const event = new CustomEvent('interactingchanged', { 162 detail: { value: this.isInteracting } 163 }); 164 this.dispatchEvent(event); 165 }; 166 this.loadBSFData(); 167 } 168 169 computeGitHubHref(sha) { 170 return 'https://github.com/web-platform-tests/wpt/commit/' + sha; 171 } 172 173 computeShortSHA(sha) { 174 return sha.slice(0, 10); 175 } 176 177 stableButtonClass(isExperimental) { 178 return isExperimental ? 'unselected' : 'selected'; 179 } 180 181 experimentalButtonClass(isExperimental) { 182 return isExperimental ? 'selected' : 'unselected'; 183 } 184 185 loadBSFData() { 186 const url = new URL('/api/bsf', window.location); 187 if (this.isExperimental) { 188 url.searchParams.set('experimental', true); 189 } 190 191 this.load( 192 window.fetch(url).then( 193 async r => { 194 if (!r.ok || r.status !== 200) { 195 throw new Error(`status ${r.status}`); 196 } 197 return r.json(); 198 }) 199 .then(bsf => { 200 this.sha = bsf.lastUpdateRevision; 201 // Insert fields into the 0th row of the data table. 202 bsf.data.splice(0, 0, bsf.fields); 203 // BSF data's columns have the format of an array of 204 // sha, date, [product-version, product-score]+ 205 // google-chart.js only needs the date and product 206 // scores to produce the graph, so drop the other columns. 207 this.data = bsf.data.map((row, rowIdx) => { 208 // Drop the sha. 209 row = row.slice(1); 210 211 // Drop the version columns. 212 row = row.filter((c, i) => (i % 2) === 0); 213 214 if (rowIdx === 0) { 215 return row; 216 } 217 218 const dateParts = row[0].split('-').map(x => parseInt(x)); 219 // Javascript Date objects take 0-indexed months, whilst the CSV is 1-indexed. 220 row[0] = new Date(dateParts[0], dateParts[1] - 1, dateParts[2]); 221 for (let i = 1; i < row.length; i++) { 222 row[i] = parseFloat(row[i]); 223 } 224 return row; 225 }); 226 }).catch(e => { 227 // eslint-disable-next-line no-console 228 console.log(`Failed to load BSF data: ${e}`); 229 }) 230 ); 231 } 232 } 233 window.customElements.define(WPTBSF.is, WPTBSF);