Files
gh-christianlouis-quizzical…/tests/test_routes.py
T
2026-03-12 01:16:36 +00:00

200 lines
7.8 KiB
Python

"""Tests for Flask routes."""
import pytest
from musicround.models import db, User, Song, Round, Tag
class TestCoreRoutes:
"""Tests for core blueprint routes."""
def test_index_unauthenticated_redirects_to_login(self, client):
"""Test that unauthenticated access to / redirects to login."""
response = client.get('/')
assert response.status_code == 302
assert 'login' in response.headers['Location'].lower()
def test_view_songs_requires_login(self, client):
"""Test that /view-songs requires authentication."""
response = client.get('/view-songs')
assert response.status_code == 302
assert 'login' in response.headers['Location'].lower()
def test_search_requires_login(self, client):
"""Test that /search requires authentication."""
response = client.get('/search')
assert response.status_code == 302
assert 'login' in response.headers['Location'].lower()
class TestUserRoutes:
"""Tests for user-related routes."""
def test_login_page_accessible(self, client):
"""Test that the login page is accessible without authentication."""
response = client.get('/users/login')
assert response.status_code == 200
def test_register_page_accessible(self, client):
"""Test that the register page is accessible without authentication."""
response = client.get('/users/register')
assert response.status_code == 200
def test_logout_redirects(self, client):
"""Test that /logout redirects (even for unauthenticated users)."""
response = client.get('/users/logout')
# Should redirect somewhere (login page)
assert response.status_code in (302, 200)
def test_profile_requires_login(self, client):
"""Test that /users/profile requires authentication."""
response = client.get('/users/profile')
assert response.status_code == 302
assert 'login' in response.headers['Location'].lower()
def test_register_post_missing_fields(self, client):
"""Test that register POST with missing required fields stays on page."""
response = client.post('/users/register', data={}, follow_redirects=True)
assert response.status_code == 200
def test_register_post_valid_data(self, app, client):
"""Test that registering a user with valid data succeeds."""
response = client.post('/users/register', data={
'username': 'newuser',
'email': 'newuser@example.com',
'password': 'SecurePass123!',
'confirm_password': 'SecurePass123!',
}, follow_redirects=True)
assert response.status_code == 200
# User should now exist in db
with app.app_context():
user = User.query.filter_by(username='newuser').first()
assert user is not None
def test_login_post_invalid_credentials(self, client):
"""Test that login with invalid credentials fails gracefully."""
response = client.post('/users/login', data={
'username': 'nobody',
'password': 'wrongpass',
}, follow_redirects=True)
assert response.status_code == 200
def test_login_post_valid_credentials(self, app, client):
"""Test that login with valid credentials works."""
# First create a user
with app.app_context():
user = User(username='logintest', email='logintest@example.com')
user.password = 'ValidPass123!'
db.session.add(user)
db.session.commit()
response = client.post('/users/login', data={
'username': 'logintest',
'password': 'ValidPass123!',
}, follow_redirects=True)
assert response.status_code == 200
class TestApiRoutes:
"""Tests for API blueprint routes."""
def test_list_tags_no_auth_required(self, client):
"""Test /api/tags is publicly accessible and returns a tags dict."""
response = client.get('/api/tags')
assert response.status_code == 200
data = response.get_json()
assert 'tags' in data
assert isinstance(data['tags'], list)
def test_song_detail_unauthenticated_returns_404_or_redirect(self, client):
"""Test /api/songs/<id> returns 404 for nonexistent song (no auth required)."""
response = client.get('/api/songs/99999')
# Song doesn't exist, so should 404; endpoint itself is not auth-gated
assert response.status_code in (302, 401, 403, 404)
def test_search_songs_unauthenticated_redirects(self, client):
"""Test /api/songs/search requires authentication."""
response = client.get('/api/songs/search?q=test')
assert response.status_code in (302, 401, 403)
class TestRoundsRoutes:
"""Tests for rounds blueprint routes."""
def test_rounds_index_requires_login(self, client):
"""Test that rounds index page requires authentication."""
response = client.get('/rounds/')
assert response.status_code in (302, 404)
def test_view_round_requires_login(self, client):
"""Test that viewing a round requires authentication."""
response = client.get('/rounds/view/1')
assert response.status_code in (302, 404)
class TestErrorHandling:
"""Tests for error handling."""
def test_404_returns_error_page(self, client):
"""Test that a non-existent route returns a 404."""
response = client.get('/this-page-does-not-exist-at-all-xyz')
assert response.status_code == 404
def test_app_is_in_testing_mode(self, app):
"""Test that the test app is correctly in testing mode."""
assert app.config['TESTING'] is True
assert app.config['WTF_CSRF_ENABLED'] is False
class TestAuthenticatedRoutes:
"""Tests for routes that require authentication, tested while logged in."""
def _login(self, app, client):
"""Helper: create a user and log in."""
with app.app_context():
user = User(username='authtest', email='authtest@example.com')
user.password = 'TestPass123!'
db.session.add(user)
db.session.commit()
client.post('/users/login', data={
'username': 'authtest',
'password': 'TestPass123!',
})
def test_view_songs_accessible_when_logged_in(self, app, client):
"""Test that view-songs is accessible when logged in."""
self._login(app, client)
response = client.get('/view-songs')
assert response.status_code == 200
def test_search_accessible_when_logged_in(self, app, client):
"""Test that search page is accessible when logged in."""
self._login(app, client)
response = client.get('/search')
assert response.status_code == 200
def test_index_accessible_when_logged_in(self, app, client):
"""Test that homepage is accessible when logged in."""
self._login(app, client)
response = client.get('/')
assert response.status_code == 200
def test_profile_accessible_when_logged_in(self, app, client):
"""Test that profile page is accessible when logged in."""
self._login(app, client)
response = client.get('/users/profile')
assert response.status_code == 200
def test_api_tags_accessible_when_logged_in(self, app, client):
"""Test that API tags endpoint is accessible when logged in."""
self._login(app, client)
response = client.get('/api/tags')
assert response.status_code == 200
data = response.get_json()
assert 'tags' in data
assert isinstance(data['tags'], list)
def test_api_search_songs_when_logged_in(self, app, client):
"""Test that song search API is accessible when logged in."""
self._login(app, client)
response = client.get('/api/songs/search?q=test')
assert response.status_code == 200