mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-15 17:30:13 +08:00
* refactor: migrate to fastapi * structure refactor * fix: pyright fix * refactor: improve error handling and public messages in plugin services * feat(api): refactor API client integration and enhance request handling - Updated API client configuration to use a dedicated HTTP client. - Introduced utility functions for generating options, queries, and form data for API requests. - Refactored multiple API methods to utilize the new utility functions for improved consistency and readability. - Renamed types for clarity and updated import statements accordingly. feat(docs): add script to update OpenAPI JSON from YAML spec - Created a Python script to convert OpenAPI YAML specification to JSON format. - The script supports customizable input and output paths. - Ensured the script handles directory creation for output paths and validates the YAML structure. * fix * feat(auth): implement rate limiting for v1 login endpoint and enhance request handling * Refactor dashboard API routers to use legacy_router for backward compatibility - Changed all instances of dashboard_router to legacy_router across multiple API modules including platform, plugins, providers, sessions, skills, stats, subagents, t2i, tools, updates, and asgi_runtime. - Updated route definitions to ensure existing endpoints remain functional under the new router structure. - Introduced support for Quart request context in asgi_runtime to enhance compatibility with existing Quart-based plugins. - Added a test case to validate the functionality of the new Quart request context handling in plugin extensions. * chore: remove cli test * fix: update dashboard tests for fastapi migration * chore: satisfy ruff checks * fix: update openapi api key scopes * fix: sync config scope chip selection * fix: restore quart dependency * docs: clarify quart plugin api compatibility * docs: update openapi scope documentation * fix: use singular skill openapi scope * fix: hide update service exception details * fix: address fastapi review comments * fix: address dashboard review findings * docs: revert unrelated package deployment changes * docs: update agent api generation guidance * feat: add plugin page web api helpers * docs: add plugin page bridge demo * fix: type plugin upload files * fix: stabilize plugin page uploads * fix: type plugin web request proxy * docs: remove plugin page docs example * fix: authenticate plugin page SSE bridge
195 lines
6.0 KiB
Python
195 lines
6.0 KiB
Python
"""Tests for astrbot.core.star.base module."""
|
|
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
class TestStarBase:
|
|
"""Test cases for the Star base class."""
|
|
|
|
def test_star_class_exists(self):
|
|
"""Test that Star class can be imported."""
|
|
from astrbot.core.star import Star
|
|
|
|
assert Star is not None
|
|
|
|
def test_star_init_with_context(self):
|
|
"""Test Star initialization with a context-like object."""
|
|
from astrbot.core.star import Star
|
|
|
|
# Create a mock context with get_config method
|
|
mock_context = MagicMock()
|
|
mock_context.get_config.return_value = MagicMock()
|
|
|
|
# Create a concrete Star subclass for testing
|
|
class TestStar(Star):
|
|
name = "test_star"
|
|
author = "test_author"
|
|
|
|
star = TestStar(context=mock_context)
|
|
|
|
assert star.context is mock_context
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_text_to_image_with_config(self):
|
|
"""Test text_to_image method with valid config."""
|
|
from astrbot.core.star import Star
|
|
|
|
mock_context = MagicMock()
|
|
mock_config = MagicMock()
|
|
mock_config.get.return_value = "default_template"
|
|
mock_context.get_config.return_value = mock_config
|
|
|
|
class TestStar(Star):
|
|
name = "test_star"
|
|
author = "test_author"
|
|
|
|
star = TestStar(context=mock_context)
|
|
|
|
with patch(
|
|
"astrbot.core.star.base.html_renderer.render_t2i",
|
|
new_callable=AsyncMock,
|
|
) as mock_render:
|
|
mock_render.return_value = "http://example.com/image.png"
|
|
result = await star.text_to_image("test text", return_url=True)
|
|
|
|
mock_render.assert_called_once_with(
|
|
"test text",
|
|
return_url=True,
|
|
template_name="default_template",
|
|
)
|
|
assert result == "http://example.com/image.png"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_text_to_image_without_config(self):
|
|
"""Test text_to_image method when get_config returns None."""
|
|
from astrbot.core.star import Star
|
|
|
|
mock_context = MagicMock()
|
|
mock_context.get_config.return_value = None
|
|
|
|
class TestStar(Star):
|
|
name = "test_star"
|
|
author = "test_author"
|
|
|
|
star = TestStar(context=mock_context)
|
|
|
|
with patch(
|
|
"astrbot.core.star.base.html_renderer.render_t2i",
|
|
new_callable=AsyncMock,
|
|
) as mock_render:
|
|
mock_render.return_value = "http://example.com/image.png"
|
|
result = await star.text_to_image("test text", return_url=False)
|
|
|
|
mock_render.assert_called_once_with(
|
|
"test text",
|
|
return_url=False,
|
|
template_name=None,
|
|
)
|
|
assert result == "http://example.com/image.png"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_html_render(self):
|
|
"""Test html_render method."""
|
|
from astrbot.core.star import Star
|
|
|
|
mock_context = MagicMock()
|
|
|
|
class TestStar(Star):
|
|
name = "test_star"
|
|
author = "test_author"
|
|
|
|
star = TestStar(context=mock_context)
|
|
|
|
with patch(
|
|
"astrbot.core.star.base.html_renderer.render_custom_template",
|
|
new_callable=AsyncMock,
|
|
) as mock_render:
|
|
mock_render.return_value = "http://example.com/rendered.png"
|
|
result = await star.html_render(
|
|
"<html>{{ data }}</html>",
|
|
{"data": "test"},
|
|
return_url=True,
|
|
)
|
|
|
|
mock_render.assert_called_once_with(
|
|
"<html>{{ data }}</html>",
|
|
{"data": "test"},
|
|
return_url=True,
|
|
options=None,
|
|
)
|
|
assert result == "http://example.com/rendered.png"
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_initialize_and_terminate(self):
|
|
"""Test that initialize and terminate methods can be overridden."""
|
|
from astrbot.core.star import Star
|
|
|
|
class TestStar(Star):
|
|
name = "test_star"
|
|
author = "test_author"
|
|
|
|
async def initialize(self) -> None:
|
|
self.initialized = True
|
|
|
|
async def terminate(self) -> None:
|
|
self.terminated = True
|
|
|
|
mock_context = MagicMock()
|
|
star = TestStar(context=mock_context)
|
|
|
|
await star.initialize()
|
|
assert star.initialized is True
|
|
|
|
await star.terminate()
|
|
assert star.terminated is True
|
|
|
|
def test_star_metadata_registration(self):
|
|
"""Test that Star subclass is automatically registered."""
|
|
from astrbot.core.star import star_registry
|
|
|
|
class UniqueTestStar:
|
|
"""Not a Star subclass, should not be registered."""
|
|
|
|
pass
|
|
|
|
# Verify Star subclass gets registered
|
|
initial_count = len(star_registry)
|
|
|
|
# Note: This test verifies the __init_subclass__ mechanism
|
|
# The actual registration happens when a class inherits from Star
|
|
assert len(star_registry) >= initial_count
|
|
|
|
|
|
class TestNoCircularImports:
|
|
"""Test that there are no circular import issues."""
|
|
|
|
def test_import_star_module(self):
|
|
"""Test that star module can be imported without circular import errors."""
|
|
import astrbot.core.star
|
|
|
|
assert astrbot.core.star is not None
|
|
|
|
def test_import_pipeline_module(self):
|
|
"""Test that pipeline module can be imported without circular import errors."""
|
|
import astrbot.core.pipeline
|
|
|
|
assert astrbot.core.pipeline is not None
|
|
|
|
def test_import_both_modules(self):
|
|
"""Test that both modules can be imported together."""
|
|
|
|
# Verify key exports are available
|
|
from astrbot.core.star import Context, PluginManager, Star
|
|
|
|
assert Context is not None
|
|
assert Star is not None
|
|
assert PluginManager is not None
|
|
|
|
def test_import_pipeline_context(self):
|
|
"""Test that PipelineContext can be imported."""
|
|
from astrbot.core.pipeline.context import PipelineContext
|
|
|
|
assert PipelineContext is not None
|