fix: Update migration tests after Phase 1 IndieAuth removal
Fixed 5 failing tests related to code_verifier column which was added by migration 001 but removed by migration 003. Changes: - Renamed legacy_db_without_code_verifier to legacy_db_basic - Updated column_exists tests to use 'state' column instead of 'code_verifier' - Updated test_run_migrations_legacy_database to test with generic column - Replaced test_actual_migration_001 with test_actual_migration_003 - Fixed test_dev_mode_requires_dev_admin_me to explicitly override DEV_ADMIN_ME All 551 tests now passing. Part of Phase 1 completion: IndieAuth authorization server removal 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -49,19 +49,54 @@ def temp_migrations_dir():
|
||||
|
||||
@pytest.fixture
|
||||
def fresh_db_with_schema(temp_db):
|
||||
"""Create a fresh database with current schema (includes code_verifier)"""
|
||||
"""Create a fresh database with current schema (no code_verifier after migration 003)"""
|
||||
conn = sqlite3.connect(temp_db)
|
||||
try:
|
||||
# Create auth_state table with code_verifier (current schema)
|
||||
# Create auth_state table WITHOUT code_verifier (current schema after Phase 1)
|
||||
conn.execute("""
|
||||
CREATE TABLE auth_state (
|
||||
state TEXT PRIMARY KEY,
|
||||
code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
redirect_uri TEXT
|
||||
)
|
||||
""")
|
||||
# Also need other tables to make schema truly current
|
||||
conn.execute("""
|
||||
CREATE TABLE tokens (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
token_hash TEXT UNIQUE NOT NULL,
|
||||
me TEXT NOT NULL,
|
||||
client_id TEXT,
|
||||
scope TEXT DEFAULT 'create',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
last_used_at TIMESTAMP,
|
||||
revoked_at TIMESTAMP
|
||||
)
|
||||
""")
|
||||
conn.execute("""
|
||||
CREATE TABLE authorization_codes (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
code_hash TEXT UNIQUE NOT NULL,
|
||||
me TEXT NOT NULL,
|
||||
client_id TEXT NOT NULL,
|
||||
redirect_uri TEXT NOT NULL,
|
||||
scope TEXT,
|
||||
state TEXT,
|
||||
code_challenge TEXT,
|
||||
code_challenge_method TEXT,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
used_at TIMESTAMP
|
||||
)
|
||||
""")
|
||||
# Add required indexes
|
||||
conn.execute("CREATE INDEX idx_tokens_hash ON tokens(token_hash)")
|
||||
conn.execute("CREATE INDEX idx_tokens_me ON tokens(me)")
|
||||
conn.execute("CREATE INDEX idx_tokens_expires ON tokens(expires_at)")
|
||||
conn.execute("CREATE INDEX idx_auth_codes_hash ON authorization_codes(code_hash)")
|
||||
conn.execute("CREATE INDEX idx_auth_codes_expires ON authorization_codes(expires_at)")
|
||||
conn.commit()
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -69,11 +104,11 @@ def fresh_db_with_schema(temp_db):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def legacy_db_without_code_verifier(temp_db):
|
||||
"""Create a legacy database without code_verifier column"""
|
||||
def legacy_db_basic(temp_db):
|
||||
"""Create a basic database with auth_state table"""
|
||||
conn = sqlite3.connect(temp_db)
|
||||
try:
|
||||
# Create auth_state table WITHOUT code_verifier (legacy schema)
|
||||
# Create auth_state table WITHOUT code_verifier (current schema)
|
||||
conn.execute("""
|
||||
CREATE TABLE auth_state (
|
||||
state TEXT PRIMARY KEY,
|
||||
@@ -132,17 +167,18 @@ class TestSchemaDetection:
|
||||
"""Tests for fresh database detection"""
|
||||
|
||||
def test_is_schema_current_with_code_verifier(self, fresh_db_with_schema):
|
||||
"""Test detecting current schema (has code_verifier)"""
|
||||
"""Test detecting current schema (no code_verifier after Phase 1)"""
|
||||
conn = sqlite3.connect(fresh_db_with_schema)
|
||||
try:
|
||||
assert is_schema_current(conn) is True
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def test_is_schema_current_without_code_verifier(self, legacy_db_without_code_verifier):
|
||||
"""Test detecting legacy schema (no code_verifier)"""
|
||||
conn = sqlite3.connect(legacy_db_without_code_verifier)
|
||||
def test_is_schema_current_without_code_verifier(self, legacy_db_basic):
|
||||
"""Test detecting incomplete schema (missing tokens/authorization_codes tables)"""
|
||||
conn = sqlite3.connect(legacy_db_basic)
|
||||
try:
|
||||
# Should be False because missing tokens and authorization_codes tables
|
||||
assert is_schema_current(conn) is False
|
||||
finally:
|
||||
conn.close()
|
||||
@@ -179,15 +215,17 @@ class TestHelperFunctions:
|
||||
"""Test detecting existing column"""
|
||||
conn = sqlite3.connect(fresh_db_with_schema)
|
||||
try:
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is True
|
||||
# Test with a column that actually exists in current schema
|
||||
assert column_exists(conn, 'auth_state', 'state') is True
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def test_column_exists_false(self, legacy_db_without_code_verifier):
|
||||
def test_column_exists_false(self, legacy_db_basic):
|
||||
"""Test detecting non-existent column"""
|
||||
conn = sqlite3.connect(legacy_db_without_code_verifier)
|
||||
conn = sqlite3.connect(legacy_db_basic)
|
||||
try:
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is False
|
||||
# Test with a column that doesn't exist
|
||||
assert column_exists(conn, 'auth_state', 'nonexistent_column') is False
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
@@ -375,48 +413,55 @@ class TestRunMigrations:
|
||||
assert migration_count == 0
|
||||
assert is_schema_current(conn) is True
|
||||
|
||||
# Manually mark migration as applied (simulating fresh DB detection)
|
||||
# Manually mark migrations as applied (simulating fresh DB detection)
|
||||
conn.execute(
|
||||
"INSERT INTO schema_migrations (migration_name) VALUES (?)",
|
||||
("001_add_code_verifier_to_auth_state.sql",)
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT INTO schema_migrations (migration_name) VALUES (?)",
|
||||
("003_remove_code_verifier_from_auth_state.sql",)
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
# Verify migration was marked but NOT executed
|
||||
# Verify migrations were marked but NOT executed
|
||||
applied = get_applied_migrations(conn)
|
||||
assert "001_add_code_verifier_to_auth_state.sql" in applied
|
||||
assert "003_remove_code_verifier_from_auth_state.sql" in applied
|
||||
|
||||
# Table should still have only one code_verifier column (not duplicated)
|
||||
# Table should NOT have code_verifier column (current schema after Phase 1)
|
||||
cursor = conn.execute("PRAGMA table_info(auth_state)")
|
||||
columns = [row[1] for row in cursor.fetchall()]
|
||||
assert columns.count('code_verifier') == 1
|
||||
assert 'code_verifier' not in columns
|
||||
assert 'state' in columns
|
||||
assert 'expires_at' in columns
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def test_run_migrations_legacy_database(self, legacy_db_without_code_verifier, temp_migrations_dir):
|
||||
def test_run_migrations_legacy_database(self, legacy_db_basic, temp_migrations_dir):
|
||||
"""Test legacy database scenario - migration should execute"""
|
||||
# Create the migration to add code_verifier
|
||||
migration_file = temp_migrations_dir / "001_add_code_verifier_to_auth_state.sql"
|
||||
# Create a migration to add a test column
|
||||
migration_file = temp_migrations_dir / "001_add_test_column.sql"
|
||||
migration_file.write_text(
|
||||
"ALTER TABLE auth_state ADD COLUMN code_verifier TEXT NOT NULL DEFAULT '';"
|
||||
"ALTER TABLE auth_state ADD COLUMN test_column TEXT;"
|
||||
)
|
||||
|
||||
conn = sqlite3.connect(legacy_db_without_code_verifier)
|
||||
conn = sqlite3.connect(legacy_db_basic)
|
||||
try:
|
||||
create_migrations_table(conn)
|
||||
|
||||
# Verify code_verifier doesn't exist yet
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is False
|
||||
# Verify test_column doesn't exist yet
|
||||
assert column_exists(conn, 'auth_state', 'test_column') is False
|
||||
|
||||
# Apply migration
|
||||
apply_migration(conn, "001_add_code_verifier_to_auth_state.sql", migration_file)
|
||||
apply_migration(conn, "001_add_test_column.sql", migration_file)
|
||||
|
||||
# Verify code_verifier was added
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is True
|
||||
# Verify test_column was added
|
||||
assert column_exists(conn, 'auth_state', 'test_column') is True
|
||||
|
||||
# Verify migration was recorded
|
||||
applied = get_applied_migrations(conn)
|
||||
assert "001_add_code_verifier_to_auth_state.sql" in applied
|
||||
assert "001_add_test_column.sql" in applied
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
@@ -525,36 +570,52 @@ class TestRunMigrations:
|
||||
|
||||
|
||||
class TestRealMigration:
|
||||
"""Test with actual migration file from the project"""
|
||||
"""Test with actual migration files from the project"""
|
||||
|
||||
def test_actual_migration_001(self, legacy_db_without_code_verifier):
|
||||
"""Test the actual 001 migration file"""
|
||||
def test_actual_migration_003(self, temp_db):
|
||||
"""Test the actual 003 migration file (remove code_verifier)"""
|
||||
# Get the actual migration file
|
||||
project_root = Path(__file__).parent.parent
|
||||
migration_file = project_root / "migrations" / "001_add_code_verifier_to_auth_state.sql"
|
||||
migration_file = project_root / "migrations" / "003_remove_code_verifier_from_auth_state.sql"
|
||||
|
||||
if not migration_file.exists():
|
||||
pytest.skip("Migration file 001_add_code_verifier_to_auth_state.sql not found")
|
||||
pytest.skip("Migration file 003_remove_code_verifier_from_auth_state.sql not found")
|
||||
|
||||
conn = sqlite3.connect(legacy_db_without_code_verifier)
|
||||
conn = sqlite3.connect(temp_db)
|
||||
try:
|
||||
create_migrations_table(conn)
|
||||
|
||||
# Verify starting state
|
||||
assert not column_exists(conn, 'auth_state', 'code_verifier')
|
||||
# Create auth_state table WITH code_verifier (pre-migration state)
|
||||
conn.execute("""
|
||||
CREATE TABLE auth_state (
|
||||
state TEXT PRIMARY KEY,
|
||||
code_verifier TEXT NOT NULL DEFAULT '',
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
expires_at TIMESTAMP NOT NULL,
|
||||
redirect_uri TEXT
|
||||
)
|
||||
""")
|
||||
conn.execute("CREATE INDEX idx_auth_state_expires ON auth_state(expires_at)")
|
||||
conn.commit()
|
||||
|
||||
# Verify starting state (has code_verifier)
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is True
|
||||
|
||||
# Apply migration
|
||||
apply_migration(
|
||||
conn,
|
||||
"001_add_code_verifier_to_auth_state.sql",
|
||||
"003_remove_code_verifier_from_auth_state.sql",
|
||||
migration_file
|
||||
)
|
||||
|
||||
# Verify end state
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier')
|
||||
# Verify end state (no code_verifier)
|
||||
assert column_exists(conn, 'auth_state', 'code_verifier') is False
|
||||
# Other columns should still exist
|
||||
assert column_exists(conn, 'auth_state', 'state') is True
|
||||
assert column_exists(conn, 'auth_state', 'redirect_uri') is True
|
||||
|
||||
# Verify migration recorded
|
||||
applied = get_applied_migrations(conn)
|
||||
assert "001_add_code_verifier_to_auth_state.sql" in applied
|
||||
assert "003_remove_code_verifier_from_auth_state.sql" in applied
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
@@ -167,7 +167,7 @@ class TestConfigurationValidation:
|
||||
"SESSION_SECRET": "test-secret",
|
||||
"SITE_URL": "http://localhost:5000",
|
||||
"DEV_MODE": True,
|
||||
# Missing DEV_ADMIN_ME
|
||||
"DEV_ADMIN_ME": "", # Explicitly set to empty string
|
||||
}
|
||||
|
||||
with pytest.raises(ValueError, match="DEV_ADMIN_ME"):
|
||||
|
||||
Reference in New Issue
Block a user