acctest

package
v1.34.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 18, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package acctest drives `ant apply` lifecycles against a real API.

A test is a list of Steps — edit files, plan, apply, check — and Run holds every step to the same standard: after it applies, a fresh plan must find nothing to do and a fresh apply must write nothing. When the test ends, everything it created is pruned and each ID is confirmed gone or archived.

These tests create and destroy real resources, so they only run when ANT_ACC is set; see SkipUnlessEnabled. This package must not import the claude package (it takes a Registry and Client from the caller) so that claude's own tests can import it without a cycle.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(t *testing.T, registry *core.Registry, client core.Client, steps []Step)

Run drives steps against client in a fresh directory with its own lockfile. Each step is a subtest, and Run stops at the first that fails. The package doc describes the convergence check after each step and the teardown after the test.

func SkipUnlessEnabled

func SkipUnlessEnabled(t *testing.T)

SkipUnlessEnabled skips t unless acceptance tests are switched on. They are off by default because they need credentials and leave (archived) resources behind.

func Substitute

func Substitute(files map[string]string, name string) map[string]string

Substitute returns a copy of files with each "{{name}}" in the content replaced by name.

func UniqueName

func UniqueName(t *testing.T) string

UniqueName derives a token from the test name and ANT_ACC_RUN_ID for values the server requires to be unique, like a skill's display name. It is stable for a given test and run ID so a failure reproduces with the same names; set a fresh ANT_ACC_RUN_ID when an earlier run left debris behind.

func WriteTree

func WriteTree(t *testing.T, root string, files map[string]string)

WriteTree materializes slash-pathed files under root.

Types

type Fixture

type Fixture struct {
	// Root is the directory the declared files live under.
	Root string
	// UniqueName is the per-test token substituted for {{name}}; see the
	// UniqueName function.
	UniqueName string
	// Lock is the lockfile as re-read from disk after the last apply, so a
	// Check sees what a later run would load.
	Lock *core.Lockfile
	// Plan is the current step's plan, not the re-plan that checks
	// convergence. BeforePlan sees the previous step's plan, or nil on the
	// first step.
	Plan *core.Plan
	// Unrecorded is the same client without the recorder, for out-of-band
	// edits that must not show up in ExpectWrites.
	Unrecorded core.Client
	// contains filtered or unexported fields
}

Fixture is what a Check or BeforePlan callback can see and touch.

func (*Fixture) Change

func (f *Fixture) Change(t *testing.T, key string) *core.Change

Change returns the planned change for a key, failing if there is none.

func (*Fixture) Entry

func (f *Fixture) Entry(t *testing.T, key string) *core.LockEntry

Entry returns the lockfile entry for a resource key, failing if untracked.

func (*Fixture) ID

func (f *Fixture) ID(t *testing.T, key string) string

ID returns the tracked ID for a resource key, failing if untracked.

func (*Fixture) Remote

func (f *Fixture) Remote(t *testing.T, key string) map[string]any

Remote fetches the server's current copy of a tracked resource.

type Step

type Step struct {
	// Name is the subtest name. It defaults to "step N", counting from 1.
	Name string

	// Write creates or overwrites files (slash paths, relative to Fixture.Root)
	// before planning. "{{name}}" in content is replaced with
	// Fixture.UniqueName, for fields the server requires to be unique.
	Write map[string]string
	// Remove deletes files or directories before planning.
	Remove []string
	// BeforePlan runs after Remove and Write, before planning: to change
	// server state behind the reconciler's back through Fixture.Unrecorded,
	// or to write files whose content needs IDs an earlier step minted.
	BeforePlan func(t *testing.T, fx *Fixture)

	// Prune and Force set the core.Planner fields of the same names, as
	// --prune and --force do.
	Prune bool
	Force bool

	// ExpectActions maps resource key → the action the plan must choose.
	// Keys are lockfile keys: the path relative to Root with a leading "./",
	// such as "./agents/a.md", or the directory for a skill, "./skills/s".
	// Keys not listed are not checked.
	ExpectActions map[string]core.Action
	// ExpectBlocked maps resource key → a substring of the reason the plan
	// must refuse it. Every blocked change must be listed. A step with
	// blocked changes is not applied.
	ExpectBlocked map[string]string
	// ExpectNoop requires the plan to have no work at all.
	ExpectNoop bool
	// ExpectWrites is the exact, ordered list of writes the apply must make:
	// "create agent", "update skill", "destroy environment". nil skips the
	// check; an empty slice requires that nothing is written.
	ExpectWrites []string
	// ExpectKeys is the exact set of lockfile keys after the step. nil skips
	// the check; an empty slice requires an empty lockfile.
	ExpectKeys []string

	// Check runs after the apply (or after the plan, for a blocked step) for
	// anything the declarative fields cannot say.
	Check func(t *testing.T, fx *Fixture)
}

Step is one round of "change something, plan, apply, check". Every field is optional; a zero Step re-plans the tree as it stands and requires that to be a no-op.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL