ferro-cli 0.2.19

CLI for scaffolding Ferro web applications
Documentation
---
name: ferro:test
description: Run tests with Ferro-specific setup
allowed-tools:
  - Bash
  - Read
---

<objective>
Run the Ferro application test suite with proper configuration.

Handles:
- Database setup for tests (test database)
- Feature flags
- Coverage reporting
- Filtered test runs
</objective>

<arguments>
Optional:
- `[filter]` - Filter tests by name
- `--coverage` - Generate coverage report
- `--watch` - Watch mode (re-run on changes)
- `--doc` - Run doc tests only
- `--integration` - Run integration tests only

Examples:
- `/ferro:test` - Run all tests
- `/ferro:test user` - Run tests matching "user"
- `/ferro:test --coverage` - Run with coverage
- `/ferro:test --integration` - Integration tests only
</arguments>

<process>

<step name="setup_test_env">

Ensure test environment is ready:

```bash
# Check if test database is configured
if grep -q "DATABASE_URL_TEST" .env 2>/dev/null; then
    export DATABASE_URL=$(grep DATABASE_URL_TEST .env | cut -d= -f2-)
    echo "Using test database"
fi
```

</step>

<step name="run_tests">

**Standard test run:**
```bash
cargo test --all-features {filter}
```

**With coverage (--coverage):**
```bash
# Check if cargo-llvm-cov is installed
if ! command -v cargo-llvm-cov &> /dev/null; then
    echo "Installing cargo-llvm-cov..."
    cargo install cargo-llvm-cov
fi

cargo llvm-cov --all-features --html
echo "Coverage report: target/llvm-cov/html/index.html"
```

**Doc tests only (--doc):**
```bash
cargo test --doc --all-features
```

**Integration tests (--integration):**
```bash
cargo test --test '*' --all-features
```

**Watch mode (--watch):**
```bash
# Check if cargo-watch is installed
if ! command -v cargo-watch &> /dev/null; then
    echo "Installing cargo-watch..."
    cargo install cargo-watch
fi

cargo watch -x "test --all-features {filter}"
```

</step>

<step name="report_results">

After tests complete, provide summary:

```
# Test Results

✓ Passed: {passed_count}
✗ Failed: {failed_count}
○ Ignored: {ignored_count}

{if failed}
## Failed Tests

{list of failed tests with brief error}

Run `/ferro:diagnose` for detailed error analysis.
{/if}

{if coverage}
## Coverage

- Lines: {line_coverage}%
- Functions: {fn_coverage}%
- Branches: {branch_coverage}%

Report: target/llvm-cov/html/index.html
{/if}
```

</step>

</process>

<test_patterns>

## Writing Ferro Tests

**Handler test:**
```rust
#[ferro_test]
async fn test_user_index() {
    let response = TestClient::new()
        .get("/api/users")
        .send()
        .await;

    response.assert_ok();
    response.assert_json_contains(json!({"data": []}));
}
```

**Authenticated request:**
```rust
#[ferro_test]
async fn test_protected_route() {
    let user = User::factory().create().await;

    let response = TestClient::new()
        .acting_as(&user)
        .get("/api/profile")
        .send()
        .await;

    response.assert_ok();
}
```

**Database test:**
```rust
#[ferro_test]
async fn test_user_creation() {
    let user = User::create(CreateUser {
        email: "test@example.com".into(),
        name: "Test User".into(),
    }).await.unwrap();

    assert_eq!(user.email, "test@example.com");

    // Database is automatically rolled back after test
}
```

</test_patterns>