Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Test for URL Params in Flask Redirect

On Successfully POSTing to a form endpoint I redirect back to the same endpoint with some URL params that my client side code can interact with.

@bp.route('/submit', methods=['GET', 'POST'])
def submit():
    form = SubmissionForm()
    labels = current_app.config['TRELLO_LABELS']

    if form.validate_on_submit():

        submission = Submission().create(
            title=form.data['title'], email=form.data['email'], card_id=card.id, card_url=card.url)

        # reset form by redirecting back and setting the URL params
        return redirect(url_for('bp.submit', success=1, id=card.id))

    return render_template('submit.html', form=form)

But I ran into some issues trying to write a test for this code as I can't figure out how to test that those URL params are on my redirect URL. My incomplete test code is:

import pytest

@pytest.mark.usefixtures('session')
class TestRoutes:

    def test_submit_post(self, app, mocker):
        with app.test_request_context('/submit',
            method='post',
            query_string=dict(
                email='[email protected]',
                title='foo',
                pitch='foo',
                format='IN-DEPTH',
                audience='INTERMEDIATE',
                description='foo',
                notes='foo')):
            assert resp.status_code == 200

I've tried a few different methods to test this. With and without the context manager and I've dug deep into the Flask and Werkzeug source on the test_client and test_request_context.

I just want to test that the URL params for success and id exist on redirect after a valid POST.

like image 591
frankV Avatar asked Oct 18 '22 00:10

frankV


1 Answers

Here's a super simple yet inclusive example of patching Flask's url_for method (can be run as-is in a Python interpreter):

import flask
from unittest.mock import patch

@patch('flask.url_for')
def test(self):
    resp = flask.url_for('spam')
    self.assert_called_with('spam')


However, the above example will only work if you're importing Flask directly and not using from flask import url_for in your routes code. You'll have to patch the exact namespace, which would look something like this:

@patch('application.routes.url_for')
def another_test(self, client):
    # Some code that envokes Flask's url_for, such as:
    client.post('/submit', data={}, follow_redirects=True)

    self.assert_called_once_with('bp.submit', success=1, id=1)

For more info, check out Where to Patch in the mock documentation.

like image 171
emilyemorehouse Avatar answered Oct 22 '22 14:10

emilyemorehouse