factory

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Jun 8, 2026 License: MIT Imports: 8 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 entity's bundled CRUD handler. 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 as a snake_cased map.

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. Use [Suite] as the entry point in tests.

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