change-username.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. import assert from 'assert';
  2. import moment from 'moment'; // jshint ignore:line
  3. import React from 'react'; // jshint ignore:line
  4. import FormLoading from 'misago/components/options/change-username/form-loading'; // jshint ignore:line
  5. import FormLocked from 'misago/components/options/change-username/form-locked'; // jshint ignore:line
  6. import Form from 'misago/components/options/change-username/form'; // jshint ignore:line
  7. import Root from 'misago/components/options/change-username/root'; // jshint ignore:line
  8. import UsernameHistory from 'misago/components/options/change-username/username-history'; // jshint ignore:line
  9. import misago from 'misago/index';
  10. import snackbar from 'misago/services/snackbar';
  11. import store from 'misago/services/store';
  12. import * as testUtils from 'misago/utils/test-utils';
  13. let snackbarStore = null;
  14. let user = testUtils.mockUser();
  15. user.acl.name_changes_expire = 2;
  16. describe("Change Username Form", function() {
  17. beforeEach(function() {
  18. snackbarStore = testUtils.snackbarStoreMock();
  19. snackbar.init(snackbarStore);
  20. testUtils.initEmptyStore(store);
  21. });
  22. afterEach(function() {
  23. testUtils.unmountComponents();
  24. testUtils.snackbarClear(snackbar);
  25. $.mockjax.clear();
  26. });
  27. it("renders", function(done) {
  28. /* jshint ignore:start */
  29. let options = {
  30. changes_left: 5,
  31. length_min: 3,
  32. length_max: 14,
  33. next_on: null
  34. };
  35. testUtils.render(
  36. <Form user={user}
  37. options={options} />
  38. );
  39. /* jshint ignore:end */
  40. testUtils.onElement('#test-mount .form-horizontal', function() {
  41. assert.ok(true, "component renders");
  42. assert.equal($('#test-mount form .help-block').text().trim(),
  43. "You can change your username 5 more times. Used changes redeem after 2 days.",
  44. "valid help text is displayed in form");
  45. done();
  46. });
  47. });
  48. it("handles empty submit", function(done) {
  49. /* jshint ignore:start */
  50. let options = {
  51. changes_left: 5,
  52. length_min: 3,
  53. length_max: 14,
  54. next_on: null
  55. };
  56. testUtils.render(
  57. <Form user={user}
  58. options={options} />
  59. );
  60. /* jshint ignore:end */
  61. snackbarStore.callback(function(message) {
  62. assert.deepEqual(message, {
  63. message: "This field is required.",
  64. type: 'error'
  65. }, "error message was shown");
  66. done();
  67. });
  68. testUtils.onElement('#test-mount form', function() {
  69. testUtils.simulateSubmit('#test-mount form');
  70. });
  71. });
  72. it("handles invalid submit", function(done) {
  73. /* jshint ignore:start */
  74. let options = {
  75. changes_left: 5,
  76. length_min: 10,
  77. length_max: 14,
  78. next_on: null
  79. };
  80. testUtils.render(
  81. <Form user={user}
  82. options={options} />
  83. );
  84. /* jshint ignore:end */
  85. snackbarStore.callback(function(message) {
  86. assert.deepEqual(message, {
  87. message: "Username must be at least 10 characters long.",
  88. type: 'error'
  89. }, "error message was shown");
  90. done();
  91. });
  92. testUtils.onElement('#test-mount form', function() {
  93. testUtils.simulateChange('#test-mount form #id_username', 'NewName');
  94. testUtils.simulateSubmit('#test-mount form');
  95. });
  96. });
  97. it("handles backend rejection", function(done) {
  98. $.mockjax({
  99. url: user.api_url.username,
  100. status: 400,
  101. responseText: {
  102. detail: "Lol nope!"
  103. }
  104. });
  105. /* jshint ignore:start */
  106. let options = {
  107. changes_left: 5,
  108. length_min: 3,
  109. length_max: 14,
  110. next_on: null
  111. };
  112. testUtils.render(
  113. <Form user={user}
  114. options={options} />
  115. );
  116. /* jshint ignore:end */
  117. snackbarStore.callback(function(message) {
  118. assert.deepEqual(message, {
  119. message: "Lol nope!",
  120. type: 'error'
  121. }, "error message from backend was shown");
  122. done();
  123. });
  124. testUtils.onElement('#test-mount form', function() {
  125. testUtils.simulateChange('#test-mount form #id_username', 'Newt');
  126. testUtils.simulateSubmit('#test-mount form');
  127. });
  128. });
  129. it("handles backend error", function(done) {
  130. $.mockjax({
  131. url: user.api_url.username,
  132. status: 500
  133. });
  134. /* jshint ignore:start */
  135. let options = {
  136. changes_left: 5,
  137. length_min: 3,
  138. length_max: 14,
  139. next_on: null
  140. };
  141. testUtils.render(
  142. <Form user={user}
  143. options={options} />
  144. );
  145. /* jshint ignore:end */
  146. snackbarStore.callback(function(message) {
  147. assert.deepEqual(message, {
  148. message: "Unknown error has occured.",
  149. type: 'error'
  150. }, "error message from backend was shown");
  151. done();
  152. });
  153. testUtils.onElement('#test-mount form', function() {
  154. testUtils.simulateChange('#test-mount form #id_username', 'Newt');
  155. testUtils.simulateSubmit('#test-mount form');
  156. });
  157. });
  158. it("handles successfull submission", function(done) { // jshint ignore:line
  159. $.mockjax({
  160. url: user.api_url.username,
  161. status: 200,
  162. responseText: {
  163. username: 'Newt',
  164. slug: 'newt',
  165. options: {
  166. changes_left: 4,
  167. length_min: 3,
  168. length_max: 14,
  169. next_on: null
  170. }
  171. }
  172. });
  173. /* jshint ignore:start */
  174. let options = {
  175. changes_left: 5,
  176. length_min: 3,
  177. length_max: 14,
  178. next_on: null
  179. };
  180. let callback = function(username, slug, options) {
  181. assert.equal(username, 'Newt', "new username is passed to callback");
  182. assert.equal(slug, 'newt', "new slug is passed to callback");
  183. assert.deepEqual(options, {
  184. changes_left: 4,
  185. length_min: 3,
  186. length_max: 14,
  187. next_on: null
  188. }, "new options are passed to callback");
  189. done();
  190. };
  191. testUtils.render(
  192. <Form user={user}
  193. options={options}
  194. complete={callback} />
  195. );
  196. /* jshint ignore:end */
  197. testUtils.onElement('#test-mount form', function() {
  198. testUtils.simulateChange('#test-mount form #id_username', 'newt');
  199. testUtils.simulateSubmit('#test-mount form');
  200. });
  201. });
  202. });
  203. describe("Change Username Form Locked", function() {
  204. afterEach(function() {
  205. testUtils.unmountComponents();
  206. });
  207. it("renders", function(done) {
  208. /* jshint ignore:start */
  209. let options = {
  210. changes_left: 5,
  211. length_min: 3,
  212. length_max: 14,
  213. next_on: null
  214. };
  215. testUtils.render(<FormLocked options={options} />);
  216. /* jshint ignore:end */
  217. testUtils.onElement('#test-mount .panel-message-body', function() {
  218. assert.ok(true, "component renders");
  219. assert.equal($('#test-mount .help-block').text().trim(),
  220. "You have used up available name changes.",
  221. "valid help text is displayed in message");
  222. done();
  223. });
  224. });
  225. it("renders with next change message", function(done) {
  226. /* jshint ignore:start */
  227. let options = {
  228. changes_left: 5,
  229. length_min: 3,
  230. length_max: 14,
  231. next_on: moment().add(5, 'days')
  232. };
  233. testUtils.render(<FormLocked options={options} />);
  234. /* jshint ignore:end */
  235. testUtils.onElement('#test-mount .panel-message-body', function() {
  236. assert.ok(true, "component renders");
  237. assert.equal($('#test-mount .help-block').text().trim(),
  238. "You will be able to change your username in 5 days.",
  239. "valid help text is displayed in message");
  240. done();
  241. });
  242. });
  243. });
  244. describe("Change Username Form Loading", function() {
  245. afterEach(function() {
  246. testUtils.unmountComponents();
  247. });
  248. it("renders", function(done) {
  249. /* jshint ignore:start */
  250. testUtils.render(<FormLoading />);
  251. /* jshint ignore:end */
  252. testUtils.onElement('#test-mount .panel-body-loading', function() {
  253. assert.ok(true, "component renders");
  254. done();
  255. });
  256. });
  257. });
  258. describe("Username History Changes List", function() {
  259. afterEach(function() {
  260. testUtils.unmountComponents();
  261. });
  262. it("renders preview", function(done) {
  263. /* jshint ignore:start */
  264. testUtils.render(<UsernameHistory isLoaded={false} />);
  265. /* jshint ignore:end */
  266. testUtils.onElement('#test-mount .username-history.ui-preview', function() {
  267. assert.ok(true, "component renders");
  268. done();
  269. });
  270. });
  271. it("renders empty", function(done) {
  272. /* jshint ignore:start */
  273. testUtils.render(
  274. <UsernameHistory isLoaded={true}
  275. changes={[]} />
  276. );
  277. /* jshint ignore:end */
  278. testUtils.onElement('#test-mount .empty-message', function() {
  279. assert.equal($('.empty-message').text().trim(),
  280. "No name changes have been recorded for your account.",
  281. "component renders with message");
  282. done();
  283. });
  284. });
  285. it("renders with two changes", function(done) {
  286. /* jshint ignore:start */
  287. let changes = [
  288. {
  289. id: 27,
  290. changed_by: {
  291. id: 1,
  292. username: "rafalp",
  293. slug: "rafalp",
  294. avatar_hash: "5c6a04b4",
  295. absolute_url: "/user/rafalp-1/"
  296. },
  297. changed_by_username: "rafalp",
  298. changed_on: moment(),
  299. new_username: "Newt",
  300. old_username: "LoremIpsum"
  301. },
  302. {
  303. id: 26,
  304. changed_by: {
  305. id: 1,
  306. username: "rafalp",
  307. slug: "rafalp",
  308. avatar_hash: "5c6a04b4",
  309. absolute_url: "/user/rafalp-1/"
  310. },
  311. changed_by_username: "rafalp",
  312. changed_on: moment(),
  313. new_username: "LoremIpsum",
  314. old_username: "BobBoberson"
  315. }
  316. ];
  317. testUtils.render(
  318. <UsernameHistory isLoaded={true}
  319. changes={changes} />
  320. );
  321. /* jshint ignore:end */
  322. testUtils.onElement('#test-mount .username-history.ui-ready', function() {
  323. assert.equal($('#test-mount .list-group-item').length, 2,
  324. "component renders with two items");
  325. done();
  326. });
  327. });
  328. });
  329. describe("Change Username Integration", function() {
  330. beforeEach(function() {
  331. snackbarStore = testUtils.snackbarStoreMock();
  332. snackbar.init(snackbarStore);
  333. testUtils.initEmptyStore(store);
  334. misago._context = {
  335. USERNAME_CHANGES_API: '/test-api/name-history/'
  336. };
  337. });
  338. afterEach(function() {
  339. testUtils.unmountComponents();
  340. testUtils.snackbarClear(snackbar);
  341. $.mockjax.clear();
  342. });
  343. it("renders", function(done) {
  344. $.mockjax({
  345. url: user.api_url.username,
  346. status: 200,
  347. responseText: {
  348. changes_left: 2,
  349. length_min: 3,
  350. length_max: 14,
  351. next_on: null
  352. }
  353. });
  354. $.mockjax({
  355. url: '/test-api/name-history/?user=' + user.id,
  356. status: 200,
  357. responseText: {
  358. results: []
  359. }
  360. });
  361. /* jshint ignore:start */
  362. testUtils.render(
  363. <Root user={user}
  364. username-history={[]} />
  365. );
  366. /* jshint ignore:end */
  367. testUtils.onElement('#test-mount .username-history.ui-ready', function() {
  368. assert.ok(true, "root component renders");
  369. done();
  370. });
  371. });
  372. it("renders with no changes left", function(done) {
  373. $.mockjax({
  374. url: user.api_url.username,
  375. status: 200,
  376. responseText: {
  377. changes_left: 0,
  378. length_min: 3,
  379. length_max: 14,
  380. next_on: null
  381. }
  382. });
  383. $.mockjax({
  384. url: '/test-api/name-history/?user=' + user.id,
  385. status: 200,
  386. responseText: {
  387. results: []
  388. }
  389. });
  390. /* jshint ignore:start */
  391. testUtils.render(
  392. <Root user={user}
  393. username-history={[]} />
  394. );
  395. /* jshint ignore:end */
  396. testUtils.onElement('#test-mount .panel-message-body', function() {
  397. assert.ok(true, "root component renders");
  398. assert.equal($('#test-mount .help-block').text().trim(),
  399. "You have used up available name changes.",
  400. "valid help text is displayed in message");
  401. done();
  402. });
  403. });
  404. it("handles username change", function(done) {
  405. $.mockjax({
  406. url: user.api_url.username,
  407. status: 200,
  408. type: 'GET',
  409. responseText: {
  410. changes_left: 2,
  411. length_min: 3,
  412. length_max: 14,
  413. next_on: null
  414. }
  415. });
  416. $.mockjax({
  417. url: user.api_url.username,
  418. status: 200,
  419. type: 'POST',
  420. responseText: {
  421. username: 'Newt',
  422. slug: 'newt',
  423. options: {
  424. changes_left: 2,
  425. length_min: 3,
  426. length_max: 14,
  427. next_on: null
  428. }
  429. }
  430. });
  431. $.mockjax({
  432. url: '/test-api/name-history/?user=' + user.id,
  433. status: 200,
  434. responseText: {
  435. results: []
  436. }
  437. });
  438. /* jshint ignore:start */
  439. testUtils.render(
  440. <Root user={user}
  441. username-history={[]} />
  442. );
  443. /* jshint ignore:end */
  444. snackbarStore.callback(function(message) {
  445. assert.deepEqual(message, {
  446. message: "Your username has been changed successfully.",
  447. type: 'success'
  448. }, "error message was shown");
  449. done();
  450. });
  451. testUtils.onElement('#test-mount form #id_username', function() {
  452. testUtils.simulateChange('#test-mount form #id_username', 'newt');
  453. testUtils.simulateSubmit('#test-mount form');
  454. });
  455. });
  456. });