0

So I have web app where if the user is logged in, he cannot sign up. Instead he is redirected and a message saying he cannot sign up is flashed.

The problem is I can't test it for some reason.

Here is the view

@users_template.route('/signup', methods=['GET', 'POST'])
def signup():
    form = RegisterationForm()
    if current_user.is_authenticated and current_user.is_active:  # prevent the user from seeing the register page if he's already logged in
        flash('You cannot sign up while you\'re logged in')
        return redirect(url_for('main.home'))

    if request.method == 'POST' and form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        user = User(username=username, password=password)
        if db.session.query(User).filter(User.username == username).first() is None:
            current_app.logger.info('<{}> did not register before. Registering him/her now'.format(username))
            db.session.add(user)
            db.session.commit()
            flash('Thank you for registering. Please login now')
            return redirect(url_for('users.login'))
        else:  # the user name has been registered before
            flash('You already registered')
    return render_template('signup.html', form=form)

Now in my test module I have this method

def test_signup_page_requires_logout(self):
    data_to_signup = {'username': 'mustafa1', 'password': 'mustafa1',
            'confirm_password': 'mustafa1'}
    data_to_login = {'username': 'mustafa1', 'password': 'mustafa1'}
    # with statement preserves the request context for the current_user
    with self.client:
        self.client.post('/signup', data=data_to_signup)
        self.client.post('/login', data=data_to_login)
        response = self.client.get('/signup', follow_redirects=True)
        assert b'You cannot sign up while you\'re logged in' in response.data

What's even more confusing is that this structure works for other methods

def test_headquarter_after_login(self):
    data_to_signup = {'username': 'mustafa1', 'password': 'mustafa1',
            'confirm_password': 'mustafa1'}
    data_to_login = {'username': 'mustafa1', 'password': 'mustafa1'}
    with self.client:
        self.client.post('/signup', data=data_to_signup)
        self.client.post('/login', data=data_to_login)
        response = self.client.get('/headquarter')
        assert b'Headquarter page' in response.data

EDIT: here is the login view

from .. import bcrypt
@users_template.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm(request.form)
    if form.validate_on_submit() and request.method == 'POST':
        username = form.username.data
        password = form.password.data

        user = User.query.filter(User.username == username).first()

        if user is not None and bcrypt.check_password_hash(user.password, password):  # authenticate
            login_user(user)  # then log the user in
            flash('You are logged in')
            return redirect(url_for('main.home'))

        else:
            flash('Incorrect username or password')  # if username is wrong, it will be caught by the error handling above
    return render_template('login.html', form=form)  # for a GET request

This is the error (I'm using py.test fyi)

            assert current_user.is_active() == True
            assert current_user.is_authenticated() == True
>           assert b'You cannot sign up while you\'re logged in' in response.data
E           AssertionError: assert b"You cannot sign up while you're logged in" in b'<!DOCTYPE html>\n<html lang="en">\n  <head>\n    <meta charset="utf-8">\n    <meta http-equiv="X-UA-Compatible" cont...jquery/1.12.4/jquery.min.js"></script>\n    <script src="/static/js/bootstrap.min.js"> </script>\n  </body>\n</html>\n'
E            +  where b'<!DOCTYPE html>\n<html lang="en">\n  <head>\n    <meta charset="utf-8">\n    <meta http-equiv="X-UA-Compatible" cont...jquery/1.12.4/jquery.min.js"></script>\n    <script src="/static/js/bootstrap.min.js"> </script>\n  </body>\n</html>\n' = <TestResponse 3874 bytes [200 OK]>.

This is to display the flashed messages in all my templates(It's in my "base.html" which I inherit from)

    {% if get_flashed_messages() %}
        {% for message in get_flashed_messages() %}
            <div class='container'>
                    <span class='alert alert-info'>
                        <small>{{ message }}</small>
                    </span>
            </div>
        {% endfor %}
    {% endif %}

I've made more tests using the flashed messages and it worked fine. Like this one for testing the user signup

assert b'Thank you for registering. Please login now' in response.data
MAA
  • 1,294
  • 3
  • 18
  • 34

1 Answers1

1

Suggestion no:

  1. Because of this line:

    if current_user.is_authenticated and current_user.is_active:
    

    current_user has his is_active flag set as False. If I'm not right, then please paste test error.

  2. Another clue could be lack of flash messages in home template. Put this code below in for example flashMessages.html:

    {% macro render_flashMessages() %}
        {% with messages = get_flashed_messages() %}
            {% if messages %}
            <ul class="list-unstyled">
                {% for message in messages %}
                <li><div class="alert alert-info">{{ message|safe }}</div></li>
                {% endfor %}
            </ul>
            {% endif %}
        {% endwith %}
    {% endmacro %}
    

    then you can use it in this way in home.html:

    {% from "flashMessages.html" import render_flashMessages %}
    
    {{ render_flashMessages() }}
    
  3. Next thing to check is to use assert with something else than response.data, if you're using Flask-WebTest you can try:

    assert b'You cannot sign up while you\'re logged in' in response.flashes[0][1]
    

    Where flashes is:

    List of tuples (category, message) containing messages that were flashed during request.

  4. But if you're not using FlaskWebTest, you can check session:

    from flask import session
    
    session['_flashes'][0][1]
    
turkus
  • 4,637
  • 2
  • 24
  • 28
  • I've included the error. Both the is_active and is_authenticated are in fact True – MAA Sep 03 '16 at 06:42
  • @MAA does it work or still nothing, because I have something more in my mind. – turkus Sep 03 '16 at 10:13
  • First thank you for following up with me. Yeah I have in my "base.html" (which I subclass in all my jinja2 templates) {% block content %}. Then after it I have the part where I include the flashed message in all the templates. Check the original post – MAA Sep 03 '16 at 12:40
  • @MAA That's why we are here :) Updated. – turkus Sep 03 '16 at 14:31