change-username.js 13 KB

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