captcha.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. import assert from "assert";
  2. import React from 'react'; // jshint ignore:line
  3. import ReactDOM from 'react-dom'; // jshint ignore:line
  4. import ajax from 'misago/services/ajax';
  5. import { NoCaptcha, QACaptcha, ReCaptcha, Captcha } from 'misago/services/captcha';
  6. import snackbar from 'misago/services/snackbar';
  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 = window.snackbarStoreMock();
  30. snackbar.init(snackbarStore);
  31. });
  32. afterEach(function() {
  33. window.emptyTestContainers();
  34. window.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_URL', "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_URL', "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_URL', "valid setting is used");
  106. return '/test-api/captcha/';
  107. }
  108. }, ajax, {}, {});
  109. captcha.load().then(function() {
  110. /* jshint ignore:start */
  111. ReactDOM.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. document.getElementById('test-mount')
  130. );
  131. /* jshint ignore:end */
  132. let element = $('#test-mount');
  133. assert.ok(element.length, "component renders");
  134. assert.equal(element.find('label').text().trim(), "Test question:",
  135. "label contains test question");
  136. assert.equal(element.find('p.help-block').text().trim(),
  137. "This is test quesiton for tests",
  138. "question's help text is displayed");
  139. done();
  140. });
  141. });
  142. });
  143. describe("ReCaptcha", function() {
  144. afterEach(function() {
  145. delete window.grecaptcha;
  146. window.emptyTestContainers();
  147. window.snackbarClear(snackbar);
  148. $.mockjax.clear();
  149. });
  150. it("loads library", function(done) {
  151. captcha = new ReCaptcha();
  152. captcha.init({
  153. get: function(setting) {
  154. assert.equal(setting, 'SETTINGS', "settings object is accessed");
  155. return {
  156. recaptcha_site_key: 'aabbcc'
  157. };
  158. }
  159. }, {}, {
  160. include: function(url) {
  161. assert.ok(url, "library is requested from google servers");
  162. }
  163. }, {});
  164. captcha.load().then(function() {
  165. assert.ok('promise resolves');
  166. done();
  167. });
  168. window.setTimeout(function() {
  169. window.grecaptcha = {};
  170. }, 100);captcha = new ReCaptcha();
  171. });
  172. it("is required", function() {
  173. captcha = new ReCaptcha();
  174. assert.deepEqual(captcha.validator(), [], "recaptcha is required");
  175. });
  176. it("renders component", function(done) {
  177. captcha = new ReCaptcha();
  178. captcha.init({
  179. get: function(setting) {
  180. assert.equal(setting, 'SETTINGS', "settings object is accessed");
  181. return {
  182. recaptcha_site_key: 'aabbcc'
  183. };
  184. }
  185. }, {}, {
  186. include: function(url) {
  187. assert.ok(url, "library is requested from google servers");
  188. }
  189. }, {});
  190. captcha.load().then(function() {
  191. /* jshint ignore:start */
  192. ReactDOM.render(
  193. <div>
  194. {captcha.component({
  195. form: {
  196. state: {
  197. errors: {},
  198. captcha: ''
  199. },
  200. bindInput: function() {
  201. return function(value) {
  202. assert.deepEqual(value, {
  203. target: {
  204. value: 'valid-captcha'
  205. }
  206. }, "captcha is called");
  207. done();
  208. };
  209. }
  210. }
  211. })}
  212. </div>,
  213. document.getElementById('test-mount')
  214. );
  215. /* jshint ignore:end */
  216. let element = $('#test-mount');
  217. assert.ok(element.length, "component renders");
  218. assert.equal(element.find('label').text().trim(), "Captcha:",
  219. "label is valid");
  220. assert.equal(element.find('p.help-block').text().trim(),
  221. "Please solve the quick test.",
  222. "field's help text is displayed");
  223. });
  224. window.setTimeout(function() {
  225. window.grecaptcha = {
  226. render: function(field, options) {
  227. assert.equal(field, 'recaptcha', "component is rendered in outlet");
  228. assert.equal(options.sitekey, 'aabbcc', "sitekey is passed to api");
  229. window.setTimeout(function() {
  230. options.callback('valid-captcha');
  231. }, 100);
  232. }
  233. };
  234. }, 100);
  235. });
  236. });
  237. describe("Captcha", function() {
  238. it("delegates load calls", function(done) {
  239. let captcha = new Captcha();
  240. captcha._captcha = {
  241. load: function() {
  242. assert.ok(true, "load call was delegated to strategy");
  243. done();
  244. }
  245. };
  246. captcha.load();
  247. });
  248. it("delegates validator calls", function(done) {
  249. let captcha = new Captcha();
  250. captcha._captcha = {
  251. validator: function() {
  252. assert.ok(true, "validator call was delegated to strategy");
  253. done();
  254. }
  255. };
  256. captcha.validator();
  257. });
  258. it("delegates component calls", function(done) {
  259. let captcha = new Captcha();
  260. captcha._captcha = {
  261. component: function() {
  262. assert.ok(true, "component call was delegated to strategy");
  263. done();
  264. }
  265. };
  266. captcha.component();
  267. });
  268. });