emailTemplateTest.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. 'use strict';
  2. require('../common');
  3. // DOM builder that mirrors bootstrap5.php navbar
  4. function buildEmailDomNoShortUrl() {
  5. $('body').html(
  6. // TopNav expects initially hidden #emaillink BUTTON.
  7. '<nav><div id="navbar"><ul>' +
  8. '<li>' +
  9. '<button id="clonebutton" type="button" class="btn btn-warning navbar-btn">' +
  10. '<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone' +
  11. '</button>' +
  12. '</li>' +
  13. '<li>' +
  14. '<button id="emaillink" type="button" class="hidden btn btn-secondary">Email</button>' +
  15. '</li>' +
  16. '</ul></div></nav>' +
  17. '<input id="burnafterreadingoption" type="checkbox">'
  18. );
  19. }
  20. // DOM builder that adds the shortener result block
  21. function buildEmailDomWithShortUrl() {
  22. buildEmailDomNoShortUrl();
  23. $('body').html(
  24. // TopNav expectsinitially hidden #emaillink BUTTON.
  25. '<nav><div id="navbar"><ul>' +
  26. '<li>' +
  27. '<button id="clonebutton" type="button" class="btn btn-warning navbar-btn">' +
  28. '<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone' +
  29. '</button>' +
  30. '</li>' +
  31. '<li>' +
  32. '<button id="emaillink" type="button" class="hidden btn btn-secondary">Email</button>' +
  33. '</li>' +
  34. '</ul></div></nav>' +
  35. '<input id="burnafterreadingoption" type="checkbox">' +
  36. '<div id="pastelink">Your document is ' +
  37. '<a id="pasteurl" href="https://short.example/xYz">https://short.example/xYz</a> ' +
  38. '<span id="copyhint">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>' +
  39. '</div>'
  40. );
  41. }
  42. function stubWinOpen($element) {
  43. const win = $element[0].ownerDocument.defaultView;
  44. // Some helpers in privatebin.js expect a global document.
  45. global.document = win.document;
  46. let openedUrl = null;
  47. const origOpen = win.open;
  48. // Prefer simple assignment; if blocked, fall back to defineProperty.
  49. try {
  50. win.open = function (url) {
  51. openedUrl = url;
  52. return {};
  53. };
  54. } catch (e) {
  55. Object.defineProperty(win, 'open', {
  56. value: function (url) {
  57. openedUrl = url;
  58. return {};
  59. },
  60. configurable: true,
  61. writable: true
  62. });
  63. }
  64. return {
  65. getUrl: () => openedUrl,
  66. restore: () => { try { win.open = origOpen; } catch (e) { /* suppress exception in restore */ } },
  67. win
  68. };
  69. }
  70. // Extract and decode the body from a "mailto:?body=..." URL.
  71. function extractMailtoBody(mailtoUrl) {
  72. assert.match(mailtoUrl, /^mailto:\?body=/, 'expected a mailto:?body= URL');
  73. return decodeURIComponent(mailtoUrl.replace(/^mailto:\?body=/, ''));
  74. }
  75. describe('Email - mail body content (short URL vs. fallback)', function () {
  76. before(function () {
  77. cleanup(); // provided by common
  78. });
  79. it('Uses the short URL when #pasteurl is present and never includes "undefined"', function () {
  80. buildEmailDomWithShortUrl(); // with #pastelink/#pasteurl
  81. $.PrivateBin.TopNav.init();
  82. $.PrivateBin.TopNav.showEmailButton(0);
  83. const $emailBtn = $('#emaillink');
  84. assert.ok(!$emailBtn.hasClass('hidden'), '#emaillink should be visible after showEmailButton');
  85. const { getUrl, restore } = stubWinOpen($emailBtn);
  86. try {
  87. $emailBtn.trigger('click');
  88. const openedUrl = getUrl();
  89. assert.ok(openedUrl, 'window.open should have been called');
  90. const body = extractMailtoBody(openedUrl);
  91. assert.match(body, /https:\/\/short\.example\/xYz/, 'email body should include the short URL');
  92. assert.doesNotMatch(body, /undefined/, 'email body must not contain "undefined"');
  93. } finally {
  94. restore();
  95. cleanup();
  96. }
  97. });
  98. it('Falls back to window.location.href when #pasteurl is absent and never includes "undefined"', function () {
  99. buildEmailDomNoShortUrl(); // No #pasteurl
  100. $.PrivateBin.TopNav.init();
  101. $.PrivateBin.TopNav.showEmailButton(0);
  102. const $emailBtn = $('#emaillink');
  103. assert.ok(!$emailBtn.hasClass('hidden'), '#emaillink should be visible after showEmailButton');
  104. const { getUrl, restore, win } = stubWinOpen($emailBtn);
  105. try {
  106. $emailBtn.trigger('click');
  107. const openedUrl = getUrl();
  108. assert.ok(openedUrl, 'window.open should have been called');
  109. const body = extractMailtoBody(openedUrl);
  110. assert.match(body, new RegExp(win.location.href), 'email body should include the fallback page URL');
  111. assert.doesNotMatch(body, /undefined/, 'email body must not contain "undefined"');
  112. } finally {
  113. restore();
  114. cleanup();
  115. }
  116. });
  117. });