]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
mgr/dashboard: Copy to clipboard does not work in Firefox 37493/head
authorVolker Theile <vtheile@suse.com>
Tue, 22 Sep 2020 12:09:52 +0000 (14:09 +0200)
committerVolker Theile <vtheile@suse.com>
Wed, 30 Sep 2020 11:40:41 +0000 (13:40 +0200)
Fixes: https://tracker.ceph.com/issues/47578
Signed-off-by: Volker Theile <vtheile@suse.com>
(cherry picked from commit 8b9d881a63aac8ed3d7d1a7fc80be5e3d3d0b3b1)

Conflicts:
  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.spec.ts
src/pybind/mgr/dashboard/frontend/src/app/shared/directives/copy2clipboard-button.directive.ts

index 37fca45264e6572291498f99166c9006b8bb6c7d..28659705a8319baf24b2d93124f1d007d05dfc66 100644 (file)
@@ -1,18 +1,69 @@
 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();
+    });
+  });
 });
index 91d76151950822095ef88cefb1d186d1a43da8bb..be84809b4c755c165130a1bd9f57dcfa0de91b60 100644 (file)
@@ -1,6 +1,7 @@
 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({
@@ -25,24 +26,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.');
     }
   }