emailTemplateTest.js 4.9 KB

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