factory

package
v0.96.0 Latest Latest
Warning

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

Go to latest
Published: Nov 7, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package factory provides Rails-style fixture / factory helpers for GoFastr tests and dev-time seeders. Each Factory binds to one entity's CRUD handler and produces fresh row bodies, typically by layering caller overrides on top of a base function, so test setup reads "make me a user with admin=true" instead of "construct a map with every required field by hand."

The package leans on the in-process crud.CrudHandler.CreateOne API so factories run through the exact same Before/After hook chain, transaction, and event emission as real HTTP traffic. That keeps integration-style tests close to production behaviour.

Wiring:

users := framework.NewApp(...).Entity("users", ...) // registers CRUD
userFactory := factory.New(app.Registry, "users", func() map[string]any {
    n := userSeq.Next()
    return map[string]any{
        "email": fmt.Sprintf("user%d@example.com", n),
        "name":  fmt.Sprintf("User %d", n),
    }
})

u, _ := userFactory.Create(ctx)
admin, _ := userFactory.Create(ctx, map[string]any{"role": "admin"})

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BaseFunc

type BaseFunc func() map[string]any

BaseFunc returns a fresh body map. Called for each Create / Build, returning a new map each time keeps tests independent of each other.

type EntityRegistry

type EntityRegistry interface {
	Get(name string) (*entity.Entity, error)
}

EntityRegistry is the minimal surface the factory needs from the framework's registry, a way to look up an entity by name. The factory accepts the interface so tests can supply a hand-rolled registry; in production this is the App.Registry.

type Factory

type Factory struct {
	// contains filtered or unexported fields
}

Factory builds and persists rows for one entity. Construct via New.

The handler defaults to the one the owning App's routes serve, when reg is an App's registry (app.Registry), and to a bare crud.NewCrudHandler (no hooks, events or app casing) for any other registry. Override it via WithHandler when your tests need a different DB connection (sandboxed schema, in-memory fork, …).

func New

func New(reg EntityRegistry, entityName string, base BaseFunc, opts ...Option) (*Factory, error)

New constructs a Factory bound to the named entity in the registry. The base function MUST return a fresh map per call, sharing a map would let later overrides leak into earlier factory results.

Returns an error when the entity is unknown or has no DB attached.

func (*Factory) Build

func (f *Factory) Build(overrides ...map[string]any) map[string]any

Build returns the row body that Create would insert, useful when a test wants to assert on the request shape without actually hitting the database. Overrides apply left-to-right; later overrides win on key conflict.

func (*Factory) Create

func (f *Factory) Create(ctx context.Context, overrides ...map[string]any) (map[string]any, error)

Create inserts a fresh row through the full CRUD pipeline (Before hooks → INSERT → After hooks → event emission) and returns the persisted record keyed as the handler's API responses are (the app's JSONCase, camelCase by default).

func (*Factory) CreateMany

func (f *Factory) CreateMany(ctx context.Context, n int, perIndex func(i int) map[string]any) ([]map[string]any, error)

CreateMany inserts n rows. The optional perIndex callback runs once per row and its return is merged on top of base + caller overrides, handy when each row needs a unique value derived from its index (e.g. ordering tests).

type Option

type Option func(*Factory)

Option configures a Factory.

func WithHandler

func WithHandler(h *crud.CrudHandler) Option

WithHandler overrides the CRUD handler the factory dispatches through. Useful when tests build their own handler with a custom DB connection.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry is the optional collection of named factories shared across a test suite.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty factory registry.

func (*Registry) Create

func (r *Registry) Create(ctx context.Context, name string, overrides ...map[string]any) (map[string]any, error)

Create looks up the named factory and creates one row. Convenience wrapper for tests that don't keep a local Factory reference.

func (*Registry) Get

func (r *Registry) Get(name string) (*Factory, error)

Get returns the factory or an error when none is registered.

func (*Registry) MustGet

func (r *Registry) MustGet(name string) *Factory

MustGet returns the factory or panics. Tests are the only real caller; production code should use Registry.Get instead.

func (*Registry) Register

func (r *Registry) Register(name string, f *Factory) *Registry

Register adds (or replaces) a factory under the supplied name. Use the entity name as the registry key by convention.

type Sequence

type Sequence struct {
	// contains filtered or unexported fields
}

Sequence is a tiny atomic counter for unique base values inside factory BaseFuncs. Concurrent-test-safe: Next never returns the same integer twice within a process lifetime.

func (*Sequence) Next

func (s *Sequence) Next() int64

Next returns the next integer.

func (*Sequence) NextString

func (s *Sequence) NextString(prefix string) string

NextString returns "prefix" + Next() as a string. Useful for per-row unique fields like email addresses.

Jump to

Keyboard shortcuts

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