Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.js b/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.js
new file mode 100644
index 0000000..690bd6a
--- /dev/null
+++ b/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.js
@@ -0,0 +1,87 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {LitElement, html, css} from 'lit-element';
+
+/**
+ * `<mr-crbug-link>`
+ *
+ * Displays a crbug short-link to an issue.
+ *
+ */
+export class MrCrbugLink extends LitElement {
+ /** @override */
+ static get styles() {
+ return css`
+ :host {
+ /**
+ * CSS variables provided to allow conditionally hiding <mr-crbug-link>
+ * in a way that's screenreader friendly.
+ */
+ --mr-crbug-link-opacity: 1;
+ --mr-crbug-link-opacity-focused: 1;
+ }
+ a.material-icons {
+ font-size: var(--chops-icon-font-size);
+ display: inline-block;
+ color: var(--chops-primary-icon-color);
+ padding: 0 2px;
+ box-sizing: border-box;
+ text-decoration: none;
+ vertical-align: middle;
+ }
+ a {
+ opacity: var(--mr-crbug-link-opacity);
+ }
+ a:focus {
+ opacity: var(--mr-crbug-link-opacity-focused);
+ }
+ `;
+ }
+
+ /** @override */
+ render() {
+ return html`
+ <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
+ <a
+ id="bugLink"
+ class="material-icons"
+ href=${this._issueUrl}
+ title="crbug link"
+ >link</a>
+ `;
+ }
+
+ /** @override */
+ static get properties() {
+ return {
+ /**
+ * The issue being viewed. Falls back gracefully if this is only a ref.
+ */
+ issue: {type: Object},
+ };
+ }
+
+ /**
+ * Computes the URL to render in the shortlink.
+ * @return {string}
+ */
+ get _issueUrl() {
+ const issue = this.issue;
+ if (!issue) return '';
+ if (this._getHost() === 'bugs.chromium.org') {
+ const projectPart = (
+ issue.projectName == 'chromium' ? '' : issue.projectName + '/');
+ return `https://crbug.com/${projectPart}${issue.localId}`;
+ }
+ const issueType = issue.approvalValues ? 'approval' : 'detail';
+ return `/p/${issue.projectName}/issues/${issueType}?id=${issue.localId}`;
+ }
+
+ _getHost() {
+ // This function allows us to mock the host in unit testing.
+ return document.location.host;
+ }
+}
+customElements.define('mr-crbug-link', MrCrbugLink);
diff --git a/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.test.js b/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.test.js
new file mode 100644
index 0000000..aa7f21f
--- /dev/null
+++ b/static_src/elements/framework/links/mr-crbug-link/mr-crbug-link.test.js
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chai';
+import {MrCrbugLink} from './mr-crbug-link.js';
+
+
+let element;
+
+describe('mr-crbug-link', () => {
+ beforeEach(() => {
+ element = document.createElement('mr-crbug-link');
+ document.body.appendChild(element);
+ });
+
+ afterEach(() => {
+ document.body.removeChild(element);
+ });
+
+ it('initializes', () => {
+ assert.instanceOf(element, MrCrbugLink);
+ });
+
+ it('In prod, link to crbug.com with project name specified', async () => {
+ element._getHost = () => 'bugs.chromium.org';
+ element.issue = {
+ projectName: 'test',
+ localId: 11,
+ };
+
+ await element.updateComplete;
+
+ const link = element.shadowRoot.querySelector('#bugLink');
+ assert.equal(link.href, 'https://crbug.com/test/11');
+ });
+
+ it('In prod, link to crbug.com with implicit project name', async () => {
+ element._getHost = () => 'bugs.chromium.org';
+ element.issue = {
+ projectName: 'chromium',
+ localId: 11,
+ };
+
+ await element.updateComplete;
+
+ const link = element.shadowRoot.querySelector('#bugLink');
+ assert.equal(link.href, 'https://crbug.com/11');
+ });
+
+ it('does not redirects to approval page for regular issues', async () => {
+ element.issue = {
+ projectName: 'test',
+ localId: 11,
+ };
+
+ await element.updateComplete;
+
+ const link = element.shadowRoot.querySelector('#bugLink');
+ assert.include(link.href.trim(), '/p/test/issues/detail?id=11');
+ });
+});