Add point-links-sk to display links related to specific data points.
- Starting with displaying commit range links for configured keys. We can extend this to include other links as well.
Review suggestions:
- Most of the files in this change are due to a added config.
- The main code is in point-links-sk.ts.
- This is getting used in explore-simple-sk.ts
Bug: b/323510837
Change-Id: I0814190a72bd6b186c9ac57dd5562d1f1be8805a
Reviewed-on: https://skia-review.googlesource.com/c/buildbot/+/885310
Reviewed-by: Eduardo Yap <eduardoyap@google.com>
Commit-Queue: Ashwin Verleker <ashwinpv@google.com>
diff --git a/perf/configs/chrome-perf-non-public.json b/perf/configs/chrome-perf-non-public.json
index 064c160..1df80d3 100644
--- a/perf/configs/chrome-perf-non-public.json
+++ b/perf/configs/chrome-perf-non-public.json
@@ -83,6 +83,9 @@
"cache_expiration_minutes": 300
}
},
+ "data_point_config": {
+ "keys_for_commit_range": ["V8 Git Hash", "WebRTC Git Hash"]
+ },
"temporal_config": {
"host_port": "temporal.temporal:7233",
"namespace": "perf-grouping",
diff --git a/perf/go/config/config.go b/perf/go/config/config.go
index 8f3d0bf..58f8d19 100644
--- a/perf/go/config/config.go
+++ b/perf/go/config/config.go
@@ -818,6 +818,12 @@
TaskQueue string `json:"task_queue,omitempty"`
}
+// DataPointConfig contains config properties to customize how data for individual points is displayed.
+type DataPointConfig struct {
+ // The link keys to use for commit range urls.
+ KeysForCommitRange []string `json:"keys_for_commit_range,omitempty"`
+}
+
// QueryConfig contains query customization info for the instance.
type QueryConfig struct {
// IncludedParams defines the params that should be displayed in the query dialog.
@@ -927,6 +933,7 @@
AnomalyConfig AnomalyConfig `json:"anomaly_config,omitempty"`
QueryConfig QueryConfig `json:"query_config,omitempty"`
TemporalConfig TemporalConfig `json:"temporal_config,omitempty"`
+ DataPointConfig DataPointConfig `json:"data_point_config,omitempty"`
EnableSheriffConfig bool `json:"enable_sheriff_config,omitempty"`
diff --git a/perf/go/config/validate/instanceConfigSchema.json b/perf/go/config/validate/instanceConfigSchema.json
index 4176c77..767e393 100644
--- a/perf/go/config/validate/instanceConfigSchema.json
+++ b/perf/go/config/validate/instanceConfigSchema.json
@@ -73,6 +73,18 @@
"notifications"
]
},
+ "DataPointConfig": {
+ "properties": {
+ "keys_for_commit_range": {
+ "items": {
+ "type": "string"
+ },
+ "type": "array"
+ }
+ },
+ "additionalProperties": false,
+ "type": "object"
+ },
"DataStoreConfig": {
"properties": {
"datastore_type": {
@@ -305,6 +317,9 @@
"temporal_config": {
"$ref": "#/$defs/TemporalConfig"
},
+ "data_point_config": {
+ "$ref": "#/$defs/DataPointConfig"
+ },
"enable_sheriff_config": {
"type": "boolean"
},
diff --git a/perf/go/frontend/frontend.go b/perf/go/frontend/frontend.go
index 251de1a..5578792 100644
--- a/perf/go/frontend/frontend.go
+++ b/perf/go/frontend/frontend.go
@@ -257,6 +257,7 @@
NeedAlertAction bool `json:"need_alert_action"` // Action to take for the alert.
BugHostURL string `json:"bug_host_url"` // The URL for the bug host for the instance.
GitRepoUrl string `json:"git_repo_url"` // The URL for the associated git repo.
+ KeysForCommitRange []string `json:"keys_for_commit_range"` // The link keys for commit range url display of individual points.
}
// getPageContext returns the value of `window.perf` serialized as JSON.
@@ -284,6 +285,7 @@
NeedAlertAction: config.Config.NeedAlertAction,
BugHostURL: config.Config.BugHostUrl,
GitRepoUrl: config.Config.GitRepoConfig.URL,
+ KeysForCommitRange: config.Config.DataPointConfig.KeysForCommitRange,
}
b, err := json.MarshalIndent(pc, "", " ")
if err != nil {
diff --git a/perf/modules/anomaly-sk/anomaly-sk-demo.ts b/perf/modules/anomaly-sk/anomaly-sk-demo.ts
index 1777f2d..40a4272 100644
--- a/perf/modules/anomaly-sk/anomaly-sk-demo.ts
+++ b/perf/modules/anomaly-sk/anomaly-sk-demo.ts
@@ -23,6 +23,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
const dummyAnomaly = (bugId: number): Anomaly => ({
diff --git a/perf/modules/anomaly-sk/anomaly-sk_test.ts b/perf/modules/anomaly-sk/anomaly-sk_test.ts
index ea6581f..075ca30 100644
--- a/perf/modules/anomaly-sk/anomaly-sk_test.ts
+++ b/perf/modules/anomaly-sk/anomaly-sk_test.ts
@@ -192,6 +192,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
});
diff --git a/perf/modules/chart-tooltip-sk/chart-tooltip-sk-demo.ts b/perf/modules/chart-tooltip-sk/chart-tooltip-sk-demo.ts
index 763f28c..87c3bb0 100644
--- a/perf/modules/chart-tooltip-sk/chart-tooltip-sk-demo.ts
+++ b/perf/modules/chart-tooltip-sk/chart-tooltip-sk-demo.ts
@@ -25,6 +25,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
const dummyAnomaly = (bugId: number): Anomaly => ({
diff --git a/perf/modules/cluster-page-sk/cluster-page-sk-demo.ts b/perf/modules/cluster-page-sk/cluster-page-sk-demo.ts
index ad6cf38..3b28822 100644
--- a/perf/modules/cluster-page-sk/cluster-page-sk-demo.ts
+++ b/perf/modules/cluster-page-sk/cluster-page-sk-demo.ts
@@ -129,4 +129,5 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
diff --git a/perf/modules/commit-range-sk/commit-range-sk-demo.ts b/perf/modules/commit-range-sk/commit-range-sk-demo.ts
index 87d49fa..06ec9c3 100644
--- a/perf/modules/commit-range-sk/commit-range-sk-demo.ts
+++ b/perf/modules/commit-range-sk/commit-range-sk-demo.ts
@@ -25,6 +25,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
// The response to a POST of [64809, 64811] to /_/cid/.
diff --git a/perf/modules/commit-range-sk/commit-range-sk_test.ts b/perf/modules/commit-range-sk/commit-range-sk_test.ts
index 231ff38..6459a58 100644
--- a/perf/modules/commit-range-sk/commit-range-sk_test.ts
+++ b/perf/modules/commit-range-sk/commit-range-sk_test.ts
@@ -29,6 +29,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
element = newInstance((el: CommitRangeSk) => {
diff --git a/perf/modules/explore-multi-sk/explore-multi-sk-demo.ts b/perf/modules/explore-multi-sk/explore-multi-sk-demo.ts
index b08fea6..2ad6f28 100644
--- a/perf/modules/explore-multi-sk/explore-multi-sk-demo.ts
+++ b/perf/modules/explore-multi-sk/explore-multi-sk-demo.ts
@@ -23,6 +23,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
customElements.whenDefined('explore-multi-sk').then(() => {
diff --git a/perf/modules/explore-simple-sk/BUILD.bazel b/perf/modules/explore-simple-sk/BUILD.bazel
index 7d98e2a..ed9b2f0 100644
--- a/perf/modules/explore-simple-sk/BUILD.bazel
+++ b/perf/modules/explore-simple-sk/BUILD.bazel
@@ -33,6 +33,7 @@
"//perf/modules/plot-summary-sk",
"//perf/modules/picker-field-sk",
"//perf/modules/chart-tooltip-sk",
+ "//perf/modules/point-links-sk",
],
ts_deps = [
"//infra-sk/modules/ElementSk:index_ts_lib",
diff --git a/perf/modules/explore-simple-sk/explore-simple-sk.ts b/perf/modules/explore-simple-sk/explore-simple-sk.ts
index 7d66699..cf01607 100644
--- a/perf/modules/explore-simple-sk/explore-simple-sk.ts
+++ b/perf/modules/explore-simple-sk/explore-simple-sk.ts
@@ -42,6 +42,7 @@
import '../pivot-table-sk';
import '../plot-simple-sk';
import '../plot-summary-sk';
+import '../point-links-sk';
import '../query-count-sk';
import '../window/window';
@@ -137,6 +138,7 @@
Commit as ChartCommit,
} from '../chart-tooltip-sk/chart-tooltip-sk';
import { $$ } from '../../../infra-sk/modules/dom';
+import { PointLinksSk } from '../point-links-sk/point-links-sk';
/** The type of trace we are adding to a plot. */
type addPlotType = 'query' | 'formula' | 'pivot';
@@ -466,6 +468,8 @@
private ingestFileLinks: IngestFileLinksSk | null = null;
+ private pointLinks: PointLinksSk | null = null;
+
private logEntry: HTMLPreElement | null = null;
private paramset: ParamSetSk | null = null;
@@ -942,6 +946,7 @@
</div>
<div>
<commit-range-sk id="commit-range-link"></commit-range-sk>
+ <point-links-sk id="point-links"></point-links-sk>
<commit-detail-panel-sk id=commits selectable .hide=${
window.perf.hide_list_of_commits_on_explore
}></commit-detail-panel-sk>
@@ -977,6 +982,7 @@
this.formula = this.querySelector('#formula');
this.jsonsource = this.querySelector('#jsonsource');
this.ingestFileLinks = this.querySelector('#ingest-file-links');
+ this.pointLinks = this.querySelector<PointLinksSk>('#point-links');
this.logEntry = this.querySelector('#logEntry');
this.paramset = this.querySelector('#paramset');
this.percent = this.querySelector('#percent');
@@ -1753,6 +1759,13 @@
this.jsonsource!.cid = cid;
this.jsonsource!.traceid = traceid;
this.ingestFileLinks!.load(cid, traceid);
+ // Populate the point links element.
+ this.pointLinks!.load(
+ commit,
+ prevCommit,
+ e.detail.name,
+ window.perf.keys_for_commit_range!
+ );
}
// when the commit details are loaded, add those info to
diff --git a/perf/modules/explore-simple-sk/explore-simple-sk_test.ts b/perf/modules/explore-simple-sk/explore-simple-sk_test.ts
index c5b0be6..b17fc7f 100644
--- a/perf/modules/explore-simple-sk/explore-simple-sk_test.ts
+++ b/perf/modules/explore-simple-sk/explore-simple-sk_test.ts
@@ -136,6 +136,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
// Create a common element-sk to be used by all the tests.
diff --git a/perf/modules/explore-sk/explore-sk-demo.ts b/perf/modules/explore-sk/explore-sk-demo.ts
index 6701eea..b73e141 100644
--- a/perf/modules/explore-sk/explore-sk-demo.ts
+++ b/perf/modules/explore-sk/explore-sk-demo.ts
@@ -30,6 +30,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
customElements.whenDefined('explore-sk').then(() => {
diff --git a/perf/modules/json/index.ts b/perf/modules/json/index.ts
index f040250..506488c 100644
--- a/perf/modules/json/index.ts
+++ b/perf/modules/json/index.ts
@@ -307,6 +307,7 @@
need_alert_action: boolean;
bug_host_url: string;
git_repo_url: string;
+ keys_for_commit_range: string[] | null;
}
export interface TriageRequest {
diff --git a/perf/modules/perf-scaffold-sk/perf-scaffold-sk-demo.ts b/perf/modules/perf-scaffold-sk/perf-scaffold-sk-demo.ts
index 70a6ebe..ee9f2ce 100644
--- a/perf/modules/perf-scaffold-sk/perf-scaffold-sk-demo.ts
+++ b/perf/modules/perf-scaffold-sk/perf-scaffold-sk-demo.ts
@@ -20,6 +20,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
document.querySelector('.component-goes-here')!.innerHTML = `
diff --git a/perf/modules/point-links-sk/BUILD.bazel b/perf/modules/point-links-sk/BUILD.bazel
new file mode 100644
index 0000000..75a32ea
--- /dev/null
+++ b/perf/modules/point-links-sk/BUILD.bazel
@@ -0,0 +1,60 @@
+load("//infra-sk:index.bzl", "karma_test", "sk_demo_page_server", "sk_element", "sk_element_puppeteer_test", "sk_page")
+
+sk_demo_page_server(
+ name = "demo_page_server",
+ sk_page = ":point-links-sk-demo",
+)
+
+sk_element(
+ name = "point-links-sk",
+ sass_srcs = ["point-links-sk.scss"],
+ ts_deps = [
+ "//:node_modules/lit-html",
+ "//infra-sk/modules/ElementSk:index_ts_lib",
+ "//elements-sk/modules:define_ts_lib",
+ "//infra-sk/modules:jsonorthrow_ts_lib",
+ "//perf/modules/errorMessage:index_ts_lib",
+ "//perf/modules/json:index_ts_lib",
+ ],
+ ts_srcs = [
+ "point-links-sk.ts",
+ "index.ts",
+ ],
+ visibility = ["//visibility:public"],
+)
+
+sk_page(
+ name = "point-links-sk-demo",
+ html_file = "point-links-sk-demo.html",
+ scss_entry_point = "point-links-sk-demo.scss",
+ sk_element_deps = [":point-links-sk"],
+ ts_deps = [
+ "//:node_modules/fetch-mock",
+ "//perf/modules/json:index_ts_lib",
+ ],
+ ts_entry_point = "point-links-sk-demo.ts",
+)
+
+sk_element_puppeteer_test(
+ name = "point-links-sk_puppeteer_test",
+ src = "point-links-sk_puppeteer_test.ts",
+ sk_demo_page_server = ":demo_page_server",
+ deps = [
+ "//:node_modules/@types/chai",
+ "//:node_modules/chai",
+ "//puppeteer-tests:util_ts_lib",
+ ],
+)
+
+karma_test(
+ name = "point-links-sk_test",
+ src = "point-links-sk_test.ts",
+ deps = [
+ ":point-links-sk",
+ "//:node_modules/@types/chai",
+ "//:node_modules/chai",
+ "//:node_modules/fetch-mock",
+ "//infra-sk/modules:test_util_ts_lib",
+ "//perf/modules/json:index_ts_lib",
+ ],
+)
diff --git a/perf/modules/point-links-sk/index.ts b/perf/modules/point-links-sk/index.ts
new file mode 100644
index 0000000..d4fbe17
--- /dev/null
+++ b/perf/modules/point-links-sk/index.ts
@@ -0,0 +1 @@
+import './point-links-sk';
diff --git a/perf/modules/point-links-sk/point-links-sk-demo.html b/perf/modules/point-links-sk/point-links-sk-demo.html
new file mode 100644
index 0000000..83d9e32
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk-demo.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>point-links-sk</title>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body class="body-sk">
+ <h1>point-links-sk</h1>
+ <point-links-sk></point-links-sk>
+
+ <h2>Events</h2>
+ <pre id=events></pre>
+</body>
+</html>
diff --git a/perf/modules/point-links-sk/point-links-sk-demo.scss b/perf/modules/point-links-sk/point-links-sk-demo.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk-demo.scss
diff --git a/perf/modules/point-links-sk/point-links-sk-demo.ts b/perf/modules/point-links-sk/point-links-sk-demo.ts
new file mode 100644
index 0000000..270d547
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk-demo.ts
@@ -0,0 +1,35 @@
+import fetchMock from 'fetch-mock';
+import { CommitNumber } from '../json';
+import './index';
+import { PointLinksSk } from './point-links-sk';
+
+fetchMock.post('/_/details/?results=false', (url, request) => {
+ const requestObj = JSON.parse(request.body!.toString());
+ switch (requestObj.cid) {
+ case 12:
+ return {
+ version: 1,
+ links: {
+ 'V8 Git Hash':
+ 'https://chromium.googlesource.com/v8/v8/+/47f420e89ec1b33dacc048d93e0317ab7fec43dd',
+ },
+ };
+ case 11:
+ return {
+ version: 1,
+ links: {
+ 'V8 Git Hash':
+ 'https://chromium.googlesource.com/v8/v8/+/f052b8c4db1f08d1f8275351c047854e6ff1805f',
+ },
+ };
+ default:
+ return {};
+ }
+});
+
+window.customElements.whenDefined('point-links-sk').then(() => {
+ const sources = document.querySelectorAll<PointLinksSk>('point-links-sk')!;
+ sources.forEach((source) => {
+ source.load(CommitNumber(12), CommitNumber(11), 'foo', ['V8 Git Hash']);
+ });
+});
diff --git a/perf/modules/point-links-sk/point-links-sk.scss b/perf/modules/point-links-sk/point-links-sk.scss
new file mode 100644
index 0000000..6656b66
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk.scss
@@ -0,0 +1,2 @@
+point-links-sk {
+}
diff --git a/perf/modules/point-links-sk/point-links-sk.ts b/perf/modules/point-links-sk/point-links-sk.ts
new file mode 100644
index 0000000..9ace535
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk.ts
@@ -0,0 +1,171 @@
+/**
+ * @module modules/point-links-sk
+ * @description <h2><code>point-links-sk</code></h2>
+ * This module provides the ability to display links which are specific to data points.
+ * The original data source for the links come from the ingestion file and the caller
+ * provides a list of keys to extract from the links and format those as anchor elements
+ * to be displayed.
+ *
+ * This module also generates commit range links for incoming links that are commits. This
+ * is done by getting the links for the current commit (the point that is selected) and the
+ * previous commit, and then generating a git log url to show the list of commits between
+ * both of these.
+ *
+ * @example
+ *
+ * Link in ingestion file (commit n): {'V8 Git Hash': 'https://chromium.googlesource.com/v8/v8/+/47f420e89ec1b33dacc048d93e0317ab7fec43dd'}
+ * Link in ingestion file (commit n-1): {'V8 Git Hash': 'https://chromium.googlesource.com/v8/v8/+/f052b8c4db1f08d1f8275351c047854e6ff1805f'}
+ *
+ * Since both the commit links are different, this module will generate a new link like below.
+ *
+ * <a href='https://chromium.googlesource.com/v8/v8/+log/f052b8c4..47f420e>V8 Git Hash Range</a>
+ */
+import { TemplateResult, html } from 'lit-html';
+import { define } from '../../../elements-sk/modules/define';
+import { ElementSk } from '../../../infra-sk/modules/ElementSk';
+import { CommitDetailsRequest, CommitNumber, ingest } from '../json';
+import { jsonOrThrow } from '../../../infra-sk/modules/jsonOrThrow';
+import { errorMessage } from '../errorMessage';
+
+export class PointLinksSk extends ElementSk {
+ constructor() {
+ super(PointLinksSk.template);
+ }
+
+ // Contains the urls to be displayed.
+ displayUrls: { [key: string]: string } = {};
+
+ // Contains the texts for the urls to be displayed.
+ displayTexts: { [key: string]: string } = {};
+
+ private static template = (ele: PointLinksSk) =>
+ html` <div ?hidden=${Object.keys(ele.displayUrls || {}).length === 0}>
+ <ul>
+ ${ele.renderLinks()}
+ </ul>
+ </div>`;
+
+ connectedCallback(): void {
+ super.connectedCallback();
+ this._render();
+ }
+
+ renderLinks(): TemplateResult[] {
+ const keys = Object.keys(this.displayUrls);
+ const getHtml = (key: string): TemplateResult => {
+ const link = this.displayUrls![key];
+ const linkText = this.displayTexts[key];
+ return html`<li>${key}: <a href="${link}"> ${linkText}</a></li>`;
+ };
+ return keys.map(getHtml);
+ }
+
+ // load and display the links for the given commit and trace.
+ public async load(
+ cid: CommitNumber,
+ prev_cid: CommitNumber,
+ traceid: string,
+ keysForCommitRange: string[]
+ ): Promise<void> {
+ // Clear any existing links first.
+ this.displayUrls = {};
+ this.displayTexts = {};
+ const currentLinks = await this.getLinksForPoint(cid, traceid);
+ const prevLinks = await this.getLinksForPoint(prev_cid, traceid);
+ keysForCommitRange.forEach((key) => {
+ const currentCommitUrl = currentLinks[key];
+ if (
+ currentCommitUrl !== undefined &&
+ currentCommitUrl !== null &&
+ currentCommitUrl !== ''
+ ) {
+ const prevCommitUrl = prevLinks[key];
+ const currentCommitId = this.getCommitIdFromCommitUrl(
+ currentCommitUrl
+ ).substring(0, 7);
+ const prevCommitId = this.getCommitIdFromCommitUrl(
+ prevCommitUrl
+ ).substring(0, 7);
+ if (currentCommitId === prevCommitId) {
+ this.displayUrls[key] = currentCommitUrl;
+ this.displayTexts[key] = currentCommitId;
+ } else {
+ const repoUrl = this.getRepoUrlFromCommitUrl(currentCommitUrl);
+ const commitRangeUrl = `${repoUrl}+log/${prevCommitId}..${currentCommitId}`;
+ const displayKey = `${key} Range`;
+ this.displayUrls[displayKey] = commitRangeUrl;
+ this.displayTexts[displayKey] = this.getFormattedCommitRangeText(
+ prevCommitId,
+ currentCommitId
+ );
+ }
+ }
+ });
+ this._render();
+ }
+
+ /**
+ * Get the commit range text.
+ * @param start Start Commit.
+ * @param end End Commit.
+ * @returns Formatted text.
+ */
+ private getFormattedCommitRangeText(start: string, end: string): string {
+ return `${start} - ${end}`;
+ }
+
+ /**
+ * Get the repository name from the given commit url.
+ * @param commitUrl Full commit url.
+ * @returns Repository name.
+ */
+ private getRepoUrlFromCommitUrl(commitUrl: string): string {
+ const idx = commitUrl.indexOf('+');
+ return commitUrl.substring(0, idx);
+ }
+
+ /**
+ * Get the commit id from the given commit url.
+ * @param commitUrl Full commit url.
+ * @returns Commit id.
+ */
+ private getCommitIdFromCommitUrl(commitUrl: string): string {
+ const idx = commitUrl.lastIndexOf('/');
+ return commitUrl.substring(idx + 1);
+ }
+
+ /**
+ * Get the links for the given commit.
+ * @param cid Commit id.
+ * @param traceId Trace id.
+ * @returns Links relevant to the commit id and trace id.
+ */
+ private async getLinksForPoint(
+ cid: CommitNumber,
+ traceId: string
+ ): Promise<{ [key: string]: string }> {
+ const body: CommitDetailsRequest = {
+ cid: cid,
+ traceid: traceId,
+ };
+ const url = '/_/details/?results=false';
+ try {
+ const resp = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(body),
+ });
+ const json = await jsonOrThrow(resp);
+ const format = json as ingest.Format;
+ return format.links!;
+ } catch (error) {
+ await errorMessage(error as string);
+ }
+
+ return {};
+ }
+}
+
+define('point-links-sk', PointLinksSk);
diff --git a/perf/modules/point-links-sk/point-links-sk_puppeteer_test.ts b/perf/modules/point-links-sk/point-links-sk_puppeteer_test.ts
new file mode 100644
index 0000000..ae7ed9d
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk_puppeteer_test.ts
@@ -0,0 +1,28 @@
+import { expect } from 'chai';
+import {
+ loadCachedTestBed,
+ takeScreenshot,
+ TestBed,
+} from '../../../puppeteer-tests/util';
+
+describe('point-links-sk', () => {
+ let testBed: TestBed;
+ before(async () => {
+ testBed = await loadCachedTestBed();
+ });
+
+ beforeEach(async () => {
+ await testBed.page.goto(testBed.baseUrl);
+ await testBed.page.setViewport({ width: 400, height: 550 });
+ });
+
+ it('should render the demo page (smoke test)', async () => {
+ expect(await testBed.page.$$('point-links-sk')).to.have.length(1);
+ });
+
+ describe('screenshots', () => {
+ it('shows the default view', async () => {
+ await takeScreenshot(testBed.page, 'perf', 'point-links-sk');
+ });
+ });
+});
diff --git a/perf/modules/point-links-sk/point-links-sk_test.ts b/perf/modules/point-links-sk/point-links-sk_test.ts
new file mode 100644
index 0000000..d8d6a43
--- /dev/null
+++ b/perf/modules/point-links-sk/point-links-sk_test.ts
@@ -0,0 +1,142 @@
+import './index';
+import { assert } from 'chai';
+import fetchMock from 'fetch-mock';
+import { PointLinksSk } from './point-links-sk';
+
+import { setUpElementUnderTest } from '../../../infra-sk/modules/test_util';
+import { CommitNumber } from '../json';
+
+describe('point-links-sk', () => {
+ const newInstance = setUpElementUnderTest<PointLinksSk>('point-links-sk');
+
+ let element: PointLinksSk;
+ beforeEach(() => {});
+
+ describe('Load links for a commit.', () => {
+ beforeEach(() => {
+ element = newInstance();
+ fetchMock.reset();
+ });
+
+ it('With no eligible links.', () => {
+ const currentCommitId = CommitNumber(4);
+ const prevCommitId = CommitNumber(3);
+ const keysForCommitRange: string[] = [];
+ element.load(
+ currentCommitId,
+ prevCommitId,
+ 'my trace',
+ keysForCommitRange
+ );
+ assert.isEmpty(element.displayUrls, 'No display urls expected.');
+ assert.isEmpty(element.displayTexts, 'No display texts expected.');
+ });
+
+ it('With all eligible links but no range.', async () => {
+ const keysForCommitRange = ['key1', 'key2'];
+ const expectedLinks = {
+ key1: 'https://commit/link1',
+ key2: 'https://commit/link2',
+ };
+ fetchMock.post('/_/details/?results=false', {
+ version: 1,
+ links: expectedLinks,
+ });
+
+ const currentCommitId = CommitNumber(4);
+ const prevCommitId = CommitNumber(3);
+
+ await element.load(
+ currentCommitId,
+ prevCommitId,
+ 'my trace',
+ keysForCommitRange
+ );
+ assert.deepEqual(expectedLinks, element.displayUrls);
+ });
+
+ it('With all eligible links and only ranges.', async () => {
+ const keysForCommitRange = ['key1', 'key2'];
+ const currentCommitId = CommitNumber(4);
+ const prevCommitId = CommitNumber(3);
+
+ fetchMock.post('/_/details/?results=false', (url, request) => {
+ const requestObj = JSON.parse(request.body!.toString());
+ switch (requestObj.cid) {
+ case currentCommitId:
+ return {
+ version: 1,
+ links: {
+ key1: 'https://repoHost/repo1/+/curLink',
+ key2: 'https://repoHost/repo2/+/curLink',
+ },
+ };
+ case prevCommitId:
+ return {
+ version: 1,
+ links: {
+ key1: 'https://repoHost/repo1/+/preLink',
+ key2: 'https://repoHost/repo2/+/preLink',
+ },
+ };
+ default:
+ return {};
+ }
+ });
+
+ await element.load(
+ currentCommitId,
+ prevCommitId,
+ 'my trace',
+ keysForCommitRange
+ );
+ const expectedLinks = {
+ 'key1 Range': 'https://repoHost/repo1/+log/preLink..curLink',
+ 'key2 Range': 'https://repoHost/repo2/+log/preLink..curLink',
+ };
+ assert.deepEqual(expectedLinks, element.displayUrls);
+ });
+
+ it('With all eligible links and mixed links and ranges.', async () => {
+ const keysForCommitRange = ['key1', 'key2'];
+ const currentCommitId = CommitNumber(4);
+ const prevCommitId = CommitNumber(3);
+
+ fetchMock.post('/_/details/?results=false', (url, request) => {
+ const requestObj = JSON.parse(request.body!.toString());
+ switch (requestObj.cid) {
+ case currentCommitId:
+ return {
+ version: 1,
+ links: {
+ key1: 'https://repoHost/repo1/+/curLink',
+ key2: 'https://repoHost/repo2/+/curLink',
+ },
+ };
+ case prevCommitId:
+ return {
+ version: 1,
+ links: {
+ key1: 'https://repoHost/repo1/+/curLink',
+ key2: 'https://repoHost/repo2/+/preLink',
+ },
+ };
+ default:
+ return {};
+ }
+ });
+
+ await element.load(
+ currentCommitId,
+ prevCommitId,
+ 'my trace',
+ keysForCommitRange
+ );
+ const expectedLinks = {
+ key1: 'https://repoHost/repo1/+/curLink',
+ 'key2 Range': 'https://repoHost/repo2/+log/preLink..curLink',
+ };
+ assert.deepEqual(expectedLinks, element.displayUrls);
+ });
+ });
+});
diff --git a/perf/modules/trybot-page-sk/trybot-page-sk-demo.ts b/perf/modules/trybot-page-sk/trybot-page-sk-demo.ts
index b62dad6..f9587df 100644
--- a/perf/modules/trybot-page-sk/trybot-page-sk-demo.ts
+++ b/perf/modules/trybot-page-sk/trybot-page-sk-demo.ts
@@ -26,6 +26,7 @@
need_alert_action: false,
bug_host_url: '',
git_repo_url: '',
+ keys_for_commit_range: [],
};
Date.now = () => Date.parse('2020-03-22T00:00:00.000Z');