source: main/waeup.kofa/trunk/src/waeup/kofa/browser/tests/test_captcha.py

Last change on this file was 15012, checked in by uli, 6 years ago

Use the 'new' recaptcha v2.

The old one was turned off in March.

  • Property svn:keywords set to Id
File size: 9.8 KB
Line 
1## $Id: test_captcha.py 15012 2018-05-19 21:47:54Z uli $
2##
3## Copyright (C) 2011 Uli Fouquet
4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
8##
9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
13##
14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import grok
19from zope.component import getAdapter, getUtility
20from zope.component.hooks import setSite, clearSite
21from zope.interface import verify
22from zope.publisher.browser import TestRequest
23from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
24from waeup.kofa.browser.captcha import (
25    CaptchaResponse, CaptchaRequest, NullCaptcha, StaticCaptcha, ReCaptcha,
26    CaptchaManager)
27from waeup.kofa.browser.interfaces import (
28    ICaptchaRequest, ICaptchaResponse, ICaptcha, ICaptchaConfig,
29    ICaptchaManager)
30
31
32class CaptchaResponseTests(FunctionalTestCase):
33
34    layer = FunctionalLayer
35
36    def test_ifaces(self):
37        # make sure we implement the promised interfaces
38        obj = CaptchaResponse(True)
39        verify.verifyClass(ICaptchaResponse, CaptchaResponse)
40        verify.verifyObject(ICaptchaResponse, obj)
41        return
42
43    def test_init_vals(self):
44        # make sure the initial values are stored
45        resp = CaptchaResponse(False, 'some-msg')
46        self.assertEqual(resp.is_valid, False)
47        self.assertEqual(resp.error_code, 'some-msg')
48        return
49
50class CaptchaRequestTests(FunctionalTestCase):
51
52    layer = FunctionalLayer
53
54    def test_ifaces(self):
55        # make sure we implement the promised interfces
56        obj = CaptchaRequest(None)
57        verify.verifyClass(ICaptchaRequest, CaptchaRequest)
58        verify.verifyObject(ICaptchaRequest, obj)
59        return
60
61    def test_init_vals(self):
62        # make sure initial values are stored
63        req = CaptchaRequest('my-solution', 'my-challenge')
64        self.assertEqual(req.solution, 'my-solution')
65        self.assertEqual(req.challenge, 'my-challenge')
66        return
67
68class CaptchaTestBase(object):
69
70    def test_ifaces(self):
71        # make sure we implement the promised interfaces
72        obj = self.factory()
73        verify.verifyClass(ICaptcha, self.factory)
74        verify.verifyObject(ICaptcha, obj)
75        return
76
77    def test_utility(self):
78        # the null captcha is also registered as a utility for ICaptcha
79        captcha = getUtility(ICaptcha, name=self.name)
80        self.assertTrue(isinstance(captcha, self.factory))
81        return
82
83class NullCaptchaTests(FunctionalTestCase, CaptchaTestBase):
84
85    layer = FunctionalLayer
86
87    factory = NullCaptcha
88    name = 'No captcha'
89
90    def test_verify(self):
91        # null captchas accept any input request
92        captcha = self.factory()
93        result1 = captcha.verify(TestRequest())
94        result2 = captcha.verify(
95            TestRequest(form={'solution': 'a', 'challenge': 'b'}))
96        self.assertEqual(result1.is_valid, True)
97        self.assertEqual(result2.is_valid, True)
98        return
99
100    def test_display(self):
101        # null captchas do not generate additional HTML code
102        captcha = self.factory()
103        result = captcha.display()
104        self.assertEqual(result, u'')
105        return
106
107class StaticCaptchaTests(FunctionalTestCase, CaptchaTestBase):
108
109    layer = FunctionalLayer
110
111    factory = StaticCaptcha
112    name = 'Testing captcha'
113
114    def test_verify(self):
115        # id captchas accept any solution that matches challenge and
116        # is not empty or None
117        captcha = self.factory()
118        request1 = TestRequest(form={'solution': 'my-sol',
119                                     'challenge': 'my-challenge'})
120        request2 = TestRequest()
121        request3 = TestRequest(form={'solution': '', 'challenge': ''})
122        request4 = TestRequest(form={'solution': 'my-sol',
123                                     'challenge': 'my-sol'})
124        result1 = captcha.verify(request1)
125        result2 = captcha.verify(request2)
126        result3 = captcha.verify(request3)
127        result4 = captcha.verify(request4)
128        self.assertEqual(result1.is_valid, False)
129        self.assertEqual(result2.is_valid, False)
130        self.assertEqual(result3.is_valid, False)
131        self.assertEqual(result4.is_valid, True)
132        return
133
134    def test_display(self):
135        # id captchas provide a simple HTML input
136        captcha = self.factory()
137        result = captcha.display()
138        self.assertMatches(
139            '<input type="hidden" name="challenge"'
140            '      value="..." /><br />Type: ...<br />'
141            '<input type="text" name="solution" value="the-solution" /><br />',
142            result)
143        return
144
145class ReCaptchaTests(FunctionalTestCase, CaptchaTestBase):
146
147    layer = FunctionalLayer
148
149    factory = ReCaptcha
150    name = 'ReCaptcha'
151
152    def DISABLEDtest_verify(self):
153        # recaptcha verification cannot be tested easily. As the
154        # solution and other environment parameters is only known to
155        # the remote server, we cannot guess on server side what the
156        # solution is.  Further more this test contacts a remote
157        # server so that we might want to disable this test by
158        # default.
159        captcha = self.factory()
160        request1 = TestRequest(
161            form={'recaptcha_challenge_field': 'my-challenge',
162                  'recaptcha_response_field': 'my-solution'})
163        result1 = captcha.verify(request1)
164        self.assertEqual(result1.is_valid, False)
165        self.assertEqual(result1.error_code, 'invalid-request-cookie')
166        return
167
168    def test_display(self):
169        # recaptchas provide the pieces to trigger the remote API
170        captcha = self.factory()
171        result = captcha.display()
172        self.assertMatches(
173            '<script type="text/javascript" '
174            'src="..." async defer></script>'
175            '<div class="g-recaptcha" data-sitekey="..."></div>',
176            result)
177        return
178
179class CaptchaManagerTests(FunctionalTestCase):
180    # These tests do not require a site setup
181    # See testsuite below for insite tests.
182
183    layer = FunctionalLayer
184
185    def test_ifaces(self):
186        # make sure we implement the promised interfaces
187        obj = CaptchaManager()
188        verify.verifyClass(ICaptchaManager, CaptchaManager)
189        verify.verifyObject(ICaptchaManager, obj)
190        return
191
192    def test_utility(self):
193        # the global captcha chooser is registered as a global utility
194        result = getUtility(ICaptchaManager)
195        self.assertTrue(isinstance(result, CaptchaManager))
196        return
197
198    def test_get_avail_captchas(self):
199        # we can get a dict of available captchas.
200        chooser = getUtility(ICaptchaManager)
201        result = dict(chooser.getAvailCaptchas())
202        no_captcha = result.get('No captcha', None)
203        self.assertTrue(no_captcha is not None)
204        default_captcha = result.get(u'', None)
205        self.assertTrue(default_captcha is None)
206        return
207
208    def test_get_captcha_wo_site(self):
209        # if there is no site set, we get the default captcha
210        setSite(None)
211        chooser = getUtility(ICaptchaManager)
212        result = chooser.getCaptcha()
213        default = getUtility(ICaptcha)
214        self.assertTrue(result is default)
215        return
216
217class FakeSite(grok.Site, grok.Container):
218    pass
219
220class FakeConfiguration(object):
221    captcha = None
222
223    def __init__(self, captcha=None):
224        self.captcha = captcha
225
226class CaptchaManagerTestsWithSite(FunctionalTestCase):
227
228    layer = FunctionalLayer
229
230    def setUp(self):
231        super(CaptchaManagerTestsWithSite, self).setUp()
232        self.getRootFolder()['app'] = FakeSite()
233        self.site = self.getRootFolder()['app']
234        return
235
236    def tearDown(self):
237        super(CaptchaManagerTestsWithSite, self).tearDown()
238        clearSite(self.site)
239        return
240
241    def test_get_captcha_no_captcha_in_config(self):
242        # if a site has no configuration setting for captchas, we get
243        # the default captcha
244        setSite(self.site)
245        chooser = getUtility(ICaptchaManager)
246        result = chooser.getCaptcha()
247        default = getUtility(ICaptcha)
248        self.assertTrue(result is default)
249        return
250
251    def test_get_captcha_empty_captcha_in_config(self):
252        # if a site has None as configuration setting for captchas, we get
253        # the default captcha
254        setSite(self.site)
255        self.site['configuration'] = dict()
256        chooser = getUtility(ICaptchaManager)
257        result = chooser.getCaptcha()
258        default = getUtility(ICaptcha)
259        self.assertTrue(result is default)
260        return
261
262    def test_get_captcha_invalid_captcha_in_config(self):
263        # if a site has None as configuration setting for captchas, we get
264        # the default captcha
265        setSite(self.site)
266        self.site['configuration'] = FakeConfiguration(captcha='invalid name')
267        chooser = getUtility(ICaptchaManager)
268        result = chooser.getCaptcha()
269        default = getUtility(ICaptcha)
270        self.assertTrue(result is default)
271        return
272
273    def test_get_captcha_invalid_captcha_in_config(self):
274        # if a site has None as configuration setting for captchas, we get
275        # the default captcha
276        setSite(self.site)
277        self.site['configuration'] = FakeConfiguration(captcha='No captcha')
278        chooser = getUtility(ICaptchaManager)
279        result = chooser.getCaptcha()
280        no_captcha = getUtility(ICaptcha, name='No captcha')
281        default = getUtility(ICaptcha)
282        self.assertTrue(result is not default)
283        self.assertTrue(result is no_captcha)
284        return
Note: See TracBrowser for help on using the repository browser.