Merge pull request #37312 from votdev/issue_47578_clipboard_firefox

mgr/dashboard: Copy to clipboard does not work in Firefox

Reviewed-by: Kiefer Chang <kiefer.chang@suse.com>
Reviewed-by: Tiago Melo <tmelo@suse.com>
This commit is contained in:
Lenz Grimmer 2020-09-30 11:49:41 +02:00 committed by GitHub
commit 3fec8e7ac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 14 deletions

View File

@ -1,8 +1,65 @@
import { TestBed } from '@angular/core/testing';
import * as BrowserDetect from 'detect-browser';
import { ToastrService } from 'ngx-toastr';
import { configureTestBed } from '../../../testing/unit-test-helper';
import { Copy2ClipboardButtonDirective } from './copy2clipboard-button.directive';
describe('Copy2clipboardButtonDirective', () => {
let directive: Copy2ClipboardButtonDirective;
configureTestBed({
providers: [
{
provide: ToastrService,
useValue: {
error: () => true,
success: () => true
}
}
]
});
it('should create an instance', () => {
const directive = new Copy2ClipboardButtonDirective(null, null, null);
directive = new Copy2ClipboardButtonDirective(null, null, null);
expect(directive).toBeTruthy();
});
describe('test onClick behaviours', () => {
let toastrService: ToastrService;
let queryFn: jasmine.Spy;
let writeTextFn: jasmine.Spy;
beforeEach(() => {
toastrService = TestBed.inject(ToastrService);
directive = new Copy2ClipboardButtonDirective(null, null, toastrService);
spyOn<any>(directive, 'getText').and.returnValue('foo');
Object.assign(navigator, {
permissions: { query: jest.fn() },
clipboard: {
writeText: jest.fn()
}
});
queryFn = spyOn(navigator.permissions, 'query');
});
it('should not call permissions API', () => {
spyOn(BrowserDetect, 'detect').and.returnValue({ name: 'firefox' });
writeTextFn = spyOn(navigator.clipboard, 'writeText').and.returnValue(
new Promise<void>((resolve, _) => {
resolve();
})
);
directive.onClick();
expect(queryFn).not.toHaveBeenCalled();
expect(writeTextFn).toHaveBeenCalledWith('foo');
});
it('should call permissions API', () => {
spyOn(BrowserDetect, 'detect').and.returnValue({ name: 'chrome' });
directive.onClick();
expect(queryFn).toHaveBeenCalled();
});
});
});

View File

@ -1,5 +1,6 @@
import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2 } from '@angular/core';
import { detect } from 'detect-browser';
import { ToastrService } from 'ngx-toastr';
@Directive({
@ -23,24 +24,34 @@ export class Copy2ClipboardButtonDirective implements OnInit {
this.renderer.appendChild(this.elementRef.nativeElement, iElement);
}
private getInputElement() {
return document.getElementById(this.cdCopy2ClipboardButton) as HTMLInputElement;
private getText(): string {
const element = document.getElementById(this.cdCopy2ClipboardButton) as HTMLInputElement;
return element.value;
}
@HostListener('click')
onClick() {
try {
const browser = detect();
const text = this.getText();
const toastrFn = () => {
this.toastr.success('Copied text to the clipboard successfully.');
};
if (['firefox', 'ie', 'ios', 'safari'].includes(browser.name)) {
// Various browsers do not support the `Permissions API`.
// https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API#Browser_compatibility
navigator.clipboard.writeText(text).then(() => toastrFn());
} else {
// Checking if we have the clipboard-write permission
navigator.permissions
.query({ name: 'clipboard-write' as PermissionName })
.then((result: any) => {
if (result.state === 'granted' || result.state === 'prompt') {
// Copy text to clipboard.
navigator.clipboard.writeText(this.getInputElement().value);
navigator.clipboard.writeText(text).then(() => toastrFn());
}
});
this.toastr.success('Copied text to the clipboard successfully.');
} catch (err) {
}
} catch (_) {
this.toastr.error('Failed to copy text to the clipboard.');
}
}