]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Copy to clipboard does not work in Firefox 37312/head
authorVolker Theile <vtheile@suse.com>
Tue, 22 Sep 2020 12:09:52 +0000 (14:09 +0200)
committerVolker Theile <vtheile@suse.com>
Tue, 22 Sep 2020 14:03:55 +0000 (16:03 +0200)
Fixes: https://tracker.ceph.com/issues/47578
Signed-off-by: Volker Theile <vtheile@suse.com>
src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts

index e50fd86332c435b970d370bdf648105f3e4e58cc..1b31727fcce9aab3dda072fe2d8b9ca2397b1305 100644 (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();
+    });
+  });
 });
index 78e4767e53946e6986dc08fdbe421c169d8f05cf..2a42f19b077341b06e160337c930244b8d65a9b9 100644 (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 {
-      // 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.');
     }
   }