# -*- coding: utf-8 -*- """ Tests for account CRUD operations and pick-web filtering. """ import json import os import pytest class TestAccountAddWeb: """account add-web creates records correctly without requiring phone numbers.""" def test_add_web_email_login_id(self, clean_db): """Email login_id should be accepted (no 11-digit phone restriction).""" from service.account_service import cmd_account_add_web cmd_account_add_web( platform_input="maersk", login_id="demo@maersk.com", login_id_type="email", label="Maersk sim test", tenant_id="tenant-demo", environment="simulator", role="booking", provider_code=None, url=None, extra_json_str=None, profile_dir_override=None, ) # Should succeed with JSON output from db.accounts_repo import find_accounts accs = find_accounts(platform_key="maersk") assert len(accs) == 1 assert accs[0]["login_id"] == "demo@maersk.com" assert accs[0]["login_id_type"] == "email" assert accs[0]["environment"] == "simulator" assert accs[0]["role"] == "booking" assert accs[0]["tenant_id"] == "tenant-demo" assert accs[0]["status"] == "active" assert accs[0]["platform_key"] == "maersk" def test_add_web_no_login_id(self, clean_db): """login_id can be None (e.g. for browser_profile-only accounts).""" from service.account_service import cmd_account_add_web cmd_account_add_web( platform_input="deepseek", login_id=None, login_id_type="unknown", label="DeepSeek prod", tenant_id=None, environment="production", role="api", provider_code=None, url=None, extra_json_str=None, profile_dir_override=None, ) from db.accounts_repo import find_accounts accs = find_accounts(platform_key="deepseek") assert len(accs) == 1 assert accs[0]["login_id"] == "" def test_add_web_profile_dir_created(self, clean_db, fake_env): """profile_dir should be auto-created under fake_env data root.""" from service.account_service import cmd_account_add_web cmd_account_add_web( platform_input="maersk", login_id="test@example.com", login_id_type="email", label="Profile dir test", tenant_id="tenant-test", environment="production", role="booking", provider_code=None, url=None, extra_json_str=None, profile_dir_override=None, ) from db.accounts_repo import find_accounts accs = find_accounts(platform_key="maersk") assert len(accs) == 1 profile_dir = accs[0]["profile_dir"] assert profile_dir, "profile_dir should be non-empty" assert os.path.isdir(profile_dir), f"profile_dir should be created: {profile_dir}" # The path should be under the fake data root assert profile_dir.startswith(fake_env["data_root"]), \ f"profile_dir should be under fake data root: {profile_dir}" def test_add_web_extra_json(self, clean_db): """extra_json field is stored and retrieved correctly.""" from service.account_service import cmd_account_add_web extra = {"api_version": "v1", "timeout": 30} cmd_account_add_web( platform_input="cma_cgm", login_id="cma@test.com", login_id_type="email", label="CMA CGM test", tenant_id="tenant-cma", environment="production", role="documentation", provider_code=None, url=None, extra_json_str=json.dumps(extra), profile_dir_override=None, ) from db.accounts_repo import find_accounts accs = find_accounts(platform_key="cma_cgm") assert len(accs) == 1 raw_ex = accs[0].get("extra_json") extra_parsed = raw_ex if isinstance(raw_ex, dict) else json.loads(raw_ex or "{}") assert extra_parsed["api_version"] == "v1" assert extra_parsed["timeout"] == 30 class TestAccountGetList: """account get/list operations.""" def test_get_account_found(self, clean_db): """account get returns JSON with correct account fields.""" from service.account_service import cmd_account_add_web, cmd_account_get import io import sys # Add account first cmd_account_add_web( platform_input="evergreen", login_id="ship@evergreen.com", login_id_type="email", label="Evergreen booking", tenant_id="tenant-evg", environment="production", role="booking", provider_code=None, url=None, extra_json_str=None, profile_dir_override=None, ) accs = find_accounts_() captured = io.StringIO() sys.stdout = captured try: cmd_account_get(accs[0]["id"]) finally: sys.stdout = sys.__stdout__ output = captured.getvalue() data = json.loads(output) assert data["platform_key"] == "evergreen" assert data["login_id"] == "ship@evergreen.com" def test_get_account_not_found(self, clean_db): """account get for unknown id returns ERROR:ACCOUNT_NOT_FOUND.""" from service.account_service import cmd_account_get import io import sys captured = io.StringIO() sys.stdout = captured try: cmd_account_get(9999) finally: sys.stdout = sys.__stdout__ output = captured.getvalue() assert "ERROR:ACCOUNT_NOT_FOUND" in output def test_list_platform_filter(self, clean_db): """account list --platform filters by platform.""" from service.account_service import cmd_account_add_web, cmd_account_list import io import sys cmd_account_add_web("maersk", "a@maersk.com", "email", "m", "t1", "prod", "booking", None, None, None, None) cmd_account_add_web("maersk", "b@maersk.com", "email", "m2", "t1", "prod", "documentation", None, None, None, None) cmd_account_add_web("cma_cgm", "c@cma.com", "email", "c", "t2", "prod", "booking", None, None, None, None) captured = io.StringIO() sys.stdout = captured try: cmd_account_list(platform_input="maersk") finally: sys.stdout = sys.__stdout__ output = captured.getvalue() accs = json.loads(output) assert len(accs) == 2 assert all(a["platform_key"] == "maersk" for a in accs) def find_accounts_(): from db.accounts_repo import find_accounts return find_accounts(limit=200) class TestPickWebFiltering: """pick-web filtering by environment / role / tenant_id.""" def _add(self, platform, login, label, tenant, env, role): from service.account_service import cmd_account_add_web cmd_account_add_web( platform, login, "email", label, tenant, env, role, None, None, None, None, ) def test_filter_environment(self, clean_db): """pick-web --environment simulator selects only simulator account.""" self._add("maersk", "sim@maersk.com", "S", "t1", "simulator", "booking") self._add("maersk", "prod@maersk.com", "P", "t1", "production", "booking") self._add("maersk", "prod2@maersk.com", "P2", "t1", "production", "documentation") from service.account_service import cmd_account_pick_web import io, sys captured = io.StringIO() sys.stdout = captured try: cmd_account_pick_web("maersk", environment="simulator", tenant_id=None, role=None, do_lease=False) finally: sys.stdout = sys.__stdout__ result = json.loads(captured.getvalue()) assert result["login_id"] == "sim@maersk.com" assert result["environment"] == "simulator" def test_filter_role(self, clean_db): """pick-web --role booking selects only booking role.""" self._add("maersk", "a@maersk.com", "A", "t1", "simulator", "booking") self._add("maersk", "b@maersk.com", "B", "t1", "simulator", "documentation") from service.account_service import cmd_account_pick_web import io, sys captured = io.StringIO() sys.stdout = captured try: cmd_account_pick_web("maersk", environment=None, tenant_id=None, role="documentation", do_lease=False) finally: sys.stdout = sys.__stdout__ result = json.loads(captured.getvalue()) assert result["role"] == "documentation" def test_filter_tenant(self, clean_db): """pick-web --tenant-id filters correctly.""" self._add("cma_cgm", "a@cma.com", "A", "tenant-a", "production", "booking") self._add("cma_cgm", "b@cma.com", "B", "tenant-b", "production", "booking") from service.account_service import cmd_account_pick_web import io, sys captured = io.StringIO() sys.stdout = captured try: cmd_account_pick_web("cma_cgm", environment=None, tenant_id="tenant-b", role=None, do_lease=False) finally: sys.stdout = sys.__stdout__ result = json.loads(captured.getvalue()) assert result["tenant_id"] == "tenant-b" def test_no_accounts_returns_error(self, clean_db): """pick-web when no account matches returns ERROR:NO_ACCOUNT.""" from service.account_service import cmd_account_pick_web import io, sys captured = io.StringIO() sys.stdout = captured try: cmd_account_pick_web("maersk", environment="nonexistent", tenant_id=None, role=None, do_lease=False) finally: sys.stdout = sys.__stdout__ output = captured.getvalue() err = json.loads(output) assert err["success"] is False assert err["error"]["code"] == "ERROR:NO_ACCOUNT" def test_platform_alias_chinese(self, clean_db): """pick-web resolves Chinese platform alias correctly.""" self._add("maersk", "test@test.com", "Test", "t", "production", "booking") from service.account_service import cmd_account_pick_web import io, sys captured = io.StringIO() sys.stdout = captured try: cmd_account_pick_web("马士基", environment=None, tenant_id=None, role=None, do_lease=False) finally: sys.stdout = sys.__stdout__ result = json.loads(captured.getvalue()) assert result["platform_key"] == "maersk"