import unittest import os from mes_dashboard.app import create_app import mes_dashboard.core.database as db class AppFactoryTests(unittest.TestCase): def setUp(self): db._ENGINE = None def test_create_app_default_config(self): app = create_app("development") self.assertTrue(app.config.get("DEBUG")) self.assertEqual(app.config.get("ENV"), "development") cache = app.extensions.get("cache") self.assertIsNotNone(cache) cache.set("app_factory_probe", {"ok": True}, 30) self.assertEqual(cache.get("app_factory_probe"), {"ok": True}) def test_create_app_production_config(self): old_secret = os.environ.get("SECRET_KEY") old_conda_env_name = os.environ.get("CONDA_ENV_NAME") try: os.environ["SECRET_KEY"] = "test-production-secret-key" # Keep runtime-contract strict validation aligned with active env. os.environ["CONDA_ENV_NAME"] = os.environ.get("CONDA_DEFAULT_ENV", "base") app = create_app("production") self.assertFalse(app.config.get("DEBUG")) self.assertEqual(app.config.get("ENV"), "production") finally: if old_secret is None: os.environ.pop("SECRET_KEY", None) else: os.environ["SECRET_KEY"] = old_secret if old_conda_env_name is None: os.environ.pop("CONDA_ENV_NAME", None) else: os.environ["CONDA_ENV_NAME"] = old_conda_env_name def test_create_app_independent_instances(self): app1 = create_app("development") db._ENGINE = None app2 = create_app("development") self.assertIsNot(app1, app2) def test_routes_registered(self): app = create_app("development") rules = {rule.rule for rule in app.url_map.iter_rules()} expected = { "/", "/portal-shell", "/tables", "/resource", "/wip-overview", "/wip-detail", "/hold-overview", "/reject-history", "/excel-query", "/query-tool", "/tmtt-defect", "/api/wip/overview/summary", "/api/wip/overview/matrix", "/api/wip/overview/hold", "/api/hold-overview/summary", "/api/hold-overview/matrix", "/api/hold-overview/treemap", "/api/hold-overview/lots", "/api/wip/detail/", "/api/wip/meta/workcenters", "/api/wip/meta/packages", "/api/resource/status/summary", "/api/dashboard/kpi", "/api/portal/navigation", "/api/excel-query/upload", "/api/query-tool/resolve", "/api/tmtt-defect/analysis", "/api/reject-history/summary", } missing = expected - rules self.assertFalse(missing, f"Missing routes: {sorted(missing)}") def test_portal_spa_flag_default_enabled(self): old = os.environ.pop("PORTAL_SPA_ENABLED", None) try: app = create_app("testing") self.assertTrue(app.config.get("PORTAL_SPA_ENABLED")) client = app.test_client() response = client.get("/", follow_redirects=False) self.assertEqual(response.status_code, 302) location = response.headers.get("Location", "") self.assertTrue(location.startswith("/portal-shell")) finally: if old is not None: os.environ["PORTAL_SPA_ENABLED"] = old def test_portal_spa_flag_disabled_via_env(self): old = os.environ.get("PORTAL_SPA_ENABLED") os.environ["PORTAL_SPA_ENABLED"] = "false" try: app = create_app("testing") self.assertFalse(app.config.get("PORTAL_SPA_ENABLED")) client = app.test_client() response = client.get("/") html = response.data.decode("utf-8") self.assertIn('data-portal-spa-enabled="false"', html) finally: if old is None: os.environ.pop("PORTAL_SPA_ENABLED", None) else: os.environ["PORTAL_SPA_ENABLED"] = old def test_portal_spa_flag_enabled_via_env(self): old = os.environ.get("PORTAL_SPA_ENABLED") os.environ["PORTAL_SPA_ENABLED"] = "true" try: app = create_app("testing") self.assertTrue(app.config.get("PORTAL_SPA_ENABLED")) client = app.test_client() response = client.get("/", follow_redirects=False) self.assertEqual(response.status_code, 302) location = response.headers.get("Location", "") self.assertTrue(location.startswith("/portal-shell")) finally: if old is None: os.environ.pop("PORTAL_SPA_ENABLED", None) else: os.environ["PORTAL_SPA_ENABLED"] = old if __name__ == "__main__": unittest.main()