Files
Octop/tests/unit/api/test_exception_handlers.py
Finn Lewis 4aab7c11ec Feature/migrate im channel cronjob from ace (#201)
* fix: Update schema when restoring octop/lightclaw backups

* feat: enhance error logging for OctopError in exception handlers

* feat: enhance backup restore process to include IM channel reloading

* feat: extend backup restore functionality to include cron job reloading

* feat: add JWT secret capture and restore functionality during backup processes

* fix: update Chinese translation for presetProviders term in zh.json

* feat: implement Unix crontab semantics for weekday handling in cron triggers

Added functionality to translate numeric Unix weekdays to names and updated the cron trigger builder to support Unix-style expressions. Enhanced unit tests to validate the new behavior for various weekday formats and ranges.

* feat: enhance backup restore functionality with ownership remapping

- Updated `restore_backup_file` to accept a `user` parameter for identifying the restoring admin.
- Added `owner_user_id` option in CLI for specifying ownership during LightClaw migration archives.
- Implemented user ownership remapping in the database during system backup restoration.
- Enhanced user handling in backup processes to ensure proper ownership assignment and data integrity.
- Updated tests to validate new ownership remapping behavior during migration restores.

* refactor: streamline SQL query formatting in backup test case

- Simplified the SQL query execution in the `_make_migration_backup` function by removing unnecessary line breaks for improved readability.
2026-08-10 21:43:14 +08:00

61 lines
2.1 KiB
Python

"""Exception handlers log server-side OctopError details."""
from __future__ import annotations
from pathlib import Path
from unittest.mock import patch
import httpx
import pytest
from tests.support.app import ensure_control_plane_bound, write_octop_config
from octop.api.app import build_app
from octop.infra.errors import ErrorCode, OctopError
from octop.infra.server import OctopServer
@pytest.fixture
async def client(tmp_path: Path):
# Disable dashboard so SPA ``/{full_path:path}`` is not mounted; otherwise
# routes registered after build_app never match (first-match-wins).
write_octop_config(tmp_path, enable_dashboard=False)
srv = OctopServer(home=tmp_path)
await srv.start()
await ensure_control_plane_bound(srv)
app = build_app(srv)
# Outside /api so JWT middleware does not intercept.
@app.get("/_test/octop-500")
async def _boom() -> None:
raise OctopError(ErrorCode.INTERNAL_ERROR, "jwt secret missing")
@app.get("/_test/octop-401")
async def _auth() -> None:
raise OctopError(ErrorCode.AUTH_FAILED, "missing credentials")
async with httpx.AsyncClient(
transport=httpx.ASGITransport(app=app), base_url="http://testserver"
) as c:
yield c
await srv.stop()
async def test_octop_error_5xx_is_logged(client: httpx.AsyncClient) -> None:
with patch("octop.api.app.logger") as mock_logger:
r = await client.get("/_test/octop-500", headers={"Accept-Language": "zh"})
assert r.status_code == 500
assert r.json()["error"]["message"] == "服务器内部错误。"
mock_logger.error.assert_called_once()
args, kwargs = mock_logger.error.call_args
rendered = args[0] % args[1:]
assert "INTERNAL_ERROR" in rendered
assert "jwt secret missing" in rendered
assert kwargs.get("exc_info") is not None
async def test_octop_error_4xx_is_not_logged(client: httpx.AsyncClient) -> None:
with patch("octop.api.app.logger") as mock_logger:
r = await client.get("/_test/octop-401")
assert r.status_code == 401
mock_logger.error.assert_not_called()