import { TestBed } from '@angular/core/testing';
import { I18n } from '@ngx-translate/i18n-polyfill';
+import * as BrowserDetect from 'detect-browser';
+import { ToastrService } from 'ngx-toastr';
import { configureTestBed, i18nProviders } from '../../../testing/unit-test-helper';
import { Copy2ClipboardButtonDirective } from './copy2clipboard-button.directive';
describe('Copy2clipboardButtonDirective', () => {
+ let directive: Copy2ClipboardButtonDirective;
+
configureTestBed({
- providers: [i18nProviders]
+ providers: [
+ i18nProviders,
+ {
+ provide: ToastrService,
+ useValue: {
+ error: () => true,
+ success: () => true
+ }
+ }
+ ]
});
it('should create an instance', () => {
const i18n = TestBed.get(I18n);
- const directive = new Copy2ClipboardButtonDirective(null, null, null, i18n);
+ directive = new Copy2ClipboardButtonDirective(null, null, null, i18n);
expect(directive).toBeTruthy();
});
+
+ describe('test onClick behaviours', () => {
+ let toastrService: ToastrService;
+ let queryFn: jasmine.Spy;
+ let writeTextFn: jasmine.Spy;
+
+ beforeEach(() => {
+ const i18n = TestBed.get(I18n);
+ toastrService = TestBed.get(ToastrService);
+ directive = new Copy2ClipboardButtonDirective(null, null, toastrService, i18n);
+ 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();
+ });
+ });
});
import { Directive, ElementRef, HostListener, Input, OnInit, Renderer2 } from '@angular/core';
import { I18n } from '@ngx-translate/i18n-polyfill';
+import { detect } from 'detect-browser';
import { ToastrService } from 'ngx-toastr';
@Directive({
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 {
- // 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);
- }
- });
- this.toastr.success('Copied text to the clipboard successfully.');
- } catch (err) {
+ 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') {
+ navigator.clipboard.writeText(text).then(() => toastrFn());
+ }
+ });
+ }
+ } catch (_) {
this.toastr.error('Failed to copy text to the clipboard.');
}
}