@@ -0,0 +1,98 @@
|
||||
"""Фоновая инициализация и /api/startup/status."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import patch
|
||||
|
||||
from app import create_app, db
|
||||
from app.services.startup_background import is_reloader_parent_process, schedule_background_startup
|
||||
from app.services.startup_state import mark_startup_ready, reset_startup_state
|
||||
from config import TestingConfig
|
||||
|
||||
|
||||
class StartupBgConfig(TestingConfig):
|
||||
_TMP = tempfile.mkdtemp(prefix="wesp-startup-bg-")
|
||||
BASE_DIR = _TMP
|
||||
DATA_DIR = os.path.join(_TMP, "data")
|
||||
SQLALCHEMY_DATABASE_URI = f"sqlite:///{os.path.join(_TMP, 'recipes_test.db')}"
|
||||
SQLALCHEMY_BINDS = {"reports": f"sqlite:///{os.path.join(_TMP, 'reports_test.db')}"}
|
||||
WESP_BACKGROUND_STARTUP = False
|
||||
|
||||
|
||||
class StartupBackgroundTests(unittest.TestCase):
|
||||
def setUp(self) -> None:
|
||||
reset_startup_state()
|
||||
self.app = create_app(StartupBgConfig)
|
||||
self.client = self.app.test_client()
|
||||
self.ctx = self.app.app_context()
|
||||
self.ctx.push()
|
||||
mark_startup_ready()
|
||||
db.create_all()
|
||||
|
||||
def tearDown(self) -> None:
|
||||
db.session.remove()
|
||||
db.drop_all()
|
||||
self.ctx.pop()
|
||||
reset_startup_state()
|
||||
|
||||
def test_startup_status_ready(self) -> None:
|
||||
r = self.client.get("/api/startup/status")
|
||||
self.assertEqual(r.status_code, 200)
|
||||
body = r.get_json()
|
||||
self.assertTrue(body.get("ready"))
|
||||
|
||||
def test_reloader_parent_skips_blocking_startup(self) -> None:
|
||||
app = create_app(StartupBgConfig)
|
||||
app.debug = True
|
||||
with patch.dict(os.environ, {}, clear=False):
|
||||
os.environ.pop("WERKZEUG_RUN_MAIN", None)
|
||||
with patch(
|
||||
"app.services.startup_background.is_running_from_reloader",
|
||||
create=True,
|
||||
return_value=False,
|
||||
):
|
||||
self.assertTrue(is_reloader_parent_process(app))
|
||||
with patch("app.services.startup_background.run_blocking_startup_tasks") as blocked:
|
||||
self.assertFalse(schedule_background_startup(app))
|
||||
blocked.assert_not_called()
|
||||
|
||||
def test_health_during_starting(self) -> None:
|
||||
reset_startup_state()
|
||||
from app.services.startup_state import set_startup_phase
|
||||
|
||||
set_startup_phase("migrations", "Тест")
|
||||
with self.app.app_context():
|
||||
self.app.config["WESP_DEFERRED_STARTUP"] = True
|
||||
from app.services.update_health import build_health_payload
|
||||
|
||||
payload = build_health_payload(self.app)
|
||||
self.assertTrue(payload.get("starting"))
|
||||
self.assertFalse(payload.get("ok"))
|
||||
|
||||
def test_scales_not_redirected_to_starting_while_migrations(self) -> None:
|
||||
reset_startup_state()
|
||||
from app.services.startup_state import set_startup_phase
|
||||
|
||||
set_startup_phase("migrations", "Тест")
|
||||
self.app.config["WESP_DEFERRED_STARTUP"] = True
|
||||
r = self.client.get("/scales", follow_redirects=False)
|
||||
loc = r.headers.get("Location") or ""
|
||||
self.assertNotIn("/starting", loc)
|
||||
|
||||
def test_stream_weight_not_redirected_while_migrations(self) -> None:
|
||||
reset_startup_state()
|
||||
from app.services.startup_state import set_startup_phase
|
||||
|
||||
set_startup_phase("migrations", "Тест")
|
||||
self.app.config["WESP_DEFERRED_STARTUP"] = True
|
||||
r = self.client.get("/stream_weight")
|
||||
self.assertNotEqual(r.status_code, 302)
|
||||
loc = r.headers.get("Location") or ""
|
||||
self.assertNotIn("/starting", loc)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user