290 lines
8.7 KiB
Python
290 lines
8.7 KiB
Python
from __future__ import annotations
|
|
|
|
from typer.testing import CliRunner
|
|
|
|
from wf_cli.app import app
|
|
|
|
runner = CliRunner()
|
|
|
|
|
|
def test_wf_help_lists_lifecycle_groups() -> None:
|
|
result = runner.invoke(app, ["--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "cap" in result.output
|
|
assert "draft" in result.output
|
|
assert "artifact" in result.output
|
|
assert "deploy" in result.output
|
|
assert "run" in result.output
|
|
assert "source" in result.output
|
|
assert "admin" in result.output
|
|
assert "docs" in result.output
|
|
assert "schema" in result.output
|
|
assert "explain" in result.output
|
|
|
|
|
|
def test_wf_main_loads_dotenv_before_invoking_app(monkeypatch) -> None:
|
|
import wf_cli.app as mod
|
|
|
|
calls: list[str] = []
|
|
|
|
monkeypatch.setattr(mod, "load_dotenv", lambda: calls.append("dotenv"))
|
|
monkeypatch.setattr(mod, "app", lambda: calls.append("app"))
|
|
|
|
mod.main()
|
|
|
|
assert calls == ["dotenv", "app"]
|
|
|
|
|
|
def test_wf_run_group_help_exists() -> None:
|
|
result = runner.invoke(app, ["run", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Run workflow deployments" in result.output
|
|
|
|
|
|
def test_root_config_flag_accepted_before_subcommand() -> None:
|
|
result = runner.invoke(app, ["--config", "custom.json", "run", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Run workflow deployments" in result.output
|
|
|
|
|
|
def test_wf_deploy_validate_help_exists() -> None:
|
|
result = runner.invoke(app, ["deploy", "validate", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "Validate one saved workflow deployment" in result.output
|
|
|
|
|
|
def test_wf_run_start_help_exists() -> None:
|
|
result = runner.invoke(app, ["run", "start", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--input-file" in result.output
|
|
|
|
|
|
def test_wf_explain_help_shows_input_modes() -> None:
|
|
result = runner.invoke(app, ["explain", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--input-file" in result.output
|
|
assert "--stdin" in result.output
|
|
assert "--list" in result.output
|
|
|
|
|
|
def test_wf_cap_list_help_exists() -> None:
|
|
result = runner.invoke(app, ["cap", "list", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--format" in result.output
|
|
|
|
|
|
def test_wf_schema_help_describes_catalog_and_verbose_output() -> None:
|
|
result = runner.invoke(app, ["schema", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
output = result.output.lower()
|
|
assert "compact workflow schema outline" in output
|
|
assert "--verbose" in output
|
|
assert "draft" in output
|
|
assert "raw" in output
|
|
assert "core" in output
|
|
|
|
|
|
def test_wf_source_list_help_exists() -> None:
|
|
result = runner.invoke(app, ["source", "list", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--format" in result.output
|
|
assert "--limit" in result.output
|
|
|
|
|
|
def test_wf_admin_connections_help_exists() -> None:
|
|
result = runner.invoke(app, ["admin", "connections", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--format" in result.output
|
|
|
|
|
|
def test_wf_artifact_list_help_exists() -> None:
|
|
result = runner.invoke(app, ["artifact", "list", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--format" in result.output
|
|
|
|
|
|
def test_wf_deploy_save_help_exists() -> None:
|
|
result = runner.invoke(app, ["deploy", "save", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "--binding" in result.output
|
|
|
|
|
|
def test_wf_draft_create_help_accepts_capability_option() -> None:
|
|
result = runner.invoke(app, ["draft", "create", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
output = " ".join(result.output.split())
|
|
assert "--capability" in output
|
|
assert "--title" in output
|
|
|
|
|
|
def test_wf_draft_help_does_not_list_old_create_from_capability() -> None:
|
|
result = runner.invoke(app, ["draft", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "create-from-capability" not in result.output
|
|
|
|
|
|
def test_wf_draft_map_help_explains_replace_merge_and_validate() -> None:
|
|
input_result = runner.invoke(app, ["draft", "set-input", "--help"])
|
|
output_result = runner.invoke(app, ["draft", "set-output", "--help"])
|
|
workflow_output_result = runner.invoke(
|
|
app, ["draft", "set-workflow-output", "--help"]
|
|
)
|
|
|
|
assert input_result.exit_code == 0
|
|
assert output_result.exit_code == 0
|
|
assert workflow_output_result.exit_code == 0
|
|
input_help = " ".join(input_result.output.split())
|
|
output_help = " ".join(output_result.output.split())
|
|
workflow_output_help = " ".join(workflow_output_result.output.split())
|
|
assert "replaces the full input map" in input_help
|
|
assert "Use --merge only" in input_help
|
|
assert "draft validate" in input_help
|
|
assert "input.text=text" in input_help
|
|
assert "input.text=local.text" in input_help
|
|
assert "replaces the full output map" in output_help
|
|
assert "Use --merge only" in output_help
|
|
assert "draft validate" in output_help
|
|
assert "replaces the full workflow output map" in workflow_output_help
|
|
assert "Use --merge only" in workflow_output_help
|
|
assert "GRAPH_SOURCE=OUTPUT_FIELD" in workflow_output_help
|
|
assert "output_schema fields are projected" in workflow_output_help
|
|
assert "draft validate" in workflow_output_help
|
|
|
|
|
|
def test_wf_draft_bind_help_explains_direction() -> None:
|
|
result = runner.invoke(app, ["draft", "bind", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
help_text = " ".join(result.output.split())
|
|
assert "--from" in help_text
|
|
assert "--to" in help_text
|
|
assert "validate" in help_text
|
|
assert "project missing schema" in help_text
|
|
assert "set-input --merge" in help_text
|
|
|
|
|
|
def test_wf_draft_add_step_help_explains_explicit_wiring() -> None:
|
|
result = runner.invoke(app, ["draft", "add-step", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
output = " ".join(result.output.split())
|
|
assert "--capability" in output
|
|
assert "--from-step" in output
|
|
assert "--bind-output" in output
|
|
assert "does not guess" in output
|
|
assert "Repeat the flag" in output
|
|
assert "--input state.title=title --input state.summary=summary" in output
|
|
assert (
|
|
"--bind-output title=state.title --bind-output summary=state.summary" in output
|
|
)
|
|
|
|
|
|
def test_wf_draft_help_does_not_list_old_add_step_from_capability() -> None:
|
|
result = runner.invoke(app, ["draft", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "add-step-from-capability" not in result.output
|
|
|
|
|
|
def test_wf_draft_remove_commands_help_mentions_options() -> None:
|
|
route_result = runner.invoke(app, ["draft", "remove-route", "--help"])
|
|
step_result = runner.invoke(app, ["draft", "remove-step", "--help"])
|
|
binding_result = runner.invoke(app, ["draft", "remove-binding", "--help"])
|
|
|
|
assert route_result.exit_code == 0
|
|
assert "--step" in route_result.output
|
|
assert "--outcome" in route_result.output
|
|
assert step_result.exit_code == 0
|
|
assert "--step" in step_result.output
|
|
assert binding_result.exit_code == 0
|
|
assert "--input" in binding_result.output
|
|
assert "--output" in binding_result.output
|
|
assert "status: invalid" in binding_result.output
|
|
|
|
|
|
def test_wf_draft_route_flags_reject_duplicate_outcomes() -> None:
|
|
add_result = runner.invoke(
|
|
app,
|
|
[
|
|
"draft",
|
|
"add-step",
|
|
"ws",
|
|
"--revision",
|
|
"1",
|
|
"--step",
|
|
"call",
|
|
"--capability",
|
|
"demo.call",
|
|
"--route",
|
|
"ok=call",
|
|
"--route",
|
|
"ok=__end__",
|
|
],
|
|
)
|
|
branch_result = runner.invoke(
|
|
app,
|
|
[
|
|
"draft",
|
|
"branch",
|
|
"ws",
|
|
"--revision",
|
|
"1",
|
|
"--step",
|
|
"call",
|
|
"--route",
|
|
"ok=call",
|
|
"--route",
|
|
"ok=__end__",
|
|
],
|
|
)
|
|
|
|
assert add_result.exit_code == 2
|
|
assert branch_result.exit_code == 2
|
|
assert "duplicate --route for 'ok'" in add_result.output
|
|
assert "duplicate --route for 'ok'" in branch_result.output
|
|
|
|
|
|
def test_wf_run_resume_help_exists() -> None:
|
|
result = runner.invoke(app, ["run", "resume", "--help"])
|
|
|
|
assert result.exit_code == 0
|
|
assert "resume payload" in result.output.lower()
|
|
assert "schema" in result.output.lower()
|
|
|
|
|
|
def test_wf_draft_set_input_rejects_local_prefixed_target() -> None:
|
|
result = runner.invoke(
|
|
app,
|
|
[
|
|
"draft",
|
|
"set-input",
|
|
"report_ws",
|
|
"--revision",
|
|
"1",
|
|
"--step",
|
|
"render",
|
|
"--map",
|
|
"input.text=local.text",
|
|
],
|
|
)
|
|
|
|
assert result.exit_code == 2
|
|
output = " ".join(result.output.split())
|
|
assert "bare local field" in output
|
|
assert "input.text=text" in output
|
|
assert "input.text=local.text" in output
|