Files
falyx/tests/test_falyx/test_completion_contract.py
Roland Thomas efe3f5fd99 feat(core): clone commands and actions when binding runtimes
Add clone support across Action types and Command so commands can be safely
registered or runner-bound without mutating the original instances.

- clone BaseAction implementations across simple, composite, IO, prompt, file,
  HTTP, process, and signal actions
- bind cloned commands in Falyx.add_command_from_command() and CommandRunner
- preserve local never_prompt settings when cloning actions
- rename shared runtime state from options to options_manager for consistency
- seed root and execution option namespaces consistently
- apply scoped root and namespace option overrides during routing and dispatch
- improve namespace completion by delegating option suggestions to FalyxParser
- enrich missing-value errors and error hints
2026-06-07 13:04:35 -04:00

122 lines
3.1 KiB
Python

from prompt_toolkit.document import Document
from falyx import Falyx
from falyx.completer import FalyxCompleter
from falyx.parser import CommandArgumentParser
def completion_texts(completions) -> list[str]:
return [c.text for c in completions]
def make_completion_app() -> tuple[Falyx, FalyxCompleter]:
flx = Falyx(program="falyx")
flx.add_option(
"--profile",
suggestions=["dev", "prod", "staging"],
help="Runtime profile",
)
flx.add_option(
"--region",
choices=["us-east", "us-west"],
help="Deployment region",
)
parser = CommandArgumentParser()
parser.add_argument("--name")
parser.add_argument("--env", choices=["dev", "prod"])
flx.add_command(
key="D",
description="Deploy",
action=lambda name, env: f"deploy {name} to {env}",
aliases=["deploy"],
arg_parser=parser,
)
return flx, FalyxCompleter(flx)
def test_completion_suggests_namespace_flags():
_, completer = make_completion_app()
completions = list(
completer.get_completions(Document(text="--pr", cursor_position=4), None)
)
texts = completion_texts(completions)
assert "--profile" in texts
def test_completion_suggests_namespace_option_values():
_, completer = make_completion_app()
completions = list(
completer.get_completions(
Document(text="--profile pr", cursor_position=len("--profile pr")),
None,
)
)
texts = completion_texts(completions)
assert "prod" in texts
assert "dev" not in texts
def test_completion_after_committed_namespace_option_returns_namespace_entries():
_, completer = make_completion_app()
completions = list(
completer.get_completions(
Document(text="--profile prod de", cursor_position=len("--profile prod de")),
None,
)
)
texts = completion_texts(completions)
assert "deploy" in texts
def test_completion_preview_mode_prefixes_namespace_entry_suggestions():
_, completer = make_completion_app()
completions = list(
completer.get_completions(Document(text="?de", cursor_position=3), None)
)
texts = completion_texts(completions)
assert "?deploy" in texts
def test_resolve_completion_route_unresolved_entry_with_trailing_input_stops_namespace_entry_mode():
flx, _ = make_completion_app()
route = flx.resolve_completion_route(
["wat"],
stub="--na",
cursor_at_end_of_token=False,
invocation_context=flx.get_current_invocation_context(),
is_preview=False,
)
assert route.command is None
assert route.expecting_entry is False
assert route.remaining_argv == ["wat", "--na"]
assert route.stub == ""
def test_completion_delegates_to_command_parser_after_leaf_command_is_resolved():
_, completer = make_completion_app()
completions = list(
completer.get_completions(
Document(text="D --na", cursor_position=len("D --na")),
None,
)
)
texts = completion_texts(completions)
assert "--name" in texts