diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 10d48eb..ff67c48 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -166,6 +166,8 @@ jobs: echo "Waiting for backend to be ready..." sleep 10 + echo "Resetting MongoDB test database..." + docker-compose -f docker-compose.test.yml exec -T chores-test-app-backend python -c "from db.db import reset_mongo_db; reset_mongo_db()" echo "Seeding test user..." docker-compose -f docker-compose.test.yml exec -T chores-test-app-backend python scripts/seed_test_user.py echo "Creating admin user..." diff --git a/backend/db/db.py b/backend/db/db.py index 5bfb2e6..07090b7 100644 --- a/backend/db/db.py +++ b/backend/db/db.py @@ -579,29 +579,38 @@ def ensure_mongodb_indexes(client=None, db_name=None): coll.create_index(keys, **kwargs) -# Clear test data at import time so tests start with a clean slate. -if os.environ.get('DB_ENV', 'prod') == 'test': - if USE_MONGODB: - # Drop the entire MongoDB test database for a fresh start. Only do this - # for clearly test/e2e database names as a safety guard. - if _mongo_db_name and _mongo_db_name.endswith(('_test', '_e2e')): - get_mongo_client().drop_database(_mongo_db_name) - else: - child_db.truncate() - task_db.truncate() - routine_db.truncate() - routine_items_db.truncate() - routine_schedules_db.truncate() - routine_extensions_db.truncate() - reward_db.truncate() - image_db.truncate() - pending_reward_db.truncate() - pending_confirmations_db.truncate() - users_db.truncate() - tracking_events_db.truncate() - child_overrides_db.truncate() - chore_schedules_db.truncate() - task_extensions_db.truncate() - refresh_tokens_db.truncate() - push_subscriptions_db.truncate() - digest_action_tokens_db.truncate() +# Clear test collections at import time so tests start with a clean slate. +# Only TinyDB path — MongoDB cleanup is handled explicitly via reset_mongo_db(). +if os.environ.get('DB_ENV', 'prod') == 'test' and not USE_MONGODB: + child_db.truncate() + task_db.truncate() + routine_db.truncate() + routine_items_db.truncate() + routine_schedules_db.truncate() + routine_extensions_db.truncate() + reward_db.truncate() + image_db.truncate() + pending_reward_db.truncate() + pending_confirmations_db.truncate() + users_db.truncate() + tracking_events_db.truncate() + child_overrides_db.truncate() + chore_schedules_db.truncate() + task_extensions_db.truncate() + refresh_tokens_db.truncate() + push_subscriptions_db.truncate() + digest_action_tokens_db.truncate() + + +def reset_mongo_db(): + """Drop the MongoDB test/e2e database for a totally fresh slate. + + Only acts on database names ending with ``_test`` or ``_e2e`` as a + safety guard against accidentally dropping production data. Call this + once at the start of a test session or deployment seed step. + """ + if not USE_MONGODB: + return + if not _mongo_db_name or not _mongo_db_name.endswith(('_test', '_e2e')): + return + get_mongo_client().drop_database(_mongo_db_name) diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index ba97ced..2e84999 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -24,7 +24,8 @@ def set_test_db_env(): os.environ['MONGO_URI'] = 'mongomock' os.environ['SECRET_KEY'] = TEST_SECRET_KEY os.environ['REFRESH_TOKEN_EXPIRY_DAYS'] = str(TEST_REFRESH_TOKEN_EXPIRY_DAYS) - # Ensure indexes are created once for the test session. This is safe to - # call repeatedly because MongoDB treats index creation as idempotent. - from db.db import ensure_mongodb_indexes + # Drop the MongoDB test database once at the start of the session so every + # test begins from a clean slate. Indexes are recreated afterward. + from db.db import reset_mongo_db, ensure_mongodb_indexes + reset_mongo_db() ensure_mongodb_indexes()