Add tests and docs for '--' argument separator requirement

- Add TestArgumentSeparator class with 8 tests verifying that script
  arguments must come after '--' separator
- Update create and edit command docstrings with examples showing
  correct usage of '--' separator
- Update argument help text to indicate "(must come after '--')"
- Add "Passing Arguments to Your Script" section to README

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-01-11 19:45:54 -08:00
commit c601514e3d
3 changed files with 145 additions and 6 deletions

View file

@ -214,6 +214,99 @@ class TestDelete:
assert "does not exist" in result.output
class TestArgumentSeparator:
"""Tests verifying that '--' separator is required for passing arguments to scripts.
This ensures that:
- 'mcquack create script.sh --help' shows help for the create command
- 'mcquack create script.sh -- --help' creates a plist with --help as a script arg
"""
def test_create_help_without_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that --help without -- shows create command help, not passed to script."""
result = runner.invoke(app, ["create", str(mock_script), "--help"])
assert result.exit_code == 0
# Should show help text for create command
assert "Create and load a LaunchAgent" in result.stdout or "Usage:" in result.stdout
# Should NOT have created a plist
plist_path = get_plist_path(mock_dirs)
assert not plist_path.exists()
def test_create_help_with_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that -- --help passes --help as an argument to the script."""
result = runner.invoke(app, ["create", str(mock_script), "--", "--help"])
assert result.exit_code == 0
assert "Created:" in result.stdout
# Verify --help is in the plist as a script argument
plist_path = get_plist_path(mock_dirs)
assert plist_path.exists()
program_args = read_plist_args(plist_path)
assert "--help" in program_args
assert program_args[1] == "--help"
def test_create_verbose_without_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that --verbose without -- is treated as unknown option, not script arg."""
result = runner.invoke(app, ["create", str(mock_script), "--verbose"])
# Typer should reject unknown options
assert result.exit_code != 0
assert "No such option" in result.output or "no such option" in result.output.lower()
# Should NOT have created a plist
plist_path = get_plist_path(mock_dirs)
assert not plist_path.exists()
def test_create_verbose_with_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that -- --verbose passes --verbose as an argument to the script."""
result = runner.invoke(app, ["create", str(mock_script), "--", "--verbose"])
assert result.exit_code == 0
plist_path = get_plist_path(mock_dirs)
program_args = read_plist_args(plist_path)
assert "--verbose" in program_args
def test_edit_help_without_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that edit --help shows edit command help."""
# First create an agent
runner.invoke(app, ["create", str(mock_script)])
result = runner.invoke(app, ["edit", str(mock_script), "--help"])
assert result.exit_code == 0
assert "Edit the arguments" in result.stdout or "Usage:" in result.stdout
def test_edit_help_with_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that edit -- --help passes --help as a new argument."""
# First create an agent
runner.invoke(app, ["create", str(mock_script)])
result = runner.invoke(app, ["edit", str(mock_script), "--", "--help"])
assert result.exit_code == 0
plist_path = get_plist_path(mock_dirs)
program_args = read_plist_args(plist_path)
assert "--help" in program_args
def test_create_mixed_args_with_separator(self, mock_dirs, mock_script, mock_launchctl):
"""Verify multiple dash-prefixed args after -- are all passed to script."""
result = runner.invoke(app, ["create", str(mock_script), "--", "--config", "/path", "--debug", "-v"])
assert result.exit_code == 0
plist_path = get_plist_path(mock_dirs)
program_args = read_plist_args(plist_path)
# All args after -- should be in the plist
assert program_args[1:] == ["--config", "/path", "--debug", "-v"]
def test_create_double_dash_as_argument(self, mock_dirs, mock_script, mock_launchctl):
"""Verify that -- can be passed as a script argument using -- --."""
result = runner.invoke(app, ["create", str(mock_script), "--", "--", "arg_after_double_dash"])
assert result.exit_code == 0
plist_path = get_plist_path(mock_dirs)
program_args = read_plist_args(plist_path)
# The first -- is consumed by typer, the second becomes an argument
assert "--" in program_args
assert "arg_after_double_dash" in program_args
class TestPlistFormat:
"""Tests verifying plist file format independently of plistlib."""