...

Text file src/edge-infra.dev/third_party/gopherage/cmd/html/ts/browser.ts

Documentation: edge-infra.dev/third_party/gopherage/cmd/html/ts

     1/*
     2Copyright 2018 The Kubernetes Authors.
     3
     4Licensed under the Apache License, Version 2.0 (the "License");
     5you may not use this file except in compliance with the License.
     6You may obtain a copy of the License at
     7
     8    http://www.apache.org/licenses/LICENSE-2.0
     9
    10Unless required by applicable law or agreed to in writing, software
    11distributed under the License is distributed on an "AS IS" BASIS,
    12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13See the License for the specific language governing permissions and
    14limitations under the License.
    15*/
    16
    17import { Coverage, parseCoverage } from "./parser";
    18import { enumerate, map } from "./utils";
    19
    20declare const embeddedProfiles: Array<{ path: string; content: string }>;
    21
    22let coverageFiles: Array<{ name: string; coverage: Coverage }> = [];
    23let gPrefix = "";
    24
    25function filenameForDisplay(path: string): string {
    26  const basename = path.split("/").pop()!;
    27  const withoutSuffix = basename.replace(/\.[^.]+$/, "");
    28  return withoutSuffix;
    29}
    30
    31function loadEmbeddedProfiles(): Array<{ name: string; coverage: Coverage }> {
    32  return embeddedProfiles.map(({ path, content }) => ({
    33    coverage: parseCoverage(content),
    34    name: filenameForDisplay(path),
    35  }));
    36}
    37
    38async function loadProfile(path: string): Promise<Coverage> {
    39  const response = await fetch(path, { credentials: "include" });
    40  const content = await response.text();
    41  return parseCoverage(content);
    42}
    43
    44async function init(): Promise<void> {
    45  if (location.hash.length > 1) {
    46    gPrefix = location.hash.substring(1);
    47  }
    48
    49  coverageFiles = loadEmbeddedProfiles();
    50  google.charts.load("current", { packages: ["table"] });
    51  google.charts.setOnLoadCallback(drawTable);
    52}
    53
    54function updateBreadcrumb(): void {
    55  const parts = gPrefix.split("/");
    56  const parent = document.getElementById("breadcrumbs")!;
    57  parent.innerHTML = "";
    58  let prefixSoFar = "";
    59  for (const part of parts) {
    60    if (!part) {
    61      continue;
    62    }
    63    prefixSoFar += part + "/";
    64    const node = document.createElement("a");
    65    node.href = `#${prefixSoFar}`;
    66    node.innerText = part;
    67    parent.appendChild(node);
    68    parent.appendChild(document.createTextNode("/"));
    69  }
    70}
    71
    72function coveragesForPrefix(
    73  coverages: Coverage[],
    74  prefix: string
    75): Iterable<{ c: Array<{ v: number | string; f?: string }> }> {
    76  const m = mergeMaps(
    77    map(coverages, (c) => c.getCoverageForPrefix(prefix).children)
    78  );
    79  const keys = Array.from(m.keys());
    80  keys.sort();
    81  console.log(m);
    82  return map(keys, (k) => ({
    83    c: [{ v: k } as { v: number | string; f?: string }].concat(
    84      m.get(k)!.map((x, i) => {
    85        if (!x) {
    86          return { v: "" };
    87        }
    88        const next = m.get(k)![i + 1];
    89        const coverage = x.coveredStatements / x.totalStatements;
    90        let arrow = "";
    91        if (next) {
    92          const nextCoverage = next.coveredStatements / next.totalStatements;
    93          if (coverage > nextCoverage) {
    94            arrow = "▲";
    95          } else if (coverage < nextCoverage) {
    96            arrow = "▼";
    97          }
    98        }
    99        const percentage = `${(coverage * 100).toFixed(1)}%`;
   100        return {
   101          f: `<span class="arrow">${arrow}</span> ${percentage}`,
   102          v: coverage,
   103        };
   104      })
   105    ),
   106  }));
   107}
   108
   109function mergeMaps<T, U>(maps: Iterable<Map<T, U>>): Map<T, U[]> {
   110  const result = new Map();
   111  for (const [i, m] of enumerate(maps)) {
   112    for (const [key, value] of m.entries()) {
   113      if (!result.has(key)) {
   114        result.set(key, Array(i).fill(null));
   115      }
   116      result.get(key).push(value);
   117    }
   118    for (const entry of result.values()) {
   119      if (entry.length === i) {
   120        entry.push(null);
   121      }
   122    }
   123  }
   124  return result;
   125}
   126
   127function drawTable(): void {
   128  const rows = Array.from(
   129    coveragesForPrefix(
   130      coverageFiles.map((x) => x.coverage),
   131      gPrefix
   132    )
   133  );
   134  const cols = coverageFiles.map((x, i) => ({
   135    id: `file-${i}`,
   136    label: x.name,
   137    type: "number",
   138  }));
   139  const dataTable = new google.visualization.DataTable({
   140    cols: [{ id: "child", label: "File", type: "string" }].concat(cols),
   141    rows,
   142  });
   143
   144  const colourFormatter = new google.visualization.ColorFormat();
   145  colourFormatter.addGradientRange(0, 1.0001, "#FFFFFF", "#DD0000", "#00DD00");
   146  for (let i = 1; i < cols.length + 1; ++i) {
   147    colourFormatter.format(dataTable, i);
   148  }
   149
   150  const table = new google.visualization.Table(
   151    document.getElementById("table")!
   152  );
   153  table.draw(dataTable, { allowHtml: true });
   154
   155  google.visualization.events.addListener(table, "select", () => {
   156    const child = rows[table.getSelection()[0].row!].c[0].v as string;
   157    if (child.endsWith("/")) {
   158      location.hash = gPrefix + child;
   159    } else {
   160      // TODO: this shouldn't be hardcoded.
   161      // location.href = 'profiles/everything-diff.html#file' +
   162      //     coverage.getFile(prefix + child).fileNumber;
   163    }
   164  });
   165  updateBreadcrumb();
   166}
   167
   168document.addEventListener("DOMContentLoaded", () => init());
   169window.addEventListener("hashchange", () => {
   170  gPrefix = location.hash.substring(1);
   171  drawTable();
   172});

View as plain text