Reputation: 1925
I have a flask app based on the tutorial here https://flask.palletsprojects.com/en/stable/tutorial/. The tutorial comes with a test suite but having adapted the app to use WTForms the tests that post form data stopped working. I can see that's because none of the forms validate as they don't include a CSRF token. How can I add the token to the post data being sent? I came across this rather old gist showing how to do it but it appears to be out of date for the version of Werkzeug I'm using, as it refers to self.cookie_jar
which has been removed -- https://gist.github.com/singingwolfboy/2fca1de64950d5dfed72.
I'm using Flask==3.1.0 flask_wtf==1.2.2 pytest==8.3.4 selenium==4.29.0 Werkzeug==3.1.3 WTForms==3.2.1
tests/conftest.py
import os
import tempfile
import pytest
from flaskr import create_app
from flaskr.db import get_db, init_db
with open(os.path.join(os.path.dirname(__file__), 'data.sql'), 'rb') as f:
_data_sql = f.read().decode('utf8')
@pytest.fixture
def app():
db_fd, db_path = tempfile.mkstemp()
app = create_app({
'TESTING': True,
'DATABASE': db_path,
})
with app.app_context():
init_db()
get_db().executescript(_data_sql)
yield app
os.close(db_fd)
os.unlink(db_path)
@pytest.fixture
def client(app):
return app.test_client()
@pytest.fixture
def runner(app):
return app.test_cli_runner()
tests/test_auth.py
import pytest
from flask import g, session
from flaskr.db import get_db
def test_register(client, app):
assert client.get('/auth/register').status_code == 200
response = client.post_csrf(
'/auth/register', data={'username': 'a', 'password': 'a'}
, follow_redirects=True)
print(f'{response.status=}')
print(f'{response.response=}')
for x in response.response:
print(x)
assert response.headers["Location"] == "/auth/login"
with app.app_context():
assert get_db().execute(
"SELECT * FROM user WHERE username = 'a'",
).fetchone() is not None
Output from the test:
$ pytest tests/test_auth.py
=========================================== FAILURES
============================================
_________________________________________ test_register
_________________________________________
client = <FlaskClient <Flask 'flaskr'>>, app = <Flask 'flaskr'>
def test_register(client, app):
assert client.get('/auth/register').status_code == 200
response = client.post(
'/auth/register', data={'username': 'a', 'password': 'a'}
, follow_redirects=True)
print(f'{response.status=}')
print(f'{response.response=}')
for x in response.response:
print(x)
> assert response.headers["Location"] == "/auth/login"
tests/test_auth.py:15:
_ _ _ _ _ _ _ _ _ _ _ _ _ _
venv/lib/python3.11/site-
packages/werkzeug/datastructures/headers.py:83: in __getitem__
return self._get_key(key)
_ _ _ _ _ _ _ _ _ _ _ _ _
self = Headers([('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', '960'), ('Vary', 'Cookie')])
key = 'Location'
def _get_key(self, key: str) -> str:
ikey = key.lower()
for k, v in self._list:
if k.lower() == ikey:
return v
> raise BadRequestKeyError(key)
E werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
venv/lib/python3.11/site-packages/werkzeug/datastructures/headers.py:97: BadRequestKeyError
Upvotes: 0
Views: 17