# Cyclopts Test Suite

This directory contains the test suite for cyclopts, including unit tests, integration tests, and snapshot tests.

## Directory Structure

```
tests/
├── __snapshots__/              # Snapshot files (auto-generated by syrupy)
│   └── test_docs_snapshots/    # Individual .md and .rst snapshot files
├── apps/                       # Test applications
│   ├── complex-demo/           # Comprehensive CLI for doc testing
│   └── cyclopts-demo/          # Simple demo app
├── cli/                        # CLI-specific tests
├── completion/                 # Shell completion tests
├── config/                     # Configuration file tests
├── py312/                      # Python 3.12+ specific tests
├── types/                      # Type handling tests
├── validators/                 # Validator tests
├── conftest.py                 # Shared fixtures
├── test_docs_e2e.py            # End-to-end documentation build tests
├── test_docs_snapshots.py      # Snapshot tests for doc generation
├── test_mkdocs_ext.py          # MkDocs plugin tests
├── test_sphinx_ext.py          # Sphinx extension tests
└── ... (other test files)
```

## Running Tests

```bash
# Run all tests
uv run pytest

# Run with coverage
uv run pytest --cov=cyclopts --cov-report=term

# Run specific test file
uv run pytest tests/test_mkdocs_ext.py -v

# Run tests matching a pattern
uv run pytest -k "mkdocs" -v
```

## Documentation Plugin Tests

The documentation plugins (MkDocs and Sphinx) have three levels of testing:

### 1. Unit Tests (`test_mkdocs_ext.py`, `test_sphinx_ext.py`)

Test individual components like directive parsing, import mechanisms, and filtering logic.

```bash
uv run pytest tests/test_mkdocs_ext.py tests/test_sphinx_ext.py -v
```

### 2. Snapshot Tests (`test_docs_snapshots.py`)

Capture the exact markdown/RST output generated by the plugins to detect unintended changes.

```bash
# Run snapshot tests
uv run pytest tests/test_docs_snapshots.py -v

# Update snapshots after intentional changes
uv run pytest tests/test_docs_snapshots.py --snapshot-update
```

**What's snapshotted:**
- Generated markdown documentation (various filtering/nesting scenarios)
- Generated RST documentation
- MkDocs directive processing output
- Sphinx directive processing output

**When to update snapshots:**
- After intentionally changing documentation output format
- After adding new features that affect output
- After fixing bugs that change output

**Reviewing snapshot changes:**
```bash
# See what changed (snapshots are individual .md/.rst files)
git diff tests/__snapshots__/

# Preview a snapshot directly
open tests/__snapshots__/test_docs_snapshots/TestMarkdownSnapshots.test_full_app_markdown.md

# Accept changes
uv run pytest tests/test_docs_snapshots.py --snapshot-update
git add tests/__snapshots__/
```

### 3. End-to-End Build Tests (`test_docs_e2e.py`)

Actually run `mkdocs build` and `sphinx-build` to verify the full documentation pipeline works.

```bash
uv run pytest tests/test_docs_e2e.py -v
```

These tests:
- Build documentation using the complex-demo app
- Verify the output HTML contains expected content
- Test that nested commands, dataclass flattening, etc. work in real builds

## Test Applications

### `apps/complex-demo/`

A comprehensive CLI application designed to test all edge cases:

- **Dataclass parameter flattening** - `@Parameter(name="*")`
- **Nested dataclasses** - Dataclass containing other dataclasses
- **Pydantic models** - BaseModel parameters (if pydantic installed)
- **attrs classes** - @attrs.define parameters (if attrs installed)
- **4-level nested commands** - `admin → users → permissions → roles`
- **Custom groups** - `Group.create_ordered()`
- **Complex union types** - `int | Literal["auto"]`
- **Count parameters** - `-v`, `-vv`, `-vvv`
- **Validators** - Number, Path validators
- **Hidden commands/parameters**
- **Multiple docstring formats** - NumPy, Google, Sphinx

See `apps/complex-demo/README.md` for full details.

### `apps/cyclopts-demo/`

A simpler demo app used for basic MkDocs plugin testing.

## Writing New Tests

### Adding Snapshot Tests

1. Add a new test method in `test_docs_snapshots.py`
2. Use the `snapshot` fixture from syrupy
3. Assert output equals snapshot: `assert output == snapshot`
4. Run with `--snapshot-update` to generate initial snapshot

```python
def test_my_new_feature(self, ensure_complex_demo_importable, snapshot):
    """Snapshot test for my new feature."""
    from complex_app import app
    from cyclopts.docs.markdown import generate_markdown_docs

    markdown = generate_markdown_docs(app, my_new_option=True)
    assert markdown == snapshot
```

### Adding E2E Tests

1. Add test methods to `test_docs_e2e.py`
2. Use the build fixtures to run mkdocs/sphinx
3. Verify output files contain expected content

### Adding to complex-demo

If you need to test a new cyclopts feature:

1. Add the feature usage to `apps/complex-demo/complex_app.py`
2. Add documentation directives to `apps/complex-demo/mkdocs_docs/` and `apps/complex-demo/docs/source/`
3. Add snapshot tests for the new output
4. Add E2E assertions if needed

## Test Fixtures

Key fixtures from `conftest.py`:

- `app` - Basic cyclopts App instance
- `console` - Rich console for output capture
- `assert_parse_args` - Helper to verify argument parsing
- `chdir_to_tmp_path` - Auto-fixture that runs tests in temp directory

## Continuous Integration

Tests run on multiple Python versions (3.10-3.14) and operating systems (Ubuntu, macOS, Windows). Some tests are skipped on certain configurations:

- `py312/` tests require Python 3.12+
- Pydantic/attrs tests gracefully degrade if not installed
- MkDocs/Sphinx build tests skip if tools not available
