"""Tests for authentication: registration, login, logout.""" def test_register_page(client): resp = client.get("/register") assert resp.status_code == 200 assert b"Create Account" in resp.data assert b"Household" in resp.data def test_register_create_household(client): """Registering with 'create household' should succeed and make admin.""" resp = client.post("/register", data={ "username": "testuser", "password": "secret123", "confirm": "secret123", "household_action": "create", "new_household_name": "My House", }, follow_redirects=True) assert resp.status_code == 200 assert b"Account created" in resp.data assert b"My House" in resp.data # Shows in nav def test_register_first_in_household_is_admin(client): """First user in a new household should be admin.""" client.post("/register", data={ "username": "firstuser", "password": "secret123", "confirm": "secret123", "household_action": "create", "new_household_name": "First House", }) from models import get_user_by_username user = get_user_by_username("firstuser") assert user is not None assert user["is_admin"] == 1 def test_register_join_household_not_admin(client): """Joining an existing household makes you a non-admin.""" # First user creates household client.post("/register", data={ "username": "creator", "password": "secret123", "confirm": "secret123", "household_action": "create", "new_household_name": "Shared Home", }) client.get("/logout") # Second user joins client.post("/register", data={ "username": "joiner", "password": "pass4321", "confirm": "pass4321", "household_action": "join", "household_id": "1", }) from models import get_user_by_username joiner = get_user_by_username("joiner") assert joiner is not None assert joiner["is_admin"] == 0 assert joiner["household_id"] == 1 def test_register_create_duplicate_household_name(client): """Creating a household with an existing name should fail.""" client.post("/register", data={ "username": "u1", "password": "pass1234", "confirm": "pass1234", "household_action": "create", "new_household_name": "DupHouse", }) client.get("/logout") resp = client.post("/register", data={ "username": "u2", "password": "pass5678", "confirm": "pass5678", "household_action": "create", "new_household_name": "DupHouse", }, follow_redirects=True) assert b"already exists" in resp.data def test_register_missing_household_name(client): """Creating a household without a name should fail.""" resp = client.post("/register", data={ "username": "u3", "password": "pass1234", "confirm": "pass1234", "household_action": "create", "new_household_name": "", }, follow_redirects=True) assert b"Household name is required" in resp.data def test_register_no_household_selected(client): """Joining without selecting a household should fail.""" resp = client.post("/register", data={ "username": "u4", "password": "pass1234", "confirm": "pass1234", "household_action": "join", "household_id": "", }, follow_redirects=True) assert b"Please select a household" in resp.data def test_register_duplicate_username(client): client.post("/register", data={ "username": "dup", "password": "pass1234", "confirm": "pass1234", "household_action": "create", "new_household_name": "DupHouse", }) client.get("/logout") resp = client.post("/register", data={ "username": "dup", "password": "other5678", "confirm": "other5678", "household_action": "create", "new_household_name": "OtherHouse", }, follow_redirects=True) assert b"Username already taken" in resp.data def test_register_password_mismatch(client): resp = client.post("/register", data={ "username": "someone", "password": "abc12345", "confirm": "abc12346", "household_action": "create", "new_household_name": "AnyHouse", }, follow_redirects=True) assert b"Passwords do not match" in resp.data def test_register_short_username(client): resp = client.post("/register", data={ "username": "x", "password": "pass1234", "confirm": "pass1234", "household_action": "create", "new_household_name": "AnyHouse", }, follow_redirects=True) assert b"at least 2 characters" in resp.data def test_register_short_password(client): resp = client.post("/register", data={ "username": "validname", "password": "ab", "confirm": "ab", "household_action": "create", "new_household_name": "AnyHouse", }, follow_redirects=True) assert b"at least 4 characters" in resp.data def test_login_page(client): resp = client.get("/login") assert resp.status_code == 200 assert b"Log In" in resp.data def test_login_success(client): client.post("/register", data={ "username": "logintest", "password": "mypassword", "confirm": "mypassword", "household_action": "create", "new_household_name": "LoginHouse", }) client.get("/logout") resp = client.post("/login", data={ "username": "logintest", "password": "mypassword", }, follow_redirects=True) assert resp.status_code == 200 assert b"Today" in resp.data def test_login_wrong_password(client): client.post("/register", data={ "username": "logintest2", "password": "mypassword", "confirm": "mypassword", "household_action": "create", "new_household_name": "LoginHouse2", }) client.get("/logout") resp = client.post("/login", data={ "username": "logintest2", "password": "wrongpassword", }, follow_redirects=True) assert b"Invalid username or password" in resp.data def test_login_nonexistent_user(client): resp = client.post("/login", data={ "username": "nobody", "password": "whatever", }, follow_redirects=True) assert b"Invalid username or password" in resp.data def test_logout(auth_client): resp = auth_client.get("/logout", follow_redirects=True) assert resp.status_code == 200 assert b"Log In" in resp.data def test_unauthenticated_redirect(client): """Dashboard and root should redirect to login when not logged in.""" for path in ["/", "/dashboard", "/history"]: resp = client.get(path, follow_redirects=True) assert resp.status_code == 200 assert b"Log In" in resp.data