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

Last change on this file was 15012, checked in by uli, 7 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
RevLine 
[7282]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##
[7291]18import grok
[7285]19from zope.component import getAdapter, getUtility
[7291]20from zope.component.hooks import setSite, clearSite
[7282]21from zope.interface import verify
22from zope.publisher.browser import TestRequest
[7811]23from waeup.kofa.testing import FunctionalLayer, FunctionalTestCase
24from waeup.kofa.browser.captcha import (
[7302]25    CaptchaResponse, CaptchaRequest, NullCaptcha, StaticCaptcha, ReCaptcha,
[7307]26    CaptchaManager)
[7811]27from waeup.kofa.browser.interfaces import (
[7308]28    ICaptchaRequest, ICaptchaResponse, ICaptcha, ICaptchaConfig,
29    ICaptchaManager)
[7282]30
[7308]31
[7282]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
[7294]68class CaptchaTestBase(object):
[7282]69
70    def test_ifaces(self):
71        # make sure we implement the promised interfaces
[7294]72        obj = self.factory()
73        verify.verifyClass(ICaptcha, self.factory)
[7282]74        verify.verifyObject(ICaptcha, obj)
75        return
76
[7294]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
[7282]90    def test_verify(self):
91        # null captchas accept any input request
[7294]92        captcha = self.factory()
[7298]93        result1 = captcha.verify(TestRequest())
94        result2 = captcha.verify(
95            TestRequest(form={'solution': 'a', 'challenge': 'b'}))
[7282]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
[7294]102        captcha = self.factory()
[7282]103        result = captcha.display()
104        self.assertEqual(result, u'')
105        return
106
[7301]107class StaticCaptchaTests(FunctionalTestCase, CaptchaTestBase):
[7285]108
[7294]109    layer = FunctionalLayer
110
[7301]111    factory = StaticCaptcha
[7295]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()
[7298]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)
[7295]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 />'
[7301]141            '<input type="text" name="solution" value="the-solution" /><br />',
[7295]142            result)
143        return
144
[7302]145class ReCaptchaTests(FunctionalTestCase, CaptchaTestBase):
[7295]146
[7302]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(
[15012]173            '<script type="text/javascript" '
174            'src="..." async defer></script>'
175            '<div class="g-recaptcha" data-sitekey="..."></div>',
[7302]176            result)
177        return
178
[7307]179class CaptchaManagerTests(FunctionalTestCase):
[7291]180    # These tests do not require a site setup
[7294]181    # See testsuite below for insite tests.
[7285]182
183    layer = FunctionalLayer
184
185    def test_ifaces(self):
186        # make sure we implement the promised interfaces
[7307]187        obj = CaptchaManager()
188        verify.verifyClass(ICaptchaManager, CaptchaManager)
189        verify.verifyObject(ICaptchaManager, obj)
[7285]190        return
191
192    def test_utility(self):
193        # the global captcha chooser is registered as a global utility
[7307]194        result = getUtility(ICaptchaManager)
195        self.assertTrue(isinstance(result, CaptchaManager))
[7285]196        return
197
198    def test_get_avail_captchas(self):
199        # we can get a dict of available captchas.
[7307]200        chooser = getUtility(ICaptchaManager)
[7285]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
[7286]207
208    def test_get_captcha_wo_site(self):
209        # if there is no site set, we get the default captcha
210        setSite(None)
[7307]211        chooser = getUtility(ICaptchaManager)
[7286]212        result = chooser.getCaptcha()
213        default = getUtility(ICaptcha)
214        self.assertTrue(result is default)
215        return
[7291]216
217class FakeSite(grok.Site, grok.Container):
218    pass
219
[7312]220class FakeConfiguration(object):
221    captcha = None
222
223    def __init__(self, captcha=None):
224        self.captcha = captcha
225
[7307]226class CaptchaManagerTestsWithSite(FunctionalTestCase):
[7291]227
228    layer = FunctionalLayer
229
230    def setUp(self):
[7307]231        super(CaptchaManagerTestsWithSite, self).setUp()
[7291]232        self.getRootFolder()['app'] = FakeSite()
233        self.site = self.getRootFolder()['app']
234        return
235
236    def tearDown(self):
[7307]237        super(CaptchaManagerTestsWithSite, self).tearDown()
[7291]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)
[7307]245        chooser = getUtility(ICaptchaManager)
[7291]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()
[7307]256        chooser = getUtility(ICaptchaManager)
[7291]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)
[7312]266        self.site['configuration'] = FakeConfiguration(captcha='invalid name')
[7307]267        chooser = getUtility(ICaptchaManager)
[7291]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)
[7312]277        self.site['configuration'] = FakeConfiguration(captcha='No captcha')
[7307]278        chooser = getUtility(ICaptchaManager)
[7291]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.