Project import generated by Copybara.
GitOrigin-RevId: d9e9e3fb4e31372ec1fb43b178994ca78fa8fe70
diff --git a/static_src/elements/framework/mr-comment-content/mr-attachment.test.js b/static_src/elements/framework/mr-comment-content/mr-attachment.test.js
new file mode 100644
index 0000000..ec79c66
--- /dev/null
+++ b/static_src/elements/framework/mr-comment-content/mr-attachment.test.js
@@ -0,0 +1,228 @@
+// 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, expect} from 'chai';
+import {MrAttachment} from './mr-attachment.js';
+import {prpcClient} from 'prpc-client-instance.js';
+import {FILE_DOWNLOAD_WARNING} from 'shared/settings.js';
+
+let element;
+
+describe('mr-attachment', () => {
+ beforeEach(() => {
+ element = document.createElement('mr-attachment');
+ document.body.appendChild(element);
+ sinon.stub(prpcClient, 'call').returns(Promise.resolve({}));
+ });
+
+ afterEach(() => {
+ document.body.removeChild(element);
+ prpcClient.call.restore();
+ });
+
+ it('initializes', () => {
+ assert.instanceOf(element, MrAttachment);
+ });
+
+ it('shows image thumbnail', async () => {
+ element.attachment = {
+ thumbnailUrl: 'thumbnail.jpeg',
+ contentType: 'image/jpeg',
+ };
+ await element.updateComplete;
+ const img = element.shadowRoot.querySelector('img');
+ assert.isNotNull(img);
+ assert.isTrue(img.src.endsWith('thumbnail.jpeg'));
+ });
+
+ it('shows video thumbnail', async () => {
+ element.attachment = {
+ viewUrl: 'video.mp4',
+ contentType: 'video/mpeg',
+ };
+ await element.updateComplete;
+ const video = element.shadowRoot.querySelector('video');
+ assert.isNotNull(video);
+ assert.isTrue(video.src.endsWith('video.mp4'));
+ });
+
+ it('does not show image thumbnail if deleted', async () => {
+ element.attachment = {
+ thumbnailUrl: 'thumbnail.jpeg',
+ contentType: 'image/jpeg',
+ isDeleted: true,
+ };
+ await element.updateComplete;
+ const img = element.shadowRoot.querySelector('img');
+ assert.isNull(img);
+ });
+
+ it('does not show video thumbnail if deleted', async () => {
+ element.attachment = {
+ viewUrl: 'video.mp4',
+ contentType: 'video/mpeg',
+ isDeleted: true,
+ };
+ await element.updateComplete;
+ const video = element.shadowRoot.querySelector('video');
+ assert.isNull(video);
+ });
+
+ it('deletes attachment', async () => {
+ prpcClient.call.callsFake(() => Promise.resolve({}));
+
+ element.attachment = {
+ attachmentId: 67890,
+ isDeleted: false,
+ };
+ element.canDelete = true;
+ element.projectName = 'proj';
+ element.localId = 1234;
+ element.sequenceNum = 3;
+ await element.updateComplete;
+
+ const deleteButton = element.shadowRoot.querySelector('chops-button');
+ deleteButton.click();
+
+ assert.deepEqual(prpcClient.call.getCall(0).args, [
+ 'monorail.Issues', 'DeleteAttachment',
+ {
+ issueRef: {
+ projectName: 'proj',
+ localId: 1234,
+ },
+ sequenceNum: 3,
+ attachmentId: 67890,
+ delete: true,
+ },
+ ]);
+ assert.isTrue(prpcClient.call.calledOnce);
+ });
+
+ it('undeletes attachment', async () => {
+ prpcClient.call.callsFake(() => Promise.resolve({}));
+ element.attachment = {
+ attachmentId: 67890,
+ isDeleted: true,
+ };
+ element.canDelete = true;
+ element.projectName = 'proj';
+ element.localId = 1234;
+ element.sequenceNum = 3;
+ await element.updateComplete;
+
+ const deleteButton = element.shadowRoot.querySelector('chops-button');
+ deleteButton.click();
+
+ assert.deepEqual(prpcClient.call.getCall(0).args, [
+ 'monorail.Issues', 'DeleteAttachment',
+ {
+ issueRef: {
+ projectName: 'proj',
+ localId: 1234,
+ },
+ sequenceNum: 3,
+ attachmentId: 67890,
+ delete: false,
+ },
+ ]);
+ assert.isTrue(prpcClient.call.calledOnce);
+ });
+
+ it('view link is not displayed if not given', async () => {
+ element.attachment = {};
+ await element.updateComplete;
+ const viewLink = element.shadowRoot.querySelector('.attachment-view');
+ assert.isNull(viewLink);
+ });
+
+ it('view link is displayed if given', async () => {
+ element.attachment = {
+ viewUrl: 'http://example.com/attachment.foo',
+ };
+ await element.updateComplete;
+ const viewLink = element.shadowRoot.querySelector('.attachment-view');
+ assert.isNotNull(viewLink);
+ expect(viewLink).to.be.displayed;
+ assert.equal(viewLink.href, 'http://example.com/attachment.foo');
+ });
+
+ describe('download', () => {
+ let downloadLink;
+
+ beforeEach(async () => {
+ sinon.stub(window, 'confirm').returns(false);
+
+
+ element.attachment = {};
+ await element.updateComplete;
+ downloadLink = element.shadowRoot.querySelector('.attachment-download');
+ // Prevent Karma from opening up new tabs because of simulated link
+ // clicks.
+ downloadLink.removeAttribute('target');
+ });
+
+ afterEach(() => {
+ window.confirm.restore();
+ });
+
+ it('download link is not displayed if not given', async () => {
+ element.attachment = {};
+ await element.updateComplete;
+ assert.isTrue(downloadLink.hidden);
+ });
+
+ it('download link is displayed if given', async () => {
+ element.attachment = {
+ downloadUrl: 'http://example.com/attachment.foo',
+ };
+ await element.updateComplete;
+ const downloadLink = element.shadowRoot.querySelector(
+ '.attachment-download');
+ assert.isFalse(downloadLink.hidden);
+ expect(downloadLink).to.be.displayed;
+ assert.equal(downloadLink.href, 'http://example.com/attachment.foo');
+ });
+
+ it('download allows recognized file extension and type', async () => {
+ element.attachment = {
+ contentType: 'image/png',
+ filename: 'not-a-virus.png',
+ downloadUrl: '#',
+ };
+ await element.updateComplete;
+
+ downloadLink.click();
+
+ sinon.assert.notCalled(window.confirm);
+ });
+
+ it('file extension matching is case insensitive', async () => {
+ element.attachment = {
+ contentType: 'image/png',
+ filename: 'not-a-virus.PNG',
+ downloadUrl: '#',
+ };
+ await element.updateComplete;
+
+ downloadLink.click();
+
+ sinon.assert.notCalled(window.confirm);
+ });
+
+ it('download warns on unrecognized file extension and type', async () => {
+ element.attachment = {
+ contentType: 'application/virus',
+ filename: 'fake-virus.exe',
+ downloadUrl: '#',
+ };
+ await element.updateComplete;
+
+ downloadLink.click();
+
+ sinon.assert.calledOnce(window.confirm);
+ sinon.assert.calledWith(window.confirm, FILE_DOWNLOAD_WARNING);
+ });
+ });
+});