1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
import pytest
from flask import json
from markupsafe import Markup
from flask_wtf import FlaskForm
from flask_wtf.recaptcha import RecaptchaField
from flask_wtf.recaptcha.validators import http
from flask_wtf.recaptcha.validators import Recaptcha
class RecaptchaForm(FlaskForm):
class Meta:
csrf = False
recaptcha = RecaptchaField()
@pytest.fixture
def app(app):
app.testing = False
app.config["PROPAGATE_EXCEPTIONS"] = True
app.config["RECAPTCHA_PUBLIC_KEY"] = "public"
app.config["RECAPTCHA_PRIVATE_KEY"] = "private"
return app
@pytest.fixture(autouse=True)
def req_ctx(app):
with app.test_request_context(data={"g-recaptcha-response": "pass"}) as ctx:
yield ctx
def test_config(app, monkeypatch):
f = RecaptchaForm()
monkeypatch.setattr(app, "testing", True)
f.validate()
assert not f.recaptcha.errors
monkeypatch.undo()
monkeypatch.delitem(app.config, "RECAPTCHA_PUBLIC_KEY")
pytest.raises(RuntimeError, f.recaptcha)
monkeypatch.undo()
monkeypatch.delitem(app.config, "RECAPTCHA_PRIVATE_KEY")
pytest.raises(RuntimeError, f.validate)
def test_render_has_js():
f = RecaptchaForm()
render = f.recaptcha()
assert "https://www.google.com/recaptcha/api.js" in render
def test_render_has_custom_js(app):
captcha_script = "https://hcaptcha.com/1/api.js"
app.config["RECAPTCHA_SCRIPT"] = captcha_script
f = RecaptchaForm()
render = f.recaptcha()
assert captcha_script in render
def test_render_custom_html(app):
app.config["RECAPTCHA_HTML"] = "custom"
f = RecaptchaForm()
render = f.recaptcha()
assert render == "custom"
assert isinstance(render, Markup)
def test_render_custom_div_class(app):
div_class = "h-captcha"
app.config["RECAPTCHA_DIV_CLASS"] = div_class
f = RecaptchaForm()
render = f.recaptcha()
assert div_class in render
def test_render_custom_args(app):
app.config["RECAPTCHA_PARAMETERS"] = {"key": "(value)"}
app.config["RECAPTCHA_DATA_ATTRS"] = {"red": "blue"}
f = RecaptchaForm()
render = f.recaptcha()
assert "?key=(value)" in render or "?key=%28value%29" in render
assert 'data-red="blue"' in render
def test_missing_response(app):
with app.test_request_context():
f = RecaptchaForm()
f.validate()
assert f.recaptcha.errors[0] == "The response parameter is missing."
class MockResponse:
def __init__(self, code, error="invalid-input-response", read_bytes=False):
self.code = code
self.data = json.dumps(
{"success": not error, "error-codes": [error] if error else []}
)
self.read_bytes = read_bytes
def read(self):
if self.read_bytes:
return self.data.encode("utf-8")
return self.data
def test_send_invalid_request(monkeypatch):
def mock_urlopen(url, data):
return MockResponse(200)
monkeypatch.setattr(http, "urlopen", mock_urlopen)
f = RecaptchaForm()
f.validate()
assert f.recaptcha.errors[0] == ("The response parameter is invalid or malformed.")
def test_response_from_json(app, monkeypatch):
def mock_urlopen(url, data):
return MockResponse(200)
monkeypatch.setattr(http, "urlopen", mock_urlopen)
with app.test_request_context(
data=json.dumps({"g-recaptcha-response": "pass"}),
content_type="application/json",
):
f = RecaptchaForm()
f.validate()
assert f.recaptcha.errors[0] != "The response parameter is missing."
def test_request_fail(monkeypatch):
def mock_urlopen(url, data):
return MockResponse(400)
monkeypatch.setattr(http, "urlopen", mock_urlopen)
f = RecaptchaForm()
f.validate()
assert f.recaptcha.errors
def test_request_success(monkeypatch):
def mock_urlopen(url, data):
return MockResponse(200, "")
monkeypatch.setattr(http, "urlopen", mock_urlopen)
f = RecaptchaForm()
f.validate()
assert not f.recaptcha.errors
def test_request_custom_verify_server(app, monkeypatch):
verify_server = "https://hcaptcha.com/siteverify"
def mock_urlopen(url, data):
assert url == verify_server
return MockResponse(200, "")
monkeypatch.setattr(http, "urlopen", mock_urlopen)
app.config["RECAPTCHA_VERIFY_SERVER"] = verify_server
f = RecaptchaForm()
f.validate()
assert not f.recaptcha.errors
def test_request_unmatched_error(monkeypatch):
def mock_urlopen(url, data):
return MockResponse(200, "not-an-error", True)
monkeypatch.setattr(http, "urlopen", mock_urlopen)
f = RecaptchaForm()
f.recaptcha.validators = [Recaptcha("custom")]
f.validate()
assert f.recaptcha.errors[0] == "custom"
|