Coverage for tests/test_cli_pyproject.py: 100%
62 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-11 09:18 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-11-11 09:18 +0000
1from pathlib import Path 1abcdefghijklmn
2from unittest.mock import patch 1abcdefghijklmn
4import uvicorn 1abcdefghijklmn
5from typer.testing import CliRunner 1abcdefghijklmn
7from fastapi_cli.cli import app 1abcdefghijklmn
8from tests.utils import changing_dir 1abcdefghijklmn
10runner = CliRunner() 1abcdefghijklmn
12assets_path = Path(__file__).parent / "assets" 1abcdefghijklmn
15def test_dev_with_pyproject_app_config_uses() -> None: 1abcdefghijklmn
16 with ( 1QR
17 changing_dir(assets_path / "pyproject_config"),
18 patch.object(uvicorn, "run") as mock_run,
19 ):
20 result = runner.invoke(app, ["dev"]) 1QUVWXRYZ012345
21 assert result.exit_code == 0, result.output 1QUVWXRYZ012345
23 assert mock_run.call_args.kwargs["app"] == "my_module:app" 1QUVWXRYZ012345
24 assert mock_run.call_args.kwargs["host"] == "127.0.0.1" 1QUVWXRYZ012345
25 assert mock_run.call_args.kwargs["port"] == 8000 1QUVWXRYZ012345
26 assert mock_run.call_args.kwargs["reload"] is True 1QUVWXRYZ012345
28 assert "Using import string: my_module:app" in result.output 1QUVWXRYZ012345
29 # a configured entrypoint is not auto-discovery
30 assert "(auto-discovered" not in result.output 1QUVWXRYZ012345
31 assert "Configuration sources:" not in result.output 1QUVWXRYZ012345
34def test_run_with_pyproject_app_config() -> None: 1abcdefghijklmn
35 with ( 1ST
36 changing_dir(assets_path / "pyproject_config"),
37 patch.object(uvicorn, "run") as mock_run,
38 ):
39 result = runner.invoke(app, ["run"]) 1S6789T!#$%'()*
40 assert result.exit_code == 0, result.output 1S6789T!#$%'()*
42 assert mock_run.call_args.kwargs["app"] == "my_module:app" 1S6789T!#$%'()*
43 assert mock_run.call_args.kwargs["host"] == "0.0.0.0" 1S6789T!#$%'()*
44 assert mock_run.call_args.kwargs["port"] == 8000 1S6789T!#$%'()*
45 assert mock_run.call_args.kwargs["reload"] is False 1S6789T!#$%'()*
47 assert "Using import string: my_module:app" in result.output 1S6789T!#$%'()*
48 assert "(auto-discovered" not in result.output 1S6789T!#$%'()*
49 assert "Configuration sources:" not in result.output 1S6789T!#$%'()*
52def test_cli_arg_overrides_pyproject_config() -> None: 1abcdefghijklmn
53 with ( 1+,
54 changing_dir(assets_path / "pyproject_config"),
55 patch.object(uvicorn, "run") as mock_run,
56 ):
57 result = runner.invoke(app, ["dev", "another_module.py"]) 1+-./:,;=?@[]^_
59 assert result.exit_code == 0, result.output 1+-./:,;=?@[]^_
61 assert mock_run.call_args.kwargs["app"] == "another_module:app" 1+-./:,;=?@[]^_
62 assert "Using import string: another_module:app" in result.output 1+-./:,;=?@[]^_
63 assert "Configuration sources:" not in result.output 1+-./:,;=?@[]^_
66def test_pyproject_app_config_invalid_format() -> None: 1abcdefghijklmn
67 test_dir = assets_path / "pyproject_invalid_config" 1CDEFGHIJKLMNOP
68 test_dir.mkdir(exist_ok=True) 1CDEFGHIJKLMNOP
70 pyproject_file = test_dir / "pyproject.toml" 1CDEFGHIJKLMNOP
71 pyproject_file.write_text(""" 1CDEFGHIJKLMNOP
72[tool.fastapi]
73entrypoint = "invalid_format_without_colon"
74""")
76 try: 1CDEFGHIJKLMNOP
77 with changing_dir(test_dir): 1CDEFGHIJKLMNOP
78 result = runner.invoke(app, ["dev"]) 1CDEFGHIJKLMNOP
79 assert result.exit_code == 1 1CDEFGHIJKLMNOP
80 assert ( 1CDEFGHIJKLMNOP
81 "Import string must be in the format module.submodule:app_name"
82 in result.output
83 )
84 finally:
85 pyproject_file.unlink() 1CDEFGHIJKLMNOP
86 test_dir.rmdir() 1CDEFGHIJKLMNOP
89def test_pyproject_validation_error() -> None: 1abcdefghijklmn
90 test_dir = assets_path / "pyproject_validation_error" 1opqrstuvwxyzAB
91 test_dir.mkdir(exist_ok=True) 1opqrstuvwxyzAB
93 pyproject_file = test_dir / "pyproject.toml" 1opqrstuvwxyzAB
94 pyproject_file.write_text(""" 1opqrstuvwxyzAB
95[tool.fastapi]
96entrypoint = 123
97""")
99 try: 1opqrstuvwxyzAB
100 with changing_dir(test_dir): 1opqrstuvwxyzAB
101 result = runner.invoke(app, ["dev"]) 1opqrstuvwxyzAB
102 assert result.exit_code == 1 1opqrstuvwxyzAB
103 assert "Invalid configuration in pyproject.toml:" in result.output 1opqrstuvwxyzAB
104 assert "entrypoint" in result.output.lower() 1opqrstuvwxyzAB
105 finally:
106 pyproject_file.unlink() 1opqrstuvwxyzAB
107 test_dir.rmdir() 1opqrstuvwxyzAB