Files
codex-app-server/cloud/tests/test_codex_ui_host.py
T
host 3e0ff898e0
ci / test (push) Successful in 45m25s
feat: wire native Codex UI as /console entry, keep classic console at /console-classic
- Vendor codex-ui-stack host/ as cloud/codex-ui-host/ (original/ not vendored, 650MB)
- Bridge emulates 7 methods missing in codex 0.164.0-alpha.9, exposes 29
  experimental-protocol methods (150 -> 179), Linux binary candidates,
  read-only POST /__codex_git
- GET /console 302s to the UI host (:8095) when reachable, else falls back
  to the classic React console; GET /console-classic always serves it
- Alignment tables: docs/codex-native-ui-alignment.md
- Tests: test_console 7, new test_codex_ui_host 4, handler method pin 247 -> 249
2026-11-06 19:03:35 +00:00

81 lines
3.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""Codex 原生 UI host 入仓清单单测(见 docs/codex-native-ui-alignment.md §4 第 4 项)。
只做静态断言,不起服务、不调网络、不读密钥:
- appserver-methods.json 是合法 JSON、179 个方法、无重复;
- app-server-bridge.mjs 里 7 个仿真方法都在(读文件文本断言方法名出现);
- 仓内无 cloud/codex-ui-host/original/ 目录(650MB 原版栈不入仓);
- scripts/run-codex-ui.sh 存在且可执行。
路径一律以仓库根(本文件向上两级)为基准,不写死绝对路径。
"""
import json
import os
import unittest
REPO_ROOT = os.path.dirname(os.path.dirname(
os.path.dirname(os.path.abspath(__file__))))
# §4 适配 A5:150 个 UI 清单方法 + 29 个实验协议方法 = 179。
EXPECTED_METHOD_COUNT = 179
# §4 适配 A1–A4:桥接层仿真的 7 个缺失方法。
SIMULATED_METHODS = [
"thread/stop",
"thread/rollback",
"thread/startAeon",
"interactive/liveSessions/list",
"interactive/session/upload",
"interactive/sessionSandbox/list",
"interactive/sessionSandbox/read",
]
class TestAppserverMethodsJson(unittest.TestCase):
def test_valid_json_179_methods_no_duplicates(self):
path = os.path.join(
REPO_ROOT, "cloud", "codex-ui-host", "host",
"appserver-methods.json")
with open(path, encoding="utf-8") as f:
methods = json.load(f)
self.assertIsInstance(methods, list)
self.assertEqual(len(methods), EXPECTED_METHOD_COUNT)
self.assertTrue(all(isinstance(m, str) for m in methods))
self.assertEqual(len(set(methods)), len(methods),
"appserver-methods.json must not list a method twice")
class TestAppServerBridgeSimulations(unittest.TestCase):
def test_seven_simulated_methods_present(self):
path = os.path.join(
REPO_ROOT, "cloud", "codex-ui-host", "host",
"app-server-bridge.mjs")
with open(path, encoding="utf-8") as f:
text = f.read()
for name in SIMULATED_METHODS:
self.assertIn(name, text,
"%s must be simulated in app-server-bridge.mjs"
% name)
class TestOriginalNotVendored(unittest.TestCase):
def test_no_original_directory_in_repo(self):
self.assertFalse(
os.path.exists(os.path.join(
REPO_ROOT, "cloud", "codex-ui-host", "original")),
"cloud/codex-ui-host/original/ must not be vendored "
"(650MB original stack stays out of the repo)")
class TestRunScript(unittest.TestCase):
def test_run_script_exists_and_is_executable(self):
path = os.path.join(REPO_ROOT, "scripts", "run-codex-ui.sh")
self.assertTrue(os.path.isfile(path),
"scripts/run-codex-ui.sh must exist")
self.assertTrue(os.access(path, os.X_OK),
"scripts/run-codex-ui.sh must be executable")
if __name__ == "__main__":
unittest.main()