captcha.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import assert from "assert";
  2. import React from 'react'; // jshint ignore:line
  3. import ajax from 'misago/services/ajax';
  4. import { NoCaptcha, QACaptcha, ReCaptcha, Captcha } from 'misago/services/captcha';
  5. import snackbar from 'misago/services/snackbar';
  6. import * as testUtils from 'misago/utils/test-utils';
  7. let captcha = null;
  8. let snackbarStore = null;
  9. describe("NoCaptcha", function() {
  10. it("always loads instantly", function(done) {
  11. captcha = new NoCaptcha();
  12. captcha.init({}, {}, {}, {});
  13. captcha.load().then(function() {
  14. assert.ok(true, "service loaded immediately");
  15. done();
  16. });
  17. });
  18. it("has no validator", function() {
  19. captcha = new NoCaptcha();
  20. assert.equal(captcha.validator(), null, "nocaptcha has no validator");
  21. });
  22. it("has no component", function() {
  23. captcha = new NoCaptcha();
  24. assert.equal(captcha.component(), null, "nocaptcha has no component");
  25. });
  26. });
  27. describe("QACaptcha", function() {
  28. beforeEach(function() {
  29. snackbarStore = testUtils.snackbarStoreMock();
  30. snackbar.init(snackbarStore);
  31. });
  32. afterEach(function() {
  33. testUtils.unmountComponents();
  34. testUtils.snackbarClear(snackbar);
  35. $.mockjax.clear();
  36. });
  37. it("handles successful load", function(done) {
  38. $.mockjax({
  39. url: '/test-api/captcha/',
  40. status: 200,
  41. responseText: {
  42. 'question': "Test question",
  43. 'help_text': "This is test quesiton for tests"
  44. }
  45. });
  46. captcha = new QACaptcha();
  47. captcha.init({
  48. get: function(setting) {
  49. assert.equal(setting, 'CAPTCHA_API', "valid setting is used");
  50. return '/test-api/captcha/';
  51. }
  52. }, ajax, {}, {});
  53. captcha.load().then(function() {
  54. assert.equal(captcha.question, "Test question", "question was loaded");
  55. assert.equal(captcha.helpText, "This is test quesiton for tests",
  56. "question's help text was loaded");
  57. done();
  58. });
  59. });
  60. it("handles failed load", function(done) {
  61. $.mockjax({
  62. url: '/test-api/captcha/',
  63. status: 400,
  64. responseText: {
  65. 'question': "Test question",
  66. 'help_text': "This is test quesiton for tests"
  67. }
  68. });
  69. snackbarStore.callback(function(message) {
  70. assert.deepEqual(message, {
  71. message: "Failed to load CAPTCHA.",
  72. type: 'error'
  73. }, "question failed to load from API");
  74. done();
  75. });
  76. captcha = new QACaptcha();
  77. captcha.init({
  78. get: function(setting) {
  79. assert.equal(setting, 'CAPTCHA_API', "valid setting is used");
  80. return '/test-api/captcha/';
  81. }
  82. }, ajax, {}, snackbar);
  83. captcha.load().then(function() {
  84. assert.ok(false, "captcha should fail to load");
  85. }, function() {
  86. assert.ok(true, "captcha failed to load");
  87. });
  88. });
  89. it("is required", function() {
  90. captcha = new QACaptcha();
  91. assert.deepEqual(captcha.validator(), [], "qa-captcha is required");
  92. });
  93. it("renders component", function(done) {
  94. $.mockjax({
  95. url: '/test-api/captcha/',
  96. status: 200,
  97. responseText: {
  98. 'question': "Test question",
  99. 'help_text': "This is test quesiton for tests"
  100. }
  101. });
  102. captcha = new QACaptcha();
  103. captcha.init({
  104. get: function(setting) {
  105. assert.equal(setting, 'CAPTCHA_API', "valid setting is used");
  106. return '/test-api/captcha/';
  107. }
  108. }, ajax, {}, {});
  109. captcha.load().then(function() {
  110. /* jshint ignore:start */
  111. testUtils.render(
  112. <div>
  113. {captcha.component({
  114. form: {
  115. state: {
  116. errors: {},
  117. isLoading: false,
  118. captcha: ''
  119. },
  120. bindInput: function(field) {
  121. assert.equal(field, 'captcha', "captcha is bound to state");
  122. return function() {
  123. /* noop */
  124. };
  125. }
  126. }
  127. })}
  128. </div>
  129. );
  130. /* jshint ignore:end */
  131. let element = $('#test-mount');
  132. assert.ok(element.length, "component renders");
  133. assert.equal(element.find('label').text().trim(), "Test question:",
  134. "label contains test question");
  135. assert.equal(element.find('p.help-block').text().trim(),
  136. "This is test quesiton for tests",
  137. "question's help text is displayed");
  138. done();
  139. });
  140. });
  141. });
  142. describe("ReCaptcha", function() {
  143. afterEach(function() {
  144. delete window.grecaptcha;
  145. testUtils.unmountComponents();
  146. testUtils.snackbarClear(snackbar);
  147. $.mockjax.clear();
  148. });
  149. it("loads library", function(done) {
  150. captcha = new ReCaptcha();
  151. captcha.init({
  152. get: function(setting) {
  153. assert.equal(setting, 'SETTINGS', "settings object is accessed");
  154. return {
  155. recaptcha_site_key: 'aabbcc'
  156. };
  157. }
  158. }, {}, {
  159. include: function(url) {
  160. assert.ok(url, "library is requested from google servers");
  161. }
  162. }, {});
  163. captcha.load().then(function() {
  164. assert.ok('promise resolves');
  165. done();
  166. });
  167. window.setTimeout(function() {
  168. window.grecaptcha = {};
  169. }, 100);captcha = new ReCaptcha();
  170. });
  171. it("is required", function() {
  172. captcha = new ReCaptcha();
  173. assert.deepEqual(captcha.validator(), [], "recaptcha is required");
  174. });
  175. it("renders component", function(done) { // jshint ignore:line
  176. captcha = new ReCaptcha();
  177. captcha.init({
  178. get: function(setting) {
  179. assert.equal(setting, 'SETTINGS', "settings object is accessed");
  180. return {
  181. recaptcha_site_key: 'aabbcc'
  182. };
  183. }
  184. }, {}, {
  185. include: function(url) {
  186. assert.ok(url, "library is requested from google servers");
  187. }
  188. }, {});
  189. captcha.load().then(function() {
  190. /* jshint ignore:start */
  191. testUtils.render(
  192. <div>
  193. {captcha.component({
  194. form: {
  195. state: {
  196. errors: {},
  197. captcha: ''
  198. },
  199. bindInput: function() {
  200. return function(value) {
  201. assert.deepEqual(value, {
  202. target: {
  203. value: 'valid-captcha'
  204. }
  205. }, "captcha is called");
  206. done();
  207. };
  208. }
  209. }
  210. })}
  211. </div>
  212. );
  213. /* jshint ignore:end */
  214. let element = $('#test-mount');
  215. assert.ok(element.length, "component renders");
  216. assert.equal(element.find('label').text().trim(), "Captcha:",
  217. "label is valid");
  218. assert.equal(element.find('p.help-block').text().trim(),
  219. "Please solve the quick test.",
  220. "field's help text is displayed");
  221. });
  222. window.setTimeout(function() {
  223. window.grecaptcha = {
  224. render: function(field, options) {
  225. assert.equal(field, 'recaptcha', "component is rendered in outlet");
  226. assert.equal(options.sitekey, 'aabbcc', "sitekey is passed to api");
  227. window.setTimeout(function() {
  228. options.callback('valid-captcha');
  229. }, 100);
  230. }
  231. };
  232. }, 100);
  233. });
  234. });
  235. describe("Captcha", function() {
  236. it("delegates load calls", function(done) {
  237. let captcha = new Captcha();
  238. captcha._captcha = {
  239. load: function() {
  240. assert.ok(true, "load call was delegated to strategy");
  241. done();
  242. }
  243. };
  244. captcha.load();
  245. });
  246. it("delegates validator calls", function(done) {
  247. let captcha = new Captcha();
  248. captcha._captcha = {
  249. validator: function() {
  250. assert.ok(true, "validator call was delegated to strategy");
  251. done();
  252. }
  253. };
  254. captcha.validator();
  255. });
  256. it("delegates component calls", function(done) {
  257. let captcha = new Captcha();
  258. captcha._captcha = {
  259. component: function() {
  260. assert.ok(true, "component call was delegated to strategy");
  261. done();
  262. }
  263. };
  264. captcha.component();
  265. });
  266. });