CopyToClipboard.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. 'use strict';
  2. const common = require('../common');
  3. const fc = require('fast-check');
  4. describe('CopyToClipboard', function () {
  5. afterEach(() => {
  6. globalThis.cleanup();
  7. });
  8. describe('Copy document to clipboard', function () {
  9. it('Copy with button click', async function () {
  10. await fc.assert(fc.asyncProperty(
  11. common.fcFormats(),
  12. fc.string({minLength: 1}),
  13. async function (format, text) {
  14. common.enableClipboard();
  15. document.body.innerHTML = (
  16. '<div id="status" class="hidden"></div>' +
  17. '<div id="errormessage" class="hidden"></div>' +
  18. '<div id="placeholder" class="hidden">+++ no document text ' +
  19. '+++</div><div id="prettymessage" class="hidden">' +
  20. '<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
  21. '<svg id="copySuccessIcon"></svg></button><pre ' +
  22. 'id="prettyprint" class="prettyprint linenums:1"></pre>' +
  23. '</div><div id="plaintext" class="hidden"></div>'
  24. );
  25. PrivateBin.Alert.init();
  26. PrivateBin.PasteViewer.init();
  27. PrivateBin.PasteViewer.setFormat(format);
  28. PrivateBin.PasteViewer.setText(text);
  29. PrivateBin.PasteViewer.run();
  30. PrivateBin.CopyToClipboard.init();
  31. document.getElementById('prettyMessageCopyBtn').click();
  32. const savedToClipboardText = await navigator.clipboard.readText();
  33. return text === savedToClipboardText;
  34. }
  35. ));
  36. });
  37. /**
  38. * Unfortunately, in JSVerify impossible to check if copy with shortcut when user selected some text on the page
  39. * (the copy document to clipboard should not work in this case) due to lacking window.getSelection() in jsdom.
  40. */
  41. it('Copy with keyboard shortcut', async function () {
  42. await fc.assert(fc.asyncProperty(
  43. common.fcFormats(),
  44. fc.string({minLength: 1}),
  45. async function (format, text) {
  46. common.enableClipboard();
  47. document.body.innerHTML = (
  48. '<div id="status" class="hidden"></div>' +
  49. '<div id="errormessage" class="hidden"></div>' +
  50. '<div id="placeholder">+++ no document text ' +
  51. '+++</div><div id="prettymessage" class="hidden">' +
  52. '<button type="button" id="prettyMessageCopyBtn"><svg id="copyIcon"></svg>' +
  53. '<svg id="copySuccessIcon"></svg></button><pre ' +
  54. 'id="prettyprint" class="prettyprint linenums:1"></pre>' +
  55. '</div><div id="plaintext" class="hidden"></div>'
  56. );
  57. PrivateBin.Alert.init();
  58. PrivateBin.PasteViewer.init();
  59. PrivateBin.PasteViewer.setFormat(format);
  60. PrivateBin.PasteViewer.setText(text);
  61. PrivateBin.PasteViewer.run();
  62. PrivateBin.CopyToClipboard.init();
  63. document.body.dispatchEvent(getClipboardEvent());
  64. const copiedTextWithoutSelectedText = await navigator.clipboard.readText();
  65. return copiedTextWithoutSelectedText === text;
  66. }
  67. ));
  68. });
  69. /**
  70. * ClipboardEvent is not supported in jsdom yet, so this creates a mock event to trigger the copy event listener.
  71. *
  72. * See https://github.com/jsdom/jsdom/issues/1568
  73. *
  74. * @returns {ClipboardEvent}
  75. */
  76. function getClipboardEvent() {
  77. /** {@type ClipboardEvent} */
  78. const clipboardEvent = new Event('copy', {
  79. bubbles: true,
  80. cancelable: true,
  81. composed: true
  82. });
  83. clipboardEvent['clipboardData'] = {
  84. getData: function () {
  85. return '';
  86. }
  87. }
  88. return clipboardEvent;
  89. }
  90. });
  91. it('Copy link to clipboard', async function () {
  92. await fc.assert(fc.asyncProperty(fc.string(),
  93. async function (text) {
  94. common.enableClipboard();
  95. document.body.innerHTML = (
  96. '<div id="status" class="hidden"></div>' +
  97. '<div id="errormessage" class="hidden"></div>' +
  98. '<button id="copyLink"></button>'
  99. );
  100. PrivateBin.Alert.init();
  101. PrivateBin.CopyToClipboard.init();
  102. PrivateBin.CopyToClipboard.setUrl(text);
  103. document.getElementById('copyLink').click();
  104. const copiedText = await navigator.clipboard.readText();
  105. return text === copiedText;
  106. })
  107. );
  108. });
  109. describe('Keyboard shortcut hint', function () {
  110. it('shows hint', () => {
  111. fc.assert(fc.property(fc.string(),
  112. function (text) {
  113. document.body.innerHTML = '<small id="copyShortcutHintText"></small>';
  114. PrivateBin.CopyToClipboard.init();
  115. PrivateBin.CopyToClipboard.showKeyboardShortcutHint();
  116. const keyboardShortcutHint = document.getElementById('copyShortcutHintText').textContent;
  117. return keyboardShortcutHint.length > 0;
  118. }
  119. ));
  120. });
  121. });
  122. it('Hide hint', () => {
  123. fc.assert(fc.property(
  124. fc.string({minLength: 1}),
  125. function (text) {
  126. document.body.innerHTML = '<small id="copyShortcutHintText">' + text + '</small>';
  127. PrivateBin.CopyToClipboard.init();
  128. PrivateBin.CopyToClipboard.hideKeyboardShortcutHint();
  129. const keyboardShortcutHint = document.getElementById('copyShortcutHintText').textContent;
  130. return keyboardShortcutHint.length === 0;
  131. }
  132. ));
  133. });
  134. });