1
0

CopyToClipboard.js 6.5 KB

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