# `backend/pkg/automationtesting`

L0 bridge package between the platform flow runtime
(`backend/internal/features/automation`) and external test modules under
`tests/conformance/<pack>/`.

## Layer

**L0.** This package contains no L1 / L2 application vocabulary. No
`Lead`, no `Account`, no `Issue`, no `Project`. Anything object-shaped is
parameterized — callers pass the SObject API name in. The platform binary
includes this package's symbols in test builds only.

## Why this package exists (the cross-module path)

External scenario test modules under `tests/conformance/<pack>/` cannot
import `backend/internal/...` directly. Go's `internal/` rule is enforced
at the module boundary, and a `replace` directive in the consumer's
`go.mod` does not bypass it. (Verified empirically — see PR #196 history.)

The fix is to introduce one bridge package that sits in the **same
module** as the runtime (so it can reach internal symbols) but **not under
`internal/`** (so external modules can import it):

```
tests/conformance/sf-crm/        ← own module, replace directive → backend/
    └── imports → backend/pkg/automationtesting   ← this package (public, in backend module)
                      └── imports → backend/internal/features/automation   ← internal, same module ⇒ allowed
```

External tests therefore route through `automationtesting` and never name
`automation` themselves.

## Where this fits in the test-suite topology

| Test type                  | Location                              | Module                                | L1 fixtures? | Touches `internal/`?     |
| -------------------------- | ------------------------------------- | ------------------------------------- | ------------ | ------------------------ |
| In-package unit tests      | `backend/internal/<feature>/_test.go` | `backend/`                            | ❌ no L1     | ✅ direct                |
| **Bridge tests (this pkg)**| `backend/pkg/automationtesting/`      | `backend/`                            | ❌ generic   | ✅ via Options on runtime|
| **L1 scenario tests**      | `tests/conformance/<pack>/`           | own module per pack, replace → backend| ✅ hardcoded | ❌ via `pkg/...` only    |
| Black-box integration      | `tests/integration/<feature>/`        | shell drivers                         | depends      | ❌ pure REST/CLI         |

## Public API surface

### `Rig`

Generic test harness. Constructed via `NewRig(opts ...RigOption)`. Methods
on `Rig` (added incrementally as scenarios need them) are the only
sanctioned way for external tests to drive the runtime. No method on
`Rig` takes or returns a value from `backend/internal/...`, so consumers
never need that import.

### `RigOption`

Configures the underlying flow runtime via the corresponding
`automation.Option`. Production lookups remain for any seam not covered
by an applied `RigOption`.

Currently exposed:

- `WithFlowVersionResolver(fn)` — substitutes the flow runtime's
  `FlowDefinition+FlowVersion` query path with an in-memory resolver.

New options are added on demand as scenarios need them. Each new option
should:

1. Be generic (no application vocabulary).
2. Default to nil-safe behavior so production callers passing zero opts
   get pre-options behavior unchanged.
3. Be documented with the production fallback path it replaces.

## Authoring a scenario

L1 scenarios live in `tests/conformance/<pack>/`, not here. See
`tests/conformance/README.md` for the convention.

This package grows by what scenarios require. Until a scenario needs a
particular generic helper, do not add it. YAGNI applies — speculative
test infrastructure is dead weight, and was a contributing factor to the
PR #173 / #196 revert.
