# Test Helper Reference

## Overview

The test helpers use the **functional options pattern** to make test setup flexible and composable.

## Basic Usage

```go
// Default model (6 lines, cursor at 0,0, terminal 80x24)
tm := newTestModel(t)

// With custom lines
tm := newTestModel(t,
    WithLines([]string{"hello", "world"}),
)

// With custom cursor position
tm := newTestModel(t,
    WithCursorPos(action.Position{Line: 1, Col: 5}),
)

// With custom terminal size
tm := newTestModel(t,
    WithTermSize(120, 40),
)

// With register content (useful for paste tests)
tm := newTestModel(t,
    WithRegister('"', action.CharwiseRegister, []string{"yanked text"}),
)
```

## Combining Options

You can combine multiple options in a single call:

```go
tm := newTestModel(t,
    WithLines([]string{"line 1", "line 2", "line 3"}),
    WithCursorPos(action.Position{Line: 1, Col: 0}),
    WithTermSize(100, 30),
    WithRegister('"', action.LinewiseRegister, []string{"deleted line"}),
)
```

## Available Options

| Option | Parameters | Description |
|--------|-----------|-------------|
| `WithLines` | `[]string` | Set buffer lines |
| `WithCursorPos` | `action.Position` | Set cursor position |
| `WithTermSize` | `width, height int` | Set terminal dimensions |
| `WithRegister` | `name rune, type RegisterType, content []string` | Set register content |

## Backward Compatibility

The old helper functions still work for existing tests:

```go
newTestModelWithLines(t, []string{"a", "b"})
newTestModelWithCursorPos(t, action.Position{Line: 1, Col: 2})
newTestModelWithLinesAndCursorPos(t, lines, pos)
newTestModelWithTermSize(t, lines, pos, width, height)
```

## Example Test

```go
func TestPasteCharwise(t *testing.T) {
    tm := newTestModel(t,
        WithLines([]string{"hello world"}),
        WithCursorPos(action.Position{Line: 0, Col: 5}),
        WithRegister('"', action.CharwiseRegister, []string{"PASTE"}),
    )
    
    sendKeys(tm, "p")
    m := getFinalModel(t, tm)
    
    // Assert expected behavior
    if m.Line(0) != "hello PASTEworld" {
        t.Errorf("unexpected result: %s", m.Line(0))
    }
}
```

## Default Values

When options are not specified:

- **Lines**: `[]string{"line 1", "line 2", "line 3", "line 4", "line 5", "line 6"}`
- **Cursor**: `{Line: 0, Col: 0}`
- **Terminal**: `80x24`
- **Register**: None set

## Adding New Options

To add a new option:

1. Add field to `testModelConfig`
2. Create a `With*` function that returns `TestModelOption`
3. Apply the option in `newTestModel` after creating the model

Example:

```go
// In testModelConfig
type testModelConfig struct {
    // ... existing fields
    scrollY int
}

// New option function
func WithScrollY(y int) TestModelOption {
    return func(c *testModelConfig) {
        c.scrollY = y
    }
}

// Apply in newTestModel
if cfg.scrollY > 0 {
    m.SetScrollY(cfg.scrollY)
}
```
