from __future__ import annotations from pathlib import Path from iticli.cli import ( ProjectContext, alembic_base_cmd, detect_project, extract_message, find_optional_extra, has_package, normalize_version, parse_run_args, version_is_newer, ) def write(path: Path, text: str) -> None: path.parent.mkdir(parents=True, exist_ok=True) path.write_text(text, encoding="utf-8") def test_detect_framework_project(tmp_path: Path) -> None: write( tmp_path / "pyproject.toml", """ [project] name = "iti-flask" dependencies = [] """, ) write(tmp_path / "iti" / "app.py", "") write(tmp_path / "copier.yml", "") ctx = detect_project(tmp_path) assert ctx.kind == "framework" def test_detect_business_project(tmp_path: Path) -> None: write( tmp_path / "pyproject.toml", """ [project] name = "demo" dependencies = [ "iti-flask @ git+https://git.noahlan.cn/iti-framework/iTi-Flask.git@v0.2.4", "iti-system @ git+https://git.noahlan.cn/iti-framework/iTi-System.git@v0.2.4", ] """, ) write(tmp_path / "main.py", "") (tmp_path / "app").mkdir() write(tmp_path / "migrations" / "alembic.ini", "") ctx = detect_project(tmp_path) assert ctx.kind == "business" assert ctx.has_system is True def test_detect_system_project(tmp_path: Path) -> None: write( tmp_path / "pyproject.toml", """ [project] name = "iti-system" dependencies = ["iti-flask"] """, ) write(tmp_path / "iti_system" / "module.py", "") write(tmp_path / "iti_system" / "cli.py", "") ctx = detect_project(tmp_path) assert ctx.kind == "system" def test_detect_from_child_directory(tmp_path: Path) -> None: write( tmp_path / "pyproject.toml", """ [project] name = "demo" dependencies = ["iti-flask @ git+https://example.test/iTi-Flask.git"] """, ) write(tmp_path / "main.py", "") child = tmp_path / "app" / "modules" child.mkdir(parents=True) write(tmp_path / "migrations" / "alembic.ini", "") ctx = detect_project(child) assert ctx.root == tmp_path assert ctx.kind == "business" def test_has_package_reads_uv_sources() -> None: pyproject = { "project": {"dependencies": []}, "tool": {"uv": {"sources": {"iti-flask": {"git": "https://example.test/repo.git"}}}}, } assert has_package(pyproject, "iti-flask") is True def test_find_optional_extra_prefers_project_extra_name() -> None: pyproject = {"project": {"optional-dependencies": {"odbc": [], "dev": []}}} assert find_optional_extra(pyproject, ["odbc", "erp"]) == "odbc" def test_business_alembic_uses_template_config(tmp_path: Path) -> None: ctx = ProjectContext(tmp_path, "business", {}, False) assert alembic_base_cmd(ctx) == ["uv", "run", "alembic", "-c", "migrations/alembic.ini"] def test_framework_alembic_uses_default_config(tmp_path: Path) -> None: ctx = ProjectContext(tmp_path, "framework", {}, False) assert alembic_base_cmd(ctx) == ["uv", "run", "alembic"] def test_parse_run_args_accepts_env_and_port() -> None: assert parse_run_args("test", "9000") == ("test", "9000") assert parse_run_args("9000", None) == ("dev", "9000") assert parse_run_args("default", None) == ("dev", "8000") def test_extract_message_accepts_remainder_flags() -> None: rest = ["-m", "alice add order table", "--head", "head"] assert extract_message(rest) == "alice add order table" assert rest == ["--head", "head"] def test_version_helpers() -> None: assert normalize_version("v1.2.3") == "1.2.3" assert version_is_newer("1.2.3", "1.2.4") is True assert version_is_newer("1.2.3", "1.2.3") is False