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);