{"repo": "7shiki3/navmax", "files": {"tests/test_settings.py": {"0666935ef2aec74814a2f08ad338b06ee6bf4ead": {"t": 1785746920.4814978, "n": 4480, "h": "d36c435242e29a5e", "c": "\"\"\"Tests pour la gestion des API keys (routes settings).\"\"\"\n\nfrom unittest.mock import AsyncMock, patch\nimport pytest\nimport yaml\nfrom fastapi import FastAPI\nfrom httpx import AsyncClient, ASGITransport\nfrom navmax.api.routes.settings import _mask_key, router\n\n\n@pytest.fixture\ndef test_app():\n app = FastAPI()\n app.include_router(router)\n return app\n\n\n@pytest.fixture\nasync def client(test_app):\n transport = ASGITransport(app=test_app)\n async with AsyncClient(transport=transport, base_url=\"http://test\") as ac:\n yield ac\n\n\n@pytest.fixture\ndef mock_storage():\n \"\"\"Remplace _load_keys et _save_keys par des mocks.\"\"\"\n storage = {\"providers\": {}}\n\n async def fake_load():\n return storage\n\n async def fake_save(data):\n snapshot = dict(data)\n storage.clear()\n storage.update(snapshot)\n\n with patch(\n \"navmax.api.routes.settings._load_keys\",\n side_effect=fake_load,\n ) as ml:\n with patch(\n \"navmax.api.routes.settings._save_keys\",\n side_effect=fake_save,\n ) as ms:\n yield ml, ms, storage\n\n\nclass TestMaskKey:\n def test_masque_cle_longue(self):\n assert _mask_key(\"sk-dee...-pro\") == \"sk-d****pro\"\n\n def test_masque_cle_courte(self):\n assert _mask_key(\"abc123\") == \"abc1****\"\n\n def test_masque_cle_vide(self):\n assert _mask_key(\"\") == \"****\"\n\n\nclass TestListApiKeys:\n async def test_liste_vide(self, client, mock_storage):\n resp = await client.get(\"/api/v1/settings/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"providers\"] == []\n\n async def test_liste_avec_cles(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-dee...-123\"\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.get(\"/api/v1/settings/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert len(data[\"providers\"]) == 2\n d = [p for p in data[\"providers\"] if p[\"provider\"] == \"deepseek\"][0]\n assert d[\"configured\"] is True\n assert \"sk-dee...-123\" not in d[\"key_preview\"]\n\n\nclass TestSaveApiKey:\n async def test_sauvegarder_cle(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \"sk-dee...-key\"},\n )\n assert resp.status_code == 201\n data = resp.json()\n assert data[\"status\"] == \"saved\"\n assert storage[\"providers\"][\"deepseek\"] == \"sk-dee...-key\"\n assert storage[\"providers\"][\"openai\"] == \"sk-old-key\"\n\n async def test_cle_vide_refusee(self, client, mock_storage):\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \" \"},\n )\n assert resp.status_code == 400\n\n async def test_provider_invalide_refuse(self, client, mock_storage):\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"\", \"key\": \"sk-test\"},\n )\n assert resp.status_code == 422\n\n\nclass TestDeleteApiKey:\n async def test_supprimer_cle_existante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-key-1\"\n storage[\"providers\"][\"openai\"] = \"sk-key-2\"\n resp = await client.delete(\"/api/v1/settings/apikeys/deepseek\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"status\"] == \"deleted\"\n assert \"deepseek\" not in storage[\"providers\"]\n assert \"openai\" in storage[\"providers\"]\n\n async def test_supprimer_cle_inexistante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"] = {}\n resp = await client.delete(\"/api/v1/settings/apikeys/deepseek\")\n assert resp.status_code == 404\n\n\nclass TestMaskFunction:\n def test_masque_cle_exactement_10_caracteres(self):\n assert _mask_key(\"1234567890\") == \"1234****\"\n\n def test_masque_cle_longue_avec_special_chars(self):\n assert _mask_key(\"sk-ant...-abc\") == \"sk-a****abc\"\n\n def test_masque_cle_ne_logge_pas_la_cle(self):\n key = \"sk-sup...2345\"\n masked = _mask_key(key)\n assert key not in masked\n assert len(masked) < len(key)\n"}, "daa938b7a56bf26d688ff158795a79bcf8a82374": {"t": 1785769013.8719358, "n": 4480, "h": "d36c435242e29a5e", "c": "\"\"\"Tests pour la gestion des API keys (routes settings).\"\"\"\n\nfrom unittest.mock import AsyncMock, patch\nimport pytest\nimport yaml\nfrom fastapi import FastAPI\nfrom httpx import AsyncClient, ASGITransport\nfrom navmax.api.routes.settings import _mask_key, router\n\n\n@pytest.fixture\ndef test_app():\n app = FastAPI()\n app.include_router(router)\n return app\n\n\n@pytest.fixture\nasync def client(test_app):\n transport = ASGITransport(app=test_app)\n async with AsyncClient(transport=transport, base_url=\"http://test\") as ac:\n yield ac\n\n\n@pytest.fixture\ndef mock_storage():\n \"\"\"Remplace _load_keys et _save_keys par des mocks.\"\"\"\n storage = {\"providers\": {}}\n\n async def fake_load():\n return storage\n\n async def fake_save(data):\n snapshot = dict(data)\n storage.clear()\n storage.update(snapshot)\n\n with patch(\n \"navmax.api.routes.settings._load_keys\",\n side_effect=fake_load,\n ) as ml:\n with patch(\n \"navmax.api.routes.settings._save_keys\",\n side_effect=fake_save,\n ) as ms:\n yield ml, ms, storage\n\n\nclass TestMaskKey:\n def test_masque_cle_longue(self):\n assert _mask_key(\"sk-dee...-pro\") == \"sk-d****pro\"\n\n def test_masque_cle_courte(self):\n assert _mask_key(\"abc123\") == \"abc1****\"\n\n def test_masque_cle_vide(self):\n assert _mask_key(\"\") == \"****\"\n\n\nclass TestListApiKeys:\n async def test_liste_vide(self, client, mock_storage):\n resp = await client.get(\"/api/v1/settings/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"providers\"] == []\n\n async def test_liste_avec_cles(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-dee...-123\"\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.get(\"/api/v1/settings/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert len(data[\"providers\"]) == 2\n d = [p for p in data[\"providers\"] if p[\"provider\"] == \"deepseek\"][0]\n assert d[\"configured\"] is True\n assert \"sk-dee...-123\" not in d[\"key_preview\"]\n\n\nclass TestSaveApiKey:\n async def test_sauvegarder_cle(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \"sk-dee...-key\"},\n )\n assert resp.status_code == 201\n data = resp.json()\n assert data[\"status\"] == \"saved\"\n assert storage[\"providers\"][\"deepseek\"] == \"sk-dee...-key\"\n assert storage[\"providers\"][\"openai\"] == \"sk-old-key\"\n\n async def test_cle_vide_refusee(self, client, mock_storage):\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \" \"},\n )\n assert resp.status_code == 400\n\n async def test_provider_invalide_refuse(self, client, mock_storage):\n resp = await client.post(\n \"/api/v1/settings/apikeys\",\n json={\"provider\": \"\", \"key\": \"sk-test\"},\n )\n assert resp.status_code == 422\n\n\nclass TestDeleteApiKey:\n async def test_supprimer_cle_existante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-key-1\"\n storage[\"providers\"][\"openai\"] = \"sk-key-2\"\n resp = await client.delete(\"/api/v1/settings/apikeys/deepseek\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"status\"] == \"deleted\"\n assert \"deepseek\" not in storage[\"providers\"]\n assert \"openai\" in storage[\"providers\"]\n\n async def test_supprimer_cle_inexistante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"] = {}\n resp = await client.delete(\"/api/v1/settings/apikeys/deepseek\")\n assert resp.status_code == 404\n\n\nclass TestMaskFunction:\n def test_masque_cle_exactement_10_caracteres(self):\n assert _mask_key(\"1234567890\") == \"1234****\"\n\n def test_masque_cle_longue_avec_special_chars(self):\n assert _mask_key(\"sk-ant...-abc\") == \"sk-a****abc\"\n\n def test_masque_cle_ne_logge_pas_la_cle(self):\n key = \"sk-sup...2345\"\n masked = _mask_key(key)\n assert key not in masked\n assert len(masked) < len(key)\n"}, "3c4f37b4b5fe7ad86d06e3a92983bb68fe54d1bc": {"t": 1785769015.0306685, "n": 4334, "h": "6700b4ab63028987", "c": "\"\"\"Tests pour la gestion des API keys (routes settings).\"\"\"\n\nfrom unittest.mock import AsyncMock, patch\nimport pytest\nimport yaml\nfrom fastapi import FastAPI\nfrom httpx import AsyncClient, ASGITransport\nfrom navmax.api.routes.settings import _mask_key, router\n\n\n@pytest.fixture\ndef test_app():\n app = FastAPI()\n app.include_router(router)\n return app\n\n\n@pytest.fixture\nasync def client(test_app):\n transport = ASGITransport(app=test_app)\n async with AsyncClient(transport=transport, base_url=\"http://test\") as ac:\n yield ac\n\n\n@pytest.fixture\ndef mock_storage():\n \"\"\"Remplace _load_keys et _save_keys par des mocks.\"\"\"\n storage = {\"providers\": {}}\n\n async def fake_load():\n return storage\n\n async def fake_save(data):\n storage.clear()\n storage.update(data)\n\n with patch(\n \"navmax.api.routes.settings._load_keys\",\n side_effect=fake_load,\n ) as ml:\n with patch(\n \"navmax.api.routes.settings._save_keys\",\n side_effect=fake_save,\n ) as ms:\n yield ml, ms, storage\n\n\nclass TestMaskKey:\n def test_masque_cle_longue(self):\n assert _mask_key(\"sk-dee...-pro\") == \"sk-d****pro\"\n\n def test_masque_cle_courte(self):\n assert _mask_key(\"abc123\") == \"abc1****\"\n\n def test_masque_cle_vide(self):\n assert _mask_key(\"\") == \"****\"\n\n\nclass TestListApiKeys:\n async def test_liste_vide(self, client, mock_storage):\n resp = await client.get(\"/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"providers\"] == []\n\n async def test_liste_avec_cles(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-dee...-123\"\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.get(\"/apikeys\")\n assert resp.status_code == 200\n data = resp.json()\n assert len(data[\"providers\"]) == 2\n d = [p for p in data[\"providers\"] if p[\"provider\"] == \"deepseek\"][0]\n assert d[\"configured\"] is True\n assert \"sk-dee...-123\" not in d[\"key_preview\"]\n\n\nclass TestSaveApiKey:\n async def test_sauvegarder_cle(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"openai\"] = \"sk-old-key\"\n resp = await client.post(\n \"/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \"sk-dee...-key\"},\n )\n assert resp.status_code == 201\n data = resp.json()\n assert data[\"status\"] == \"saved\"\n assert storage[\"providers\"][\"deepseek\"] == \"sk-dee...-key\"\n assert storage[\"providers\"][\"openai\"] == \"sk-old-key\"\n\n async def test_cle_vide_refusee(self, client, mock_storage):\n resp = await client.post(\n \"/apikeys\",\n json={\"provider\": \"deepseek\", \"key\": \" \"},\n )\n assert resp.status_code == 400\n\n async def test_provider_invalide_refuse(self, client, mock_storage):\n resp = await client.post(\n \"/apikeys\",\n json={\"provider\": \"\", \"key\": \"sk-test\"},\n )\n assert resp.status_code == 422\n\n\nclass TestDeleteApiKey:\n async def test_supprimer_cle_existante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"][\"deepseek\"] = \"sk-key-1\"\n storage[\"providers\"][\"openai\"] = \"sk-key-2\"\n resp = await client.delete(\"/apikeys/deepseek\")\n assert resp.status_code == 200\n data = resp.json()\n assert data[\"status\"] == \"deleted\"\n assert \"deepseek\" not in storage[\"providers\"]\n assert \"openai\" in storage[\"providers\"]\n\n async def test_supprimer_cle_inexistante(self, client, mock_storage):\n _, _, storage = mock_storage\n storage[\"providers\"] = {}\n resp = await client.delete(\"/apikeys/deepseek\")\n assert resp.status_code == 404\n\n\nclass TestMaskFunction:\n def test_masque_cle_exactement_10_caracteres(self):\n assert _mask_key(\"1234567890\") == \"1234****\"\n\n def test_masque_cle_longue_avec_special_chars(self):\n assert _mask_key(\"sk-ant...-abc\") == \"sk-a****abc\"\n\n def test_masque_cle_ne_logge_pas_la_cle(self):\n key = \"sk-sup...2345\"\n masked = _mask_key(key)\n assert key not in masked\n assert len(masked) < len(key)\n"}}}}