/
liquid-g
/
liquid-code
Обзор
Документация
Войти
/
liquid-g
/
liquid-code
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
develop-0.4
src/liquidcode/test.py
155 строк
5 KB
User
0.3.0-RC - дописаны тесты и мелкие исправления
04 июл 2026, 13:07
04 июл 2026, 13:07
40ad8b8
Код
Авторство
О чём код?
""" Тестовый клиент для LiquidCode. Позволяет выполнять запросы к приложению без реального HTTP-сервера. """ import json from typing import Any, Dict, Optional, Union from .http import HttpRequest, HttpResponse from .kernel import Kernel from .middleware import BodyParserMiddleware class TestResponse: """ Ответ тестового клиента. """ def __init__(self, response: HttpResponse): self._response = response @property def status(self) -> int: """HTTP-статус ответа.""" return self._response.get_status() @property def headers(self) -> Dict[str, str]: """Заголовки ответа.""" return self._response.get_headers() @property def content(self) -> Any: """Содержимое ответа (сырое).""" return self._response.get_content() def json(self) -> Union[Dict[str, Any], list]: """Возвращает содержимое ответа как JSON-объект.""" content = self._response.get_content() if isinstance(content, dict): return content elif isinstance(content, str): return json.loads(content) elif isinstance(content, bytes): return json.loads(content.decode("utf-8")) else: return content def text(self) -> str: """Возвращает содержимое ответа как строку.""" content = self._response.get_content() if isinstance(content, bytes): return content.decode("utf-8") return str(content) class TestClient: """ Тестовый клиент для вызова приложения без HTTP-сервера. Пример: app = Application() client = TestClient(app) response = client.get('/users') assert response.status == 200 assert response.json() == {'users': []} """ __test__ = False # чтобы pytest не пытался собрать этот класс как тестовый def __init__(self, app): self.app = app self.kernel: Kernel = app.kernel # Добавляем BodyParserMiddleware по умолчанию для парсинга JSON/form-data self.kernel.add_middleware(BodyParserMiddleware()) def request( self, method: str, path: str, headers: Optional[Dict[str, str]] = None, body: Optional[Union[Dict[str, Any], str, bytes]] = None, query_params: Optional[Dict[str, str]] = None, ) -> TestResponse: """ Выполняет HTTP-запрос к приложению. Args: method: HTTP-метод (GET, POST, PUT, PATCH, DELETE, WEBSOCKET). path: Путь (может включать query-строку). headers: Заголовки запроса. body: Тело запроса (словарь → JSON, строка → как есть, байты → как есть). query_params: Query-параметры (добавляются к path). Returns: TestResponse """ # Добавляем query-параметры к path if query_params: from urllib.parse import urlencode sep = "&" if "?" in path else "?" path = f"{path}{sep}{urlencode(query_params)}" # Преобразуем тело body_bytes = b"" if body is not None: if isinstance(body, dict): body_bytes = json.dumps(body).encode("utf-8") headers = headers or {} if "Content-Type" not in headers: headers["Content-Type"] = "application/json" elif isinstance(body, str): body_bytes = body.encode("utf-8") elif isinstance(body, bytes): body_bytes = body # Создаём HttpRequest request = HttpRequest( path=path, method=method, headers=headers or {}, body=body_bytes, ) # Вызываем ядро response = self.kernel.handle(request) # Возвращаем обёртку return TestResponse(response) def get(self, path: str, **kwargs) -> TestResponse: """GET-запрос.""" return self.request("GET", path, **kwargs) def post(self, path: str, **kwargs) -> TestResponse: """POST-запрос.""" return self.request("POST", path, **kwargs) def put(self, path: str, **kwargs) -> TestResponse: """PUT-запрос.""" return self.request("PUT", path, **kwargs) def patch(self, path: str, **kwargs) -> TestResponse: """PATCH-запрос.""" return self.request("PATCH", path, **kwargs) def delete(self, path: str, **kwargs) -> TestResponse: """DELETE-запрос.""" return self.request("DELETE", path, **kwargs) def websocket(self, path: str, **kwargs) -> TestResponse: """WebSocket-запрос (имитация).""" return self.request("WEBSOCKET", path, **kwargs)