request-password-reset.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import assert from 'assert';
  2. import React from 'react'; // jshint ignore:line
  3. import ReactDOM from 'react-dom'; // jshint ignore:line
  4. import misago from 'misago/index';
  5. import { RequestResetForm, LinkSent, AccountInactivePage } from 'misago/components/request-password-reset'; // jshint ignore:line
  6. import snackbar from 'misago/services/snackbar';
  7. let snackbarStore = null;
  8. describe("Request Password Reset Form", function() {
  9. beforeEach(function() {
  10. snackbarStore = window.snackbarStoreMock();
  11. snackbar.init(snackbarStore);
  12. misago._context = {
  13. 'SETTINGS': {
  14. 'forum_name': 'Test forum'
  15. },
  16. 'SEND_PASSWORD_RESET_API': '/test-api/request-password-reset/'
  17. };
  18. /* jshint ignore:start */
  19. ReactDOM.render(
  20. <RequestResetForm />,
  21. document.getElementById('test-mount')
  22. );
  23. /* jshint ignore:end */
  24. });
  25. afterEach(function() {
  26. window.emptyTestContainers();
  27. window.snackbarClear(snackbar);
  28. $.mockjax.clear();
  29. });
  30. it("renders", function() {
  31. let element = $('#test-mount .well-form-request-password-reset');
  32. assert.ok(element.length, "component renders");
  33. });
  34. it("handles empty submit", function(done) {
  35. snackbarStore.callback(function(message) {
  36. assert.deepEqual(message, {
  37. message: "Enter a valid email address.",
  38. type: 'error'
  39. }, "form brought error about no input");
  40. done();
  41. });
  42. window.simulateSubmit('#test-mount form');
  43. });
  44. it("handles invalid submit", function(done) {
  45. snackbarStore.callback(function(message) {
  46. assert.deepEqual(message, {
  47. message: "Enter a valid email address.",
  48. type: 'error'
  49. }, "form brought error about invalid input");
  50. done();
  51. });
  52. window.simulateChange('#test-mount input', 'loremipsum');
  53. window.simulateSubmit('#test-mount form');
  54. });
  55. it("handles backend error", function(done) {
  56. snackbarStore.callback(function(message) {
  57. assert.deepEqual(message, {
  58. message: "Unknown error has occured.",
  59. type: 'error'
  60. }, "form raised alert about backend error");
  61. done();
  62. });
  63. $.mockjax({
  64. url: '/test-api/request-password-reset/',
  65. status: 500
  66. });
  67. window.simulateChange('#test-mount input', 'lorem@ipsum.com');
  68. window.simulateSubmit('#test-mount form');
  69. });
  70. it("handles backend rejection", function(done) {
  71. snackbarStore.callback(function(message) {
  72. assert.deepEqual(message, {
  73. message: "Nope nope nope!",
  74. type: 'error'
  75. }, "form raised alert about backend rejection");
  76. done();
  77. });
  78. $.mockjax({
  79. url: '/test-api/request-password-reset/',
  80. status: 400,
  81. responseText: {
  82. detail: "Nope nope nope!"
  83. }
  84. });
  85. window.simulateChange('#test-mount input', 'lorem@ipsum.com');
  86. window.simulateSubmit('#test-mount form');
  87. });
  88. it("displays activation required message", function(done) { // jshint ignore:line
  89. $.mockjax({
  90. url: '/test-api/request-password-reset/',
  91. status: 400,
  92. responseText: {
  93. code: 'inactive_user',
  94. detail: "Your account is inactive!"
  95. }
  96. });
  97. /* jshint ignore:start */
  98. let showInactivePage = function(apiResponse) {
  99. assert.deepEqual({
  100. code: apiResponse.code,
  101. detail: apiResponse.detail
  102. }, {
  103. code: 'inactive_user',
  104. detail: "Your account is inactive!"
  105. }, "component calls inactive page callback");
  106. done();
  107. };
  108. ReactDOM.render(
  109. <RequestResetForm showInactivePage={showInactivePage}/>,
  110. document.getElementById('test-mount')
  111. );
  112. /* jshint ignore:end */
  113. window.simulateChange('#test-mount input', 'lorem@ipsum.com');
  114. window.simulateSubmit('#test-mount form');
  115. });
  116. it("from banned IP", function(done) {
  117. $.mockjax({
  118. url: '/test-api/request-password-reset/',
  119. status: 403,
  120. responseText: {
  121. 'ban': {
  122. 'expires_on': null,
  123. 'message': {
  124. 'plain': 'Your ip is banned for spamming.',
  125. 'html': '<p>Your ip is banned for spamming.</p>',
  126. }
  127. }
  128. }
  129. });
  130. window.simulateChange('#test-mount input', 'lorem@ipsum.com');
  131. window.simulateSubmit('#test-mount form');
  132. window.onElement('.page-error-banned .lead', function() {
  133. assert.equal(
  134. $('.page .message-body .lead p').text().trim(),
  135. "Your ip is banned for spamming.",
  136. "displayed error banned page with ban message.");
  137. done();
  138. });
  139. });
  140. it("handles success", function(done) { // jshint ignore:line
  141. $.mockjax({
  142. url: '/test-api/request-password-reset/',
  143. status: 200,
  144. responseText: {
  145. 'username': 'Bob',
  146. 'email': 'bob@boberson.com'
  147. }
  148. });
  149. /* jshint ignore:start */
  150. let callback = function(apiResponse) {
  151. assert.deepEqual(apiResponse, {
  152. 'username': 'Bob',
  153. 'email': 'bob@boberson.com'
  154. }, "callback function was called on ajax success");
  155. done();
  156. };
  157. ReactDOM.render(
  158. <RequestResetForm callback={callback} />,
  159. document.getElementById('test-mount')
  160. );
  161. /* jshint ignore:end */
  162. window.simulateChange('#test-mount input', 'lorem@ipsum.com');
  163. window.simulateSubmit('#test-mount form');
  164. });
  165. });
  166. describe("Reset Link Sent", function() {
  167. afterEach(function() {
  168. window.emptyTestContainers();
  169. });
  170. it("renders message", function(done) { // jshint ignore:line
  171. /* jshint ignore:start */
  172. let callback = function() {
  173. assert.ok(true, "callback function was called on button press");
  174. done();
  175. };
  176. ReactDOM.render(
  177. <LinkSent user={{email: 'bob@boberson.com' }}
  178. callback={callback} />,
  179. document.getElementById('test-mount')
  180. );
  181. /* jshint ignore:end */
  182. let element = $('#test-mount .well-done');
  183. assert.ok(element.length, "component renders");
  184. assert.equal(element.find('p').text().trim(),
  185. "Reset password link was sent to bob@boberson.com",
  186. "component renders valid message");
  187. window.simulateClick('#test-mount .btn-primary');
  188. });
  189. });
  190. describe("Account Inactive Page", function() {
  191. beforeEach(function() {
  192. misago._context = {
  193. 'REQUEST_ACTIVATION_URL': '/activate-thy-account/'
  194. };
  195. });
  196. afterEach(function() {
  197. window.emptyTestContainers();
  198. });
  199. it("renders page for user-activated user", function() {
  200. /* jshint ignore:start */
  201. ReactDOM.render(
  202. <AccountInactivePage activation='inactive_user'
  203. message="Lorem ipsum dolor met." />,
  204. document.getElementById('test-mount')
  205. );
  206. /* jshint ignore:end */
  207. let element = $('#test-mount .page-forgotten-password-inactive');
  208. assert.ok(element.length, "component renders");
  209. assert.equal(
  210. $('#test-mount .page .message-body p:eq(1)').text().trim(),
  211. "Lorem ipsum dolor met.",
  212. "displayed error inactive page with backend message.");
  213. assert.equal($('#test-mount a').attr('href'), '/activate-thy-account/',
  214. "activate account link is displayed on inactive error page");
  215. });
  216. it("renders page for admin-activated user", function() {
  217. /* jshint ignore:start */
  218. ReactDOM.render(
  219. <AccountInactivePage activation='inactive_admin'
  220. message="Lorem ipsum dolor met admin." />,
  221. document.getElementById('test-mount')
  222. );
  223. /* jshint ignore:end */
  224. let element = $('#test-mount .page-forgotten-password-inactive');
  225. assert.ok(element.length, "component renders");
  226. assert.equal(
  227. $('#test-mount .page .message-body p:eq(1)').text().trim(),
  228. "Lorem ipsum dolor met admin.",
  229. "displayed error inactive page with backend message.");
  230. assert.ok(!$('#test-mount a').length,
  231. "activate account link is not displayed on admin-activated error page");
  232. });
  233. });