| """Authentication endpoint tests.""" | |
| class TestLogin: | |
| """Test login functionality.""" | |
| def test_login_page_loads(self, client): | |
| """Login page should return 200.""" | |
| resp = client.get("/auth/login") | |
| assert resp.status_code == 200 | |
| assert b"VenueFlow" in resp.data | |
| def test_login_with_valid_credentials(self, client): | |
| """Valid credentials should redirect to attendee home.""" | |
| resp = client.post( | |
| "/auth/login", | |
| data={"email": "fan@venueflow.demo", "password": "demo123"}, | |
| follow_redirects=False, | |
| ) | |
| assert resp.status_code == 302 | |
| assert "/app" in resp.headers.get("Location", "") | |
| def test_login_with_invalid_credentials(self, client): | |
| """Invalid credentials should show error.""" | |
| resp = client.post( | |
| "/auth/login", | |
| data={"email": "bad@email.com", "password": "wrong"}, | |
| follow_redirects=True, | |
| ) | |
| assert resp.status_code == 200 | |
| assert b"Invalid email or password" in resp.data | |
| def test_login_operator_redirects_to_dashboard(self, client): | |
| """Operator login should redirect to operator dashboard.""" | |
| resp = client.post( | |
| "/auth/login", | |
| data={"email": "operator@venueflow.demo", "password": "demo123"}, | |
| follow_redirects=False, | |
| ) | |
| assert resp.status_code == 302 | |
| assert "/operator" in resp.headers.get("Location", "") | |
| def test_login_empty_fields(self, client): | |
| """Empty fields should show error.""" | |
| resp = client.post( | |
| "/auth/login", | |
| data={"email": "", "password": ""}, | |
| follow_redirects=True, | |
| ) | |
| assert resp.status_code == 200 | |
| assert b"fill in all fields" in resp.data | |
| def test_login_invalid_email_format(self, client): | |
| """Invalid email format should show error.""" | |
| resp = client.post( | |
| "/auth/login", | |
| data={"email": "notanemail", "password": "demo123"}, | |
| follow_redirects=True, | |
| ) | |
| assert resp.status_code == 200 | |
| assert b"valid email" in resp.data | |
| class TestRegister: | |
| """Test registration functionality.""" | |
| def test_register_page_loads(self, client): | |
| """Registration page should return 200.""" | |
| resp = client.get("/auth/register") | |
| assert resp.status_code == 200 | |
| assert b"Create Account" in resp.data | |
| def test_register_new_user(self, client): | |
| """New user registration should succeed.""" | |
| resp = client.post( | |
| "/auth/register", | |
| data={ | |
| "email": "test@venue.com", | |
| "password": "test123", | |
| "confirm_password": "test123", | |
| "display_name": "Test User", | |
| }, | |
| follow_redirects=False, | |
| ) | |
| assert resp.status_code == 302 | |
| def test_register_password_mismatch(self, client): | |
| """Mismatched passwords should show error.""" | |
| resp = client.post( | |
| "/auth/register", | |
| data={ | |
| "email": "test@venue.com", | |
| "password": "test123", | |
| "confirm_password": "wrong", | |
| "display_name": "Test User", | |
| }, | |
| follow_redirects=True, | |
| ) | |
| assert resp.status_code == 200 | |
| assert b"do not match" in resp.data | |
| def test_register_short_password(self, client): | |
| """Short password should show error.""" | |
| resp = client.post( | |
| "/auth/register", | |
| data={ | |
| "email": "test@venue.com", | |
| "password": "12", | |
| "confirm_password": "12", | |
| "display_name": "Test User", | |
| }, | |
| follow_redirects=True, | |
| ) | |
| assert resp.status_code == 200 | |
| assert b"at least 6 characters" in resp.data | |
| class TestLogout: | |
| """Test logout functionality.""" | |
| def test_logout_clears_session(self, auth_client): | |
| """Logout should clear session and redirect.""" | |
| resp = auth_client.get("/auth/logout", follow_redirects=False) | |
| assert resp.status_code == 302 | |
| assert "/auth/login" in resp.headers.get("Location", "") | |
| class TestAccessControl: | |
| """Test route access control.""" | |
| def test_attendee_pages_require_login(self, client): | |
| """Attendee pages should redirect unauthenticated users.""" | |
| resp = client.get("/app/", follow_redirects=False) | |
| assert resp.status_code == 302 | |
| def test_operator_pages_require_login(self, client): | |
| """Operator pages should redirect unauthenticated users.""" | |
| resp = client.get("/operator/dashboard", follow_redirects=False) | |
| assert resp.status_code == 302 | |
| def test_attendee_cannot_access_operator(self, auth_client): | |
| """Attendee should be denied from operator pages.""" | |
| resp = auth_client.get("/operator/dashboard", follow_redirects=True) | |
| assert b"Access denied" in resp.data or b"Operator" in resp.data | |