1
0

emailTemplateTest.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. 'use strict';
  2. require('../common');
  3. // DOM builder that mirrors bootstrap5.php navbar
  4. function buildEmailDomNoShortUrl() {
  5. document.documentElement.innerHTML =
  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. // include dummy email confirm modal for sendEmail
  19. '<div id="emailconfirmmodal" class="hidden">' +
  20. '<div id="emailconfirm-timezone-current"></div>' +
  21. '<div id="emailconfirm-timezone-utc"></div>' +
  22. '</div>'
  23. }
  24. // DOM builder that adds the shortener result block
  25. function buildEmailDomWithShortUrl() {
  26. buildEmailDomNoShortUrl();
  27. document.documentElement.innerHTML =
  28. // TopNav expectsinitially hidden #emaillink BUTTON.
  29. '<nav><div id="navbar"><ul>' +
  30. '<li>' +
  31. '<button id="clonebutton" type="button" class="btn btn-warning navbar-btn">' +
  32. '<span class="glyphicon glyphicon-duplicate" aria-hidden="true"></span> Clone' +
  33. '</button>' +
  34. '</li>' +
  35. '<li>' +
  36. '<button id="emaillink" type="button" class="hidden btn btn-secondary">Email</button>' +
  37. '</li>' +
  38. '</ul></div></nav>' +
  39. '<input id="burnafterreadingoption" type="checkbox">' +
  40. '<div id="pastelink">Your document is ' +
  41. '<a id="pasteurl" href="https://short.example/xYz">https://short.example/xYz</a> ' +
  42. '<span id="copyhint">(Hit <kbd>Ctrl</kbd>+<kbd>c</kbd> to copy)</span>' +
  43. '</div>' +
  44. // add a minimal email confirmation modal so sendEmail does not crash
  45. '<div id="emailconfirmmodal" class="hidden">' +
  46. '<div id="emailconfirm-timezone-current"></div>' +
  47. '<div id="emailconfirm-timezone-utc"></div>' +
  48. '</div>'
  49. }
  50. function makeWindowOpenMock() {
  51. const originalOpen = window.open;
  52. let openedUrl = null;
  53. let mockRestoreFn = null;
  54. if (typeof jest !== 'undefined' && typeof jest.spyOn === 'function') {
  55. const spy = jest.spyOn(window, 'open').mockImplementation((url) => {
  56. openedUrl = url;
  57. return {};
  58. });
  59. mockRestoreFn = () => spy.mockRestore();
  60. } else {
  61. window.open = function (url) {
  62. openedUrl = url;
  63. return {};
  64. };
  65. mockRestoreFn = () => { window.open = originalOpen; };
  66. }
  67. return {
  68. getUrl: () => openedUrl,
  69. restore: () => {
  70. if (mockRestoreFn) {
  71. mockRestoreFn();
  72. }
  73. }
  74. };
  75. }
  76. // Extract and decode the body from a "mailto:?body=..." URL.
  77. function extractMailtoBody(mailtoUrl) {
  78. assert.match(mailtoUrl, /^mailto:\?body=/, 'expected a mailto:?body= URL');
  79. return decodeURIComponent(mailtoUrl.replace(/^mailto:\?body=/, ''));
  80. }
  81. describe('Email - mail body content (short URL vs. fallback)', function () {
  82. beforeEach(function () {
  83. cleanup(); // provided by common
  84. });
  85. it('Uses the short URL when #pasteurl is present and never includes "undefined"', function () {
  86. buildEmailDomWithShortUrl(); // with #pastelink/#pasteurl
  87. PrivateBin.TopNav.init();
  88. PrivateBin.TopNav.showEmailButton(0);
  89. const emailBtn = document.getElementById('emaillink');
  90. assert.ok(!emailBtn.classList.contains('hidden'), '#emaillink should be visible after showEmailButton');
  91. const { getUrl, restore } = makeWindowOpenMock();
  92. try {
  93. emailBtn.click();
  94. document.getElementById('emailconfirm-timezone-current').click();
  95. const openedUrl = getUrl();
  96. assert.ok(openedUrl, 'window.open should have been called');
  97. const body = extractMailtoBody(openedUrl);
  98. assert.match(body, /https:\/\/short\.example\/xYz/, 'email body should include the short URL');
  99. assert.doesNotMatch(body, /undefined/, 'email body must not contain "undefined"');
  100. } finally {
  101. restore();
  102. }
  103. });
  104. it('Falls back to window.location.href when #pasteurl is absent and never includes "undefined"', function () {
  105. buildEmailDomNoShortUrl(); // No #pasteurl
  106. PrivateBin.TopNav.init();
  107. PrivateBin.TopNav.showEmailButton(0);
  108. const emailBtn = document.getElementById('emaillink');
  109. assert.ok(!emailBtn.classList.contains('hidden'), '#emaillink should be visible after showEmailButton');
  110. const { getUrl, restore } = makeWindowOpenMock();
  111. try {
  112. emailBtn.click();
  113. document.getElementById('emailconfirm-timezone-current').click();
  114. const openedUrl = getUrl();
  115. assert.ok(openedUrl, 'window.open should have been called');
  116. const body = extractMailtoBody(openedUrl);
  117. assert.match(body, new RegExp(window.location.href), 'email body should include the fallback page URL');
  118. assert.doesNotMatch(body, /undefined/, 'email body must not contain "undefined"');
  119. } finally {
  120. restore();
  121. }
  122. });
  123. });