# coding=utf-8 """Tests for the embedded DDNS dashboard service and HTTP server.""" from __future__ import unicode_literals import copy import io import json import logging import os import shutil import sys import tempfile import threading import time from __init__ import MagicMock, patch, unittest try: from urllib.error import HTTPError from urllib.request import Request, urlopen except ImportError: # Python 2 from urllib2 import HTTPError, Request, urlopen from ddns.provider import get_provider_class from ddns.mcp import CLIENT_CAPABILITIES_KEY, PROTOCOL_VERSION, PROTOCOL_VERSION_KEY from ddns.web.server import DashboardRequestHandler, _resource_bytes, _write_stdout, create_server, serve from ddns.web.scheduler import WebScheduler from ddns.web.service import ( CONFIG_MODEL, ConfigValidationError, DashboardOperationError, DashboardService, _replace_file, resolve_config_path, validate_document, ) def _valid_config(line="default"): """Return a small valid dashboard configuration.""" return { "$schema": "https://ddns.newfuture.cc/schema/v4.1.json", "ssl": "auto", "proxy": "DIRECT", "cache": True, "cache_max_age": 259200, "log": {"level": "INFO"}, "providers": [ { "provider": "debug", "id": "", "token": "", "ipv4": ["home.example.com"], "ipv6": [], "index4": "public", "index6": False, "ttl": 300, "line": line, } ], } class TestDashboardAssets(unittest.TestCase): """Test the standalone source and packaged asset loading paths.""" def test_frontend_sources_live_in_top_level_web_directory(self): """Keep one canonical frontend source outside the Python package.""" project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) for asset_name in ("index.html", "dashboard.css", "dashboard.js", "ddns.svg"): self.assertTrue(os.path.isfile(os.path.join(project_root, "web", asset_name))) self.assertFalse(os.path.isfile(os.path.join(project_root, "ddns", "web", "static", asset_name))) @patch("ddns.web.server.pkgutil.get_data") def test_resource_loader_prefers_standalone_source(self, mock_get_data): """Read live frontend sources directly during repository development.""" self.assertIn(b"