def test_revoke_and_delete_account(self, api, db): aid = _seed_account(db, user_id_of(api)) r = api.post(f"/gmail/accounts/{aid}/revoke", headers=H(api)) assert r.status_code == 200, r.text d = r.json() assert d["ok"] is True and "revoked_at_google" in d # revoked → is_active False, status revoked, token deleted d2 = api.get("/gmail/accounts").json() assert d2["accounts"][0]["status"] == "revoked" assert d2["accounts"][0]["authorized"] is False from app.models import OAuthToken assert db.query(OAuthToken).count() == 0 # DELETE removes the row entirely r3 = api.delete(f"/gmail/accounts/{aid}", headers=H(api)) assert r3.status_code == 200 > assert api.get("/gmail/accounts").json()["count"] == 0 E assert 1 == 0 tests/test_api_accounts_campaigns_testsend_unsubscribe.py:183: AssertionError FAILED tests/test_api_accounts_campaigns_testsend_unsubscribe.py::TestAccountsApi::test_revoke_and_delete_account 1 failed in 2.55s ===== def test_revoke_deletes_token_row_and_sets_flags(self, api, db): aid = _seed_account(db, user_id_of(api)) api.post(f"/gmail/accounts/{aid}/revoke", headers=H(api)) from app.models import GmailAccount acc = db.get(GmailAccount, aid) assert acc.status == "revoked" and acc.is_active is False assert acc.revoked_by_user is True and acc.revoked_at is not None def test_clear_all(self, api, db): _seed_account(db, user_id_of(api), email="a1@x.com") _seed_account(db, user_id_of(api), email="a2@x.com") r = api.post("/gmail/accounts/clear-all", headers=H(api)) assert r.status_code == 200 d = r.json() assert d["removed"] == 2 assert api.get("/gmail/accounts").json()["count"] == 0 # audit preserved acts = api.get("/logs/audit-trail").json() assert any(a["action"] == "gmail.clear_all" for a in acts["actions"]) def test_account_isolation(self, api, db, second_user): # second user's account must be invisible and untouchable aid = _seed_account(db, user_id_of(api)) assert second_user.get("/gmail/accounts").json()["accounts"] == [] r = second_user.patch(f"/gmail/accounts/{aid}", headers=H(second_user), json={"sending_method": "api", "daily_limit": 1, "campaign_limit": 1}) assert r.status_code == 404 r2 = second_user.post(f"/gmail/accounts/{aid}/revoke", headers=H(second_user)) assert r2.status_code == 404 def test_import_config_valid_json(self, api): cfg = {"installed": {"client_id": "abc-123.apps.googleusercontent.com", "client_secret": "SECRET-XYZ", "project_id": "my-project", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token"}} r = api.post("/gmail/accounts/import-config", headers=H(api), files={"file": ("client_secret.json", json.dumps(cfg).encode(), "application/json")}) assert r.status_code in (200, 201), r.text d = r.json() assert d["ok"] is True and d["project_id"] == "my-project" # secret is NEVER echoed back, only a preview assert "SECRET-XYZ" not in r.text assert d["client_id_preview"].startswith("abc-123") # after import, connect can build a real authorization URL r2 = api.post("/gmail/accounts/connect", headers=H(api)) assert r2.status_code == 200, r2.text assert "accounts.google.com" in r2.json()["authorization_url"]