marrow

package module
v1.6.4 Latest Latest
Warning

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

Go to latest
Published: Dec 10, 2025 License: Apache-2.0 Imports: 39 Imported by: 1

README

Marrow

GoDoc Latest Version Go Report Card

An API integration test framework - for testing APIs written in Go, using a framework written in Go, with tests written in Go.

Features

  • Composable DSL for end-to-end API scenarios
    Describe tests as readable, fluent flows – no test YAML, no magic, just Go.

  • Black-box testing of any API
    Hit a real HTTP endpoint and assert on both the response and what it did to its dependencies. Works regardless of what language/framework the API is written in.

  • Real dependency “wraps” (not mocks)
    Spin up real services as test dependencies (e.g. MongoDB, LocalStack/AWS services, message brokers) and assert on their state and events.

  • Full coverage support
    Execute the API tests and optionally report endpoint coverage (even against a provided OAS spec)
    Coverage reports can also supply timings (inc. averages, variance, P50, P90, P99) - with built-in support for repeated runs.

  • Resolvable values
    Uniform mechanism for “values that come from somewhere”: JSON fields, variables, database queries, message payloads, lengths, first/last elements, etc.

  • Powerful assertions
    Rich set of assertion helpers over response payloads, headers, status codes, dependency state, and captured events.

  • Variables
    Declare vars once, SetVar() from responses or dependencies, and reuse them across steps. IDE refactoring-friendly because var names are just Go identifiers.

  • Conditional flows
    If(...) / IfNot(...) blocks let you express conditional logic directly in the DSL without branching mess in test code.

  • Capturing and inspecting side effects
    Capture SNS/SQS-style publishes, queue messages, Mongo changes, etc., and assert on count, content, and ordering.

  • Composable helpers
    Small building blocks (values, assertions, conditionals, captures) that can be combined arbitrarily – everything is designed to be reused and extended.

  • Extensible dependency model
    Built-in examples (Mongo, LocalStack, etc.) double as templates for adding your own dependency “wraps” with minimal boilerplate.

  • First-class Go testing integration
    Plays nicely with testing.T, subtests, and your existing tooling; tests are just Go code, no additional runner or framework ceremony.

  • Build freshness guard (make integration)
    Optionally run a make target before tests, so every scenario runs against the latest build artefact instead of whatever binary happened to be lying around.

  • IDE-friendly & CI/CD-friendly
    Runs identically in GoLand, VS Code, your terminal, GitHub Actions, GitLab CI, Jenkins, or any CI/CD pipeline.
    No custom runners, no plugins, no hidden runtime - just go test.

Design Philosophy

The intent of the design is to describe API tests in a non-abstract DSL (Domain Specific Language) that can be used by developers and QAs alike.

We've specifically avoided terms like "scenario" - instead using terms like "endpoint" & "method" to describe what's being tested.

Example

Full working demo examples can be found in Petstore and Petstore with db and API image

An example of what the tests definition looks like...

package main

import (
    . "github.com/go-andiamo/marrow"
)

var endpointTests = []Endpoint_{
    Endpoint("/api", "Root",
        Method(GET, "Get root").
            AssertOK().
            AssertEqual(JsonPath(Body, "hello"), "world"),
        Endpoint("/categories", "Categories",
            Method(GET, "Get first category id (used for creating pet)").
                RequireOK().
                RequireGreaterThan(JsonPath(Body, LEN), 0).
                SetVar(After, "category-id", JsonPath(JsonPath(Body, "0"), "id")),
        ),
        Endpoint("/pets", "Pets",
            Method(GET, "Get pets (empty)").
                AssertOK().
                AssertLen(Body, 0),
            Method(POST, "Create pet").
                RequestBody(JSON{
                    "name": "Felix",
                    "dob":  "2025-11-01",
                    "category": JSON{
                        "id": Var("category-id"),
                    },
                }).
                AssertCreated().
                SetVar(After, "created-pet-id", JsonPath(Body, "id")),
            Endpoint("/{petId}", "Pet",
                Method(GET, "Get pet (not found)").
                    PathParam(Var("non-uuid")).
                    AssertNotFound(),
                Method(PUT, "Update pet (not found)").
                    PathParam(Var("non-uuid")).
                    AssertNotFound(),
                Method(PUT, "Update pet successful").
                    PathParam(Var("created-pet-id")).
                    RequestBody(JSON{
                        "name": "Feline",
                        "dob":  "2025-11-02",
                        "category": JSON{
                            "id": Var("category-id"),
                        },
                    }).
                    AssertOK(),
                Method(DELETE, "Delete pet (not found)").
                    PathParam(Var("non-uuid")).
                    AssertNotFound(),
                Method(DELETE, "Delete pet successful").
                    PathParam(Var("created-pet-id")).
                    AssertNoContent(),
            ),
        ),
        Endpoint("/categories", "Categories",
            Method(GET, "Get categories").
                AssertOK().
                AssertGreaterThan(JsonPath(Body, LEN), 0),
            Endpoint("/{categoryId}", "Category",
                Method(GET, "Get category (not found)").
                    PathParam(Var("non-uuid")).
                    AssertNotFound(),
                Method(GET, "Get category (found)").
                    PathParam(Var("category-id")).
                    AssertOK(),
            ),
        ),
    ),
}

And to run the endpoints tests...

package main

import (
    . "github.com/go-andiamo/marrow"
)

func main() {
    s := Suite(endpoints...)
    err := s.Init(/* whatever initializers needed */).Run()
    if err != nil {
        panic(err)
    }
}

Or to run as part of Go tests...

package main

import (
    . "github.com/go-andiamo/marrow"
    "github.com/go-andiamo/marrow/with"
    "testing"
)

func TestApi(t *testing.T) {
    s := Suite(endpoints...)
    err := s.Init(
        with.Testing(t),
        /* whatever other initializers needed */).Run()
    if err != nil {
        t.Fatal(err)
    }
}

Installation

go get github.com/go-andiamo/marrow

Supporting images

Marrow comes with several ready-rolled supporting images for common dependencies (more to come)...

  • Artemis
    go get github.com/go-andiamo/marrow/images/artemis
  • Dragonfly (drop-in replacement for Redis)
    go get github.com/go-andiamo/marrow/images/dragonfly
  • Kafka
    go get github.com/go-andiamo/marrow/images/kafka
  • AWS localstack
    go get github.com/go-andiamo/marrow/images/localstack
  • MongoDB
    go get github.com/go-andiamo/marrow/images/mongo
  • MySql
    go get github.com/go-andiamo/marrow/images/mysql
  • Nats
    go get github.com/go-andiamo/marrow/images/nats
  • Postgres
    go get github.com/go-andiamo/marrow/images/postgres
  • Redis
    go get github.com/go-andiamo/marrow/images/redis7

Support images can also be used independently of Marrow in unit testing - see example

Documentation

Overview

Package marrow - An API integration test framework — for testing APIs written in Go, using a framework written in Go, with tests written in Go.

Index

Constants

View Source
const (
	BearerAuth = AuthScheme("Bearer")
	BasicAuth  = AuthScheme("Basic")
	TokenAuth  = AuthScheme("Token")
)
View Source
const (
	FIRST = "FIRST" // FIRST is a special token for path in JsonPath - and means resolve to first item in slice
	LAST  = "LAST"  // LAST is a special token for path in JsonPath - and means resolve to last item in slice
	LEN   = "LEN"   // LEN is a special token for path in JsonPath - and means resolve to length of slice
)

Variables

This section is empty.

Functions

func ResolveData added in v1.6.1

func ResolveData(value any, ctx Context) (data []byte, err error)

ResolveData is the same as ResolveValue, except that the value is resolved to data (i.e. []byte)

data for the value depends on type according to the following rules:

  • []byte - as is
  • string - []byte of that string
  • map, slice, struct - json data
  • other - []byte of fmt.Sprintf("%v")

func ResolveValue

func ResolveValue(value any, ctx Context) (av any, err error)

ResolveValue takes any value and attempts to resolve it (using the supplied Context to obtain actual values - such as vars, response etc.)

the value can be of any type - the following types are treated specially:

  • anything that implements Resolvable (the value is deep resolved)
  • BodyReader is executed to read the current context response body
  • `func(any) (any, error)` is called with the current context response body
  • TemplateString any var markers in the string are resolved
  • `map[string]any`, `[]any`, JSON, JSONArray - all values within the map/slice are resolved

func ResolveValues added in v1.6.2

func ResolveValues(value1 any, value2 any, ctx Context) (av1 any, av2 any, err error)

ResolveValues is the same as ResolveValue, except that it resolves two values

Types

type AndValue added in v1.5.0

type AndValue struct {
	Values []any
}

func And added in v1.5.0

func And(values ...any) AndValue

And is a resolvable value

it resolves by boolean ANDing all the supplied values (or their resolved value)

Notes:

  • if any of the values is not a bool, it errors
  • short-circuits on first false
  • if a value is an Expectation, the boolean is deduced from whether the expectation was met
  • nil values are ignored

func (AndValue) ResolveValue added in v1.5.0

func (v AndValue) ResolveValue(ctx Context) (av any, err error)

func (AndValue) String added in v1.5.0

func (v AndValue) String() string

type ApiCallValue added in v1.5.3

type ApiCallValue struct {
	Method  MethodName
	Url     any
	Body    any
	Headers Headers
}

func ApiCall added in v1.5.3

func ApiCall(method MethodName, url any, body any, headers Headers) ApiCallValue

ApiCall makes a call to the API under test - but not included as a test

this is useful for preparatory calls before/after a test endpoint is called

the value is resolved to the result of the call, represented as JSON map[string]any with the following properties...

  • "status" the response status code
  • "body" the response body (as []byte)
  • "headers" a map[string]any of the response headers

func (ApiCallValue) ResolveValue added in v1.5.3

func (v ApiCallValue) ResolveValue(ctx Context) (av any, err error)

func (ApiCallValue) String added in v1.5.3

func (v ApiCallValue) String() string

type ApiLogsValue added in v1.4.0

type ApiLogsValue struct {
	Last int
}

func ApiLogs added in v1.4.0

func ApiLogs(last int) ApiLogsValue

ApiLogs will resolve to the api logs (as []string) for the current api being tested

it will error if the tests are not being run against an api container image

func (ApiLogsValue) ResolveValue added in v1.4.0

func (v ApiLogsValue) ResolveValue(ctx Context) (av any, err error)

func (ApiLogsValue) String added in v1.4.0

func (v ApiLogsValue) String() string

type AuthScheme added in v1.6.0

type AuthScheme string

type AuthUsernamePasswordValue added in v1.6.0

type AuthUsernamePasswordValue struct {
	Username any
	Password any
}

func (AuthUsernamePasswordValue) ResolveValue added in v1.6.0

func (a AuthUsernamePasswordValue) ResolveValue(ctx Context) (av any, err error)

func (AuthUsernamePasswordValue) String added in v1.6.0

func (a AuthUsernamePasswordValue) String() string

type AuthValue added in v1.6.0

type AuthValue struct {
	Scheme AuthScheme
	Value  any
}

func (AuthValue) ResolveValue added in v1.6.0

func (v AuthValue) ResolveValue(ctx Context) (av any, err error)

func (AuthValue) String added in v1.6.0

func (v AuthValue) String() string

type BeforeAfter

type BeforeAfter interface {
	When() When
	Runnable
}

BeforeAfter is an interface that can be passed as an operation to Endpoint() or Method() (or Method.Capture) and instructs an operation to be run before or after the primary operations

func DoAfter added in v1.5.0

func DoAfter(op Runnable) BeforeAfter

DoAfter creates an after for the provided operation

if the op is nil, the resulting before/after is nil

func DoBefore added in v1.5.0

func DoBefore(op Runnable) BeforeAfter

DoBefore creates a before for the provided operation

if the op is nil, the resulting before/after is nil

func SSEListener added in v1.5.4

func SSEListener(name string, url any) BeforeAfter

SSEListener starts an SSE listener as a before operation

the name identifies the listener - for use in Events and EventsClear

if a listener with that name has previously been created, it is cleared

type BodyPath

type BodyPath string

BodyPath resolves to a value using the supplied path against the current Context response body

example:

BodyPath("foo.bar")

will resolve to the value of property foo.bar in the current Context response body

func (BodyPath) ResolveValue

func (v BodyPath) ResolveValue(ctx Context) (av any, err error)

type BodyReader

type BodyReader func(body any) (any, error)

BodyReader is a func that is called to resolve the value of the current context response body

is specially treated by ResolveValue

see also Body

type BodyValue

type BodyValue string
const (
	// Body is shorthand for the response body
	Body BodyValue = "Body"
)

func (BodyValue) ResolveValue

func (BodyValue) ResolveValue(ctx Context) (any, error)

func (BodyValue) String

func (BodyValue) String() string

type Capture

type Capture interface {
	Name() string
	Runnable
}

func ClearVars

func ClearVars() Capture

ClearVars clears all variables in the current Context

func DbClearTable

func DbClearTable(dbName string, tableName string) Capture

DbClearTable is used to clear a table in a database

Note: when only one database is used by tests, the dbName can be ""

func DbExec

func DbExec(dbName string, query string, args ...any) Capture

DbExec is used to execute a statement on a database

Note: when only one database is used by tests, the dbName can be ""

func DbInsert

func DbInsert(dbName string, tableName string, row Columns) Capture

DbInsert is used to insert into a database table

Note: when only one database is used by tests, the dbName can be ""

func EventsClear added in v1.5.4

func EventsClear(name string) Capture

EventsClear clears the events on the named listener

func ForEach added in v1.5.0

func ForEach(value any, iterVar any, ops ...Runnable) Capture

ForEach iterates over the value (or resolved value)

if the value (or resolved value) is not a slice - an error occurs

on each iteration a var is set - use the iterVar arg to set the name of this variable (if the iterVar arg is nil - a var name of "." is used)

func If added in v1.4.0

func If(condition any, ops ...Runnable) Capture

If runs the operations when the condition arg is met

Notes:

  • the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
  • if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the operations are just not performed
  • any condition that is not a bool or Expectation will cause an error during tests
  • the operations arg can be anything Runnable - any of them that are an Expectation, is run as an expectation (and treated as required) and any unmet or failure errors will be reported

func IfNot added in v1.4.0

func IfNot(condition any, ops ...Runnable) Capture

IfNot runs the operations when the condition arg is not met

Notes:

  • the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
  • if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the operations are just not performed
  • any condition that is not a bool or Expectation will cause an error during tests
  • the operations arg can be anything Runnable - any of them that are an Expectation, is run as an expectation (and treated as required) and any unmet or failure errors will be reported

func MockServiceCall

func MockServiceCall(svcName string, path string, method MethodName, responseStatus int, responseBody any, headers ...any) Capture

MockServiceCall is used to set up a mock response on a specific named mock service

func MockServiceClear

func MockServiceClear(svcName string) Capture

MockServiceClear is used to clear a specific named mock service

func MockServicesClearAll

func MockServicesClearAll() Capture

MockServicesClearAll is used to clear all mock services

func PrintVars added in v1.5.3

func PrintVars(resolve bool) Capture

func SetCookie added in v1.3.0

func SetCookie(cookie *http.Cookie) Capture

SetCookie sets a cookie in the current Context

func SetEnv added in v1.2.1

func SetEnv(name string, value any) Capture

SetEnv is used to set an environment variable

func SetQueryParam added in v1.3.0

func SetQueryParam(name string, values ...any) Capture

SetQueryParam is a capture that sets a query param for the current method

It can be used anywhere where captures are allowed, but is particularly useful as an operation in Method_.If

func SetRequestBody added in v1.3.0

func SetRequestBody(value any) Capture

SetRequestBody is a capture that sets the request body for the current method

It can be used anywhere where captures are allowed, but is particularly useful as an operation in Method_.If

func SetRequestHeader added in v1.3.0

func SetRequestHeader(name string, value any) Capture

SetRequestHeader is a capture that sets a request header for the current method

It can be used anywhere where captures are allowed, but is particularly useful as an operation in Method_.If

func SetRequestUseCookie added in v1.3.0

func SetRequestUseCookie(name string) Capture

SetRequestUseCookie is a capture that sets the name of a cookie to use for the current method

It can be used anywhere where captures are allowed, but is particularly useful as an operation in Method_.If

func SetVar

func SetVar(name any, value any) Capture

SetVar sets a variable in the current Context

func UnSetEnv added in v1.2.1

func UnSetEnv(names ...string) Capture

UnSetEnv is used to unset an environment variable

func Wait

func Wait(ms int) Capture

Wait is used to wait a specified milliseconds

Note: the wait time is not included in the coverage timings

func WaitFor added in v1.6.4

func WaitFor(condition any, maxTime time.Duration, delays ...time.Duration) Capture

WaitFor waits for a specified condition to be met

Notes:

  • the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
  • if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the condition is re-evaluated until maxTime is exceeded
  • any condition that is not a bool or Expectation will cause an error during tests

delays specifies the durations to wait on each poll cycle...

  • if not delays specified, there is no initial delay and polls occur every 250ms
  • if only one delay specified, there is no initial delay and polls occur at that specified duration
  • if more than one delay is specified, the initial delay is the first duration and subsequent poll delays are the remaining durations

type CaptureError

type CaptureError interface {
	Error
	Capture() Capture
	Values() []OperandValue
}

type ClaimValue added in v1.6.0

type ClaimValue interface {
	Name() string
	Value() any
}

func AudienceClaim added in v1.6.0

func AudienceClaim(value any) ClaimValue

func Claim added in v1.6.0

func Claim(name string, value any) ClaimValue

func ExpireAfterClaim added in v1.6.0

func ExpireAfterClaim(dur time.Duration) ClaimValue

func ExpireAtClaim added in v1.6.0

func ExpireAtClaim(expiry time.Time) ClaimValue

func IssuerClaim added in v1.6.0

func IssuerClaim(value any) ClaimValue

func SubjectClaim added in v1.6.0

func SubjectClaim(value any) ClaimValue

type Columns

type Columns map[string]any

type Context

type Context interface {
	// Host returns the currently tested API host
	Host() string
	// Vars returns the current Context variables
	//
	// the returned map is mutable but has no effect on the actual variables
	Vars() map[Var]any
	// Db returns a *sql.DB for the named database
	//
	// Note: when only one database is used by tests, the dbName can be ""
	Db(dbName string) *sql.DB
	// Ctx returns the go context.Context
	Ctx() gctx.Context
	// SetVar sets a variable in the context
	SetVar(Var, any)
	// ClearVars clears all variables in the context
	ClearVars()
	// CurrentEndpoint returns the current Endpoint being tested
	//
	// Note: may be nil if an endpoint not yet started
	CurrentEndpoint() Endpoint_
	// CurrentMethod returns the current Method being tested
	//
	// Note: may be nil if a method not yet started
	CurrentMethod() Method_
	// CurrentUrl returns the current URL for the current Endpoint
	CurrentUrl() string
	// CurrentRequest returns the current built request for a method
	//
	// Note: may be nil if the request has not yet been built
	CurrentRequest() *http.Request
	// CurrentResponse returns the current response for a method call
	//
	// Note: may be nil if the method has not yet been called
	CurrentResponse() *http.Response
	// CurrentBody returns the current unmarshalled response body for a method call
	//
	// Note: may be nil if the method has not yet been called or the response body was empty
	CurrentBody() any
	// DbInsert performs an insert into a database table
	//
	// Note: when only one database is used by tests, the dbName can be ""
	DbInsert(dbName string, tableName string, row Columns) error
	// DbExec executes a statement on a database
	//
	// Note: when only one database is used by tests, the dbName can be ""
	DbExec(dbName string, query string, args ...any) error
	// StoreCookie stores the cookie for later use
	StoreCookie(cookie *http.Cookie)
	// GetCookie returns a specific named cookie (or nil if that cookie has not been stored)
	GetCookie(name string) *http.Cookie
	// GetMockService returns a specific named mock service (or nil if that name is not registered)
	GetMockService(name string) service.MockedService
	// ClearMockServices clears all mock services
	ClearMockServices()
	// GetImage returns the named supporting image
	GetImage(name string) with.Image
	// GetApiImage returns the main api (i.e. api under test) image, or nil if not running against an image
	GetApiImage() with.ImageApi
	// Log outputs the args in the test output
	Log(args ...any)
	// DoRequest performs a http request (not as part of tests)
	DoRequest(req *http.Request) (*http.Response, error)
	// ResolveServiceValue resolves a service value
	//
	// example:
	//	ResolveServiceValue("mysql:username")
	// would resolve to the username setting on supporting image "mysql"
	//
	// all supporting images support "host", "port", "mport", "username" & "password"
	//
	// some services support additional settings, e.g. localstack supports "region", "accesskey", "secretkey", "sessiontoken" (and possibly "arn:<name>")
	ResolveServiceValue(v string) (string, bool)

	Listener(name string) Listener
	RegisterListener(name string, listener Listener)
	// contains filtered or unexported methods
}

type DefaultVarValue added in v1.5.0

type DefaultVarValue struct {
	Var   Var
	Value any
}

func DefaultVar added in v1.5.0

func DefaultVar(name any, value any) DefaultVarValue

DefaultVar resolves to the named var

if the named var is not set, it resolves to the value provided (and the var is also set to that value)

func (DefaultVarValue) ResolveValue added in v1.5.0

func (v DefaultVarValue) ResolveValue(ctx Context) (av any, err error)

func (DefaultVarValue) String added in v1.5.0

func (v DefaultVarValue) String() string

type Endpoint_

type Endpoint_ interface {
	common.Endpoint
	Runnable

	fmt.Stringer
	// contains filtered or unexported methods
}

Endpoint_ is the interface implemented by an instantiated Endpoint

func Endpoint

func Endpoint(url string, desc string, operations ...any) Endpoint_

Endpoint instantiates a new endpoint test

the operations can be any of the following types:

  • Method - adds a method test under this endpoint
  • []Method - ditto
  • Endpoint - adds a sub-path endpoint to this endpoint
  • []Endpoint - ditto
  • BeforeAfter - adds a before/after operation to the endpoint (befores are run before all methods and sub-endpoints, afters are run after all methods and sub-endpoints
  • []BeforeAfter - ditto
  • []any - treats each item as above

type Env added in v1.2.1

type Env string

Env is the name of an environment variable

when resolved, the value is the current environment variable of the name

func (Env) ResolveValue added in v1.2.1

func (e Env) ResolveValue(ctx Context) (av any, err error)

func (Env) String added in v1.2.1

func (e Env) String() string

type Error

type Error interface {
	error
	Type() ErrorType
	Name() string
	Cause() error
	Unwrap() error
	TestFormat() string
	framing.Framed
}

Error represents the basic error for almost all errors produced

type ErrorType

type ErrorType int
const (
	ErrorUnmet ErrorType = iota
	ErrorCapture
)

type Events added in v1.5.4

type Events string

Events is a resolvable value that resolves to the events on the named listener

if the named listener has not been started/registered - an error is returned

func (Events) ResolveValue added in v1.5.4

func (v Events) ResolveValue(ctx Context) (av any, err error)

func (Events) String added in v1.5.4

func (v Events) String() string

type EventsCount added in v1.5.4

type EventsCount string

EventsCount is a resolvable value that resolves to the count of events on the named listener

if the named listener has not been started/registered - an error is returned

func (EventsCount) ResolveValue added in v1.5.4

func (v EventsCount) ResolveValue(ctx Context) (av any, err error)

func (EventsCount) String added in v1.5.4

func (v EventsCount) String() string

type Expectation

type Expectation interface {
	common.Expectation
	Runnable
	Met(ctx Context) (unmet error, err error)
	IsRequired() bool
}

func ExpectAccepted added in v1.3.0

func ExpectAccepted() Expectation

ExpectAccepted asserts the response status code is 202 "Accepted"

func ExpectBadRequest added in v1.3.0

func ExpectBadRequest() Expectation

ExpectBadRequest asserts the response status code is 400 "Bad Request"

func ExpectConflict added in v1.3.0

func ExpectConflict() Expectation

ExpectConflict asserts the response status code is 409 "Conflict"

func ExpectContains added in v1.3.0

func ExpectContains(value any, s string) Expectation

ExpectContains asserts that the value contains a substring

when attempting to check contains, the value (or resolved value) is "stringified"

func ExpectCreated added in v1.3.0

func ExpectCreated() Expectation

ExpectCreated asserts the response status code is 201 "Created"

func ExpectEqual added in v1.3.0

func ExpectEqual(v1, v2 any) Expectation

ExpectEqual asserts that the supplied values are equal

values can be any of:

  • primitive type of string, bool, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectFalse added in v1.5.0

func ExpectFalse(value any) Expectation

func ExpectForbidden added in v1.3.0

func ExpectForbidden() Expectation

ExpectForbidden asserts the response status code is 403 "Forbidden"

func ExpectGone added in v1.3.0

func ExpectGone() Expectation

ExpectGone asserts the response status code is 410 "Gone"

func ExpectGreaterThan added in v1.3.0

func ExpectGreaterThan(v1, v2 any) Expectation

ExpectGreaterThan asserts that v1 is greater than v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectGreaterThanOrEqual added in v1.3.0

func ExpectGreaterThanOrEqual(v1, v2 any) Expectation

ExpectGreaterThanOrEqual asserts that v1 is greater than or equal to v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectHasProperties added in v1.3.0

func ExpectHasProperties(value any, propertyNames ...string) Expectation

ExpectHasProperties asserts that the value (or resolved value) has the supplied properties

the value (or resolved value) must be a map

func ExpectLen added in v1.3.0

func ExpectLen(value any, length int) Expectation

ExpectLen asserts that the value (or resolved value) has the supplied length

the value (or resolved value) must be a string, map or slice

func ExpectLessThan added in v1.3.0

func ExpectLessThan(v1, v2 any) Expectation

ExpectLessThan asserts that v1 is less than v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectLessThanOrEqual added in v1.3.0

func ExpectLessThanOrEqual(v1, v2 any) Expectation

ExpectLessThanOrEqual asserts that v1 is less than or equal to v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectMatch added in v1.3.0

func ExpectMatch(value any, regex string) Expectation

ExpectMatch asserts that the value matches the supplied regex

when attempting to match against the regex, the value (or resolved value) is "stringified"

values can be any of:

  • primitive type of string, bool, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectMockServiceCalled added in v1.3.0

func ExpectMockServiceCalled(svcName string, path string, method MethodName) Expectation

ExpectMockServiceCalled asserts that a specific mock service endpoint+method was called

func ExpectNil added in v1.3.0

func ExpectNil(value any) Expectation

ExpectNil asserts that the value (or resolved value) is nil

func ExpectNoContent added in v1.3.0

func ExpectNoContent() Expectation

ExpectNoContent asserts the response status code is 204 "No Content"

func ExpectNotEqual added in v1.3.0

func ExpectNotEqual(v1, v2 any) Expectation

ExpectNotEqual asserts that the supplied values are not equal

values can be any of:

  • primitive type of string, bool, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectNotFound added in v1.3.0

func ExpectNotFound() Expectation

ExpectNotFound asserts the response status code is 404 "Not Found"

func ExpectNotGreaterThan added in v1.3.0

func ExpectNotGreaterThan(v1, v2 any) Expectation

ExpectNotGreaterThan asserts that v1 is not greater than v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectNotLessThan added in v1.3.0

func ExpectNotLessThan(v1, v2 any) Expectation

ExpectNotLessThan asserts that v1 is not less than v2

values can be any of:

  • primitive type of string, int, int64, float64
  • decimal.Decimal
  • or anything that is resolvable...

examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse, StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,

func ExpectNotNil added in v1.3.0

func ExpectNotNil(value any) Expectation

ExpectNotNil asserts that the value (or resolved value) is not nil

func ExpectOK added in v1.3.0

func ExpectOK() Expectation

ExpectOK asserts the response status code is 200 "OK"

func ExpectOnlyHasProperties added in v1.3.0

func ExpectOnlyHasProperties(value any, propertyNames ...string) Expectation

ExpectOnlyHasProperties asserts that the value (or resolved value) only has the supplied properties

the value (or resolved value) must be a map

func ExpectStatus added in v1.3.0

func ExpectStatus(status any) Expectation

ExpectStatus asserts the response status code is the status supplied

func ExpectStatusCodeIn added in v1.5.0

func ExpectStatusCodeIn(statuses ...any) Expectation

ExpectStatusCodeIn asserts the response status code is in one of the supplied values

func ExpectTrue added in v1.5.0

func ExpectTrue(value any) Expectation

func ExpectType added in v1.3.0

func ExpectType(value any, typ Type_) Expectation

ExpectType asserts that the value (or resolved value) is of the supplied type

func ExpectUnauthorized added in v1.3.0

func ExpectUnauthorized() Expectation

ExpectUnauthorized asserts the response status code is 401 "Unauthorized"

func ExpectUnprocessableEntity added in v1.3.0

func ExpectUnprocessableEntity() Expectation

ExpectUnprocessableEntity asserts the response status code is 422 "Unprocessable Entity"

func ExpectVarSet added in v1.3.0

func ExpectVarSet(v Var) Expectation

ExpectVarSet asserts that a named variable has been set

func ExpectationFunc

func ExpectationFunc(fn func(ctx Context) (unmet error, err error)) Expectation

func Fail added in v1.3.0

func Fail(msg string) Expectation

Fail is an expectation that always fails (not just unmet)

can be used in Method.If to cause test fail conditions

type FirstValue added in v1.5.0

type FirstValue struct {
	Value any
}

func First added in v1.5.0

func First(value any) FirstValue

First resolves to the first item (element) of the value (or resolved value)

if the value (or resolved value) is not a slice (or an empty slice) - this always resolves to nil

func (FirstValue) ResolveValue added in v1.5.0

func (v FirstValue) ResolveValue(ctx Context) (av any, err error)

func (FirstValue) String added in v1.5.0

func (v FirstValue) String() string

type FormMultipart added in v1.5.2

type FormMultipart struct {
	Parts []MultipartPart
}

func Multipart added in v1.5.2

func Multipart(parts ...MultipartPart) FormMultipart

Multipart creates a FormMultipart for use as Method_.RequestBody

the parts can Field or FileField

type FormUrlEncoded added in v1.5.2

type FormUrlEncoded struct {
	Values map[string]any
}

func UrlEncoded added in v1.5.2

func UrlEncoded(values ...any) FormUrlEncoded

UrlEncoded creates a FormUrlEncoded for use as Method_.RequestBody

the request body is encoded as "application/x-www-form-urlencoded"

type FormatValue added in v1.6.3

type FormatValue struct {
	Format string
	Args   []any
}

func Format added in v1.6.3

func Format(format string, args ...any) FormatValue

Format is a resolvable value, similar to fmt.Sprintf except that args are resolved

func (FormatValue) ResolveValue added in v1.6.3

func (v FormatValue) ResolveValue(ctx Context) (any, error)

type Headers added in v1.5.3

type Headers map[string]any

type ImageStartupInitializer added in v1.6.3

type ImageStartupInitializer interface {
	StartupInit(ctx Context) error
}

ImageStartupInitializer is an additional interface that support images can implement if they need initializing

image initialization occurs once all supporting images have been spun up

type ImageValue added in v1.6.3

type ImageValue struct {
	Service string
	Tokens  []any
}

func ImageVal added in v1.6.3

func ImageVal(svc string, tokens ...any) ImageValue

ImageVal is a resolvable value that resolves to a setting (value) of a supporting image

svc is the name of the supporting image, e.g. "mysql", "aws" etc.

tokens can be "host", "port", "mport" (mapped port), "username", "password" or any token that the supporting image resolves

func (ImageValue) ResolveValue added in v1.6.3

func (v ImageValue) ResolveValue(ctx Context) (any, error)

type JSON

type JSON map[string]any

JSON is shorthand for a `map[string]any` representation of a json object

it is also treated specially by ResolveValue - where all values are deep resolved

type JSONArray

type JSONArray []any

JSONArray is shorthand for a `[]any` representation of a json array

it is also treated specially by ResolveValue - where all values are deep resolved

type JsonPathValue

type JsonPathValue struct {
	Value any
	Path  string
}

func JsonPath

func JsonPath(v any, path string) JsonPathValue

JsonPath resolves to a value using the supplied path on the supplied value

example:

JsonPath(Var("foo"), "bar")

will resolve to the value of Var("foo") and return the value of property "bar" within that

func (JsonPathValue) ResolveValue

func (v JsonPathValue) ResolveValue(ctx Context) (av any, err error)

func (JsonPathValue) String

func (v JsonPathValue) String() string

type JsonTraverseValue

type JsonTraverseValue struct {
	Value any
	Steps []any
}

func JsonTraverse

func JsonTraverse(v any, pathSteps ...any) JsonTraverseValue

JsonTraverse resolves to a value using the supplied path steps on the supplied value

example:

JsonTraverse(Var("foo"), FIRST, "bar", LAST)

if the Var("foo") resolved to...

[
  {
    "bar": ["aaa", "bbb", "ccc"]
  }
]

the final resolved value would be "ccc"

func (JsonTraverseValue) ResolveValue

func (v JsonTraverseValue) ResolveValue(ctx Context) (av any, err error)

type JsonifyValue added in v1.2.8

type JsonifyValue struct {
	Value any
}

func Jsonify added in v1.2.8

func Jsonify(v any) JsonifyValue

Jsonify resolves to a value using the supplied value and attempts to coerce it to a JSON representation (i.e. map[string]any / []any)

if the value does not coerce to JSON, the resolve errors

the initial value can be: string, []byte, or any map/slice/struct

func (JsonifyValue) ResolveValue added in v1.2.8

func (v JsonifyValue) ResolveValue(ctx Context) (av any, err error)

type LastValue added in v1.5.0

type LastValue struct {
	Value any
}

func Last added in v1.5.0

func Last(value any) LastValue

Last resolves to the last item (element) of the value (or resolved value)

if the value (or resolved value) is not a slice (or an empty slice) - this always resolves to nil

func (LastValue) ResolveValue added in v1.5.0

func (v LastValue) ResolveValue(ctx Context) (av any, err error)

func (LastValue) String added in v1.5.0

func (v LastValue) String() string

type LenValue added in v1.4.0

type LenValue struct {
	Value any
}

func Len added in v1.4.0

func Len(value any) LenValue

Len resolves to the length of the value (or resolved value)

if the value (or resolved value) is not a string, map or slice - this always resolves to -1

func (LenValue) ResolveValue added in v1.4.0

func (v LenValue) ResolveValue(ctx Context) (av any, err error)

func (LenValue) String added in v1.4.0

func (v LenValue) String() string

type Listener added in v1.5.4

type Listener interface {
	Events() []any
	EventsCount() int
	Clear()
	Stop()
}

type MethodCaptures added in v1.3.0

type MethodCaptures interface {
	// SetVar sets a variable in the current Context
	SetVar(when When, name any, value any) Method_
	// ClearVars clears all variables in the current Context
	ClearVars(when When) Method_
	// DbInsert performs an insert into a database table
	//
	// Note: when only one database is used by tests, the dbName can be ""
	DbInsert(when When, dbName string, tableName string, row Columns) Method_
	// DbExec executes a statement on a database
	//
	// Note: when only one database is used by tests, the dbName can be ""
	DbExec(when When, dbName string, query string, args ...any) Method_
	// DbClearTables clears table(s) in a database
	//
	// Note: when only one database is used by tests, the dbName can be ""
	DbClearTables(when When, dbName string, tableNames ...string) Method_
	// Wait wait a specified milliseconds
	//
	// Note: the wait time is not included in the coverage timings
	Wait(when When, ms int) Method_
	// WaitFor waits for a specified condition to be met
	//
	// Notes:
	//   * the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
	//   * if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the condition is re-evaluated until maxTime is exceeded
	//   * any condition that is not a bool or Expectation will cause an error during tests
	//
	// delays specifies the durations to wait on each poll cycle...
	//   * if not delays specified, there is no initial delay and polls occur every 250ms
	//   * if only one delay specified, there is no initial delay and polls occur at that specified duration
	//   * if more than one delay is specified, the initial delay is the first duration and subsequent poll delays are the remaining durations
	WaitFor(when When, condition any, maxTime time.Duration, delays ...time.Duration) Method_
	// Do adds before/after operations
	Do(ops ...BeforeAfter) Method_
	// Capture adds a before/after operations
	Capture(when When, ops ...Runnable) Method_
	// CaptureFunc adds the provided func(s) as a before/after operation
	CaptureFunc(when When, fns ...func(Context) error) Method_

	// MockServicesClearAll clears all mock services
	MockServicesClearAll(when When) Method_
	// MockServiceClear clears a specific named mock service
	MockServiceClear(when When, svcName string) Method_
	// MockServiceCall sets up a mock response on a specific named mock service
	MockServiceCall(svcName string, path string, method MethodName, responseStatus int, responseBody any, headers ...any) Method_
}

type MethodExpectations added in v1.3.0

type MethodExpectations interface {
	// Expect adds expectations to the Method_
	Expect(expectations ...Expectation) Method_

	// AssertOK asserts the response status code is 200 "OK"
	AssertOK() Method_
	// AssertCreated asserts the response status code is 201 "Created"
	AssertCreated() Method_
	// AssertAccepted asserts the response status code is 202 "Accepted"
	AssertAccepted() Method_
	// AssertNoContent asserts the response status code is 204 "No Content"
	AssertNoContent() Method_
	// AssertBadRequest asserts the response status code is 400 "Bad Request"
	AssertBadRequest() Method_
	// AssertUnauthorized asserts the response status code is 401 "Unauthorized"
	AssertUnauthorized() Method_
	// AssertForbidden asserts the response status code is 403 "Forbidden"
	AssertForbidden() Method_
	// AssertNotFound asserts the response status code is 404 "Not Found"
	AssertNotFound() Method_
	// AssertConflict asserts the response status code is 409 "Conflict"
	AssertConflict() Method_
	// AssertGone asserts the response status code is 410 "Gone"
	AssertGone() Method_
	// AssertUnprocessableEntity asserts the response status code is 422 "Unprocessable Entity"
	AssertUnprocessableEntity() Method_
	// AssertStatus asserts the response status code is the status supplied
	AssertStatus(status any) Method_
	// AssertFunc asserts that the supplied func is met
	AssertFunc(fn func(Context) (unmet error, err error)) Method_
	// AssertEqual asserts that the supplied values are equal
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertEqual(v1, v2 any) Method_
	// AssertNotEqual asserts that the supplied values are not equal
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertNotEqual(v1, v2 any) Method_
	// AssertLessThan asserts that v1 is less than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertLessThan(v1, v2 any) Method_
	// AssertLessThanOrEqual asserts that v1 is less than or equal to v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertLessThanOrEqual(v1, v2 any) Method_
	// AssertGreaterThan asserts that v1 is greater than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertGreaterThan(v1, v2 any) Method_
	// AssertGreaterThanOrEqual asserts that v1 is greater than or equal to v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertGreaterThanOrEqual(v1, v2 any) Method_
	// AssertNotLessThan asserts that v1 is not less than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertNotLessThan(v1, v2 any) Method_
	// AssertNotGreaterThan asserts that v1 is not greater than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertNotGreaterThan(v1, v2 any) Method_
	// AssertMatch asserts that the value matches the supplied regex
	//
	// when attempting to match against the regex, the value (or resolved value) is "stringified"
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	AssertMatch(value any, regex string) Method_
	// AssertContains asserts that the value contains a substring
	//
	// when attempting to check contains, the value (or resolved value) is "stringified"
	AssertContains(value any, s string) Method_
	// AssertType asserts that the value (or resolved value) is of the supplied type
	AssertType(value any, typ Type_) Method_
	// AssertNil asserts that the value (or resolved value) is nil
	AssertNil(value any) Method_
	// AssertNotNil asserts that the value (or resolved value) is not nil
	AssertNotNil(value any) Method_
	// AssertLen asserts that the value (or resolved value) has the supplied length
	//
	// the value (or resolved value) must be a string, map or slice
	AssertLen(value any, length int) Method_
	// AssertHasProperties asserts that the value (or resolved value) has the supplied properties
	//
	// the value (or resolved value) must be a map
	AssertHasProperties(value any, propertyNames ...string) Method_
	// AssertOnlyHasProperties asserts that the value (or resolved value) only has the supplied properties
	//
	// the value (or resolved value) must be a map
	AssertOnlyHasProperties(value any, propertyNames ...string) Method_

	// RequireOK requires the response status code is 200 "OK"
	RequireOK() Method_
	// RequireCreated requires the response status code is 201 "Created"
	RequireCreated() Method_
	// RequireAccepted requires the response status code is 202 "Accepted"
	RequireAccepted() Method_
	// RequireNoContent requires the response status code is 204 "No Content"
	RequireNoContent() Method_
	// RequireBadRequest requires the response status code is 400 "Bad Request"
	RequireBadRequest() Method_
	// RequireUnauthorized requires the response status code is 401 "Unauthorized"
	RequireUnauthorized() Method_
	// RequireForbidden requires the response status code is 403 "Forbidden"
	RequireForbidden() Method_
	// RequireNotFound requires the response status code is 404 "Not Found"
	RequireNotFound() Method_
	// RequireConflict requires the response status code is 409 "Conflict"
	RequireConflict() Method_
	// RequireGone requires the response status code is 410 "Gone"
	RequireGone() Method_
	// RequireUnprocessableEntity requires the response status code is 422 "Unprocessable Entity"
	RequireUnprocessableEntity() Method_
	// RequireStatus requires the response status code is the status supplied
	RequireStatus(status any) Method_
	// RequireFunc requires that the supplied func is met
	RequireFunc(fn func(Context) (unmet error, err error)) Method_
	// RequireEqual requires that the supplied values are equal
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireEqual(v1, v2 any) Method_
	// RequireNotEqual requires that the supplied values are not equal
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireNotEqual(v1, v2 any) Method_
	// RequireLessThan requires that v1 is less than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireLessThan(v1, v2 any) Method_
	// RequireLessThanOrEqual requires that v1 is less than or equal to v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireLessThanOrEqual(v1, v2 any) Method_
	// RequireGreaterThan requires that v1 is greater than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireGreaterThan(v1, v2 any) Method_
	// RequireGreaterThanOrEqual requires that v1 is greater than or equal to v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireGreaterThanOrEqual(v1, v2 any) Method_
	// RequireNotLessThan requires that v1 is not less than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireNotLessThan(v1, v2 any) Method_
	// RequireNotGreaterThan requires that v1 is not greater than v2
	//
	// values can be any of:
	//  * primitive type of string, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireNotGreaterThan(v1, v2 any) Method_
	// RequireMatch requires that the value matches the supplied regex
	//
	// when attempting to match against the regex, the value (or resolved value) is "stringified"
	//
	// values can be any of:
	//  * primitive type of string, bool, int, int64, float64
	//  * decimal.Decimal
	//  * or anything that is resolvable...
	//
	// examples of resolvable values are: Var, Body, BodyPath, Query, QueryRows, JsonPath, JsonTraverse,
	// StatusCode, ResponseCookie, ResponseHeader, JSON, JSONArray, TemplateString,
	RequireMatch(value any, regex string) Method_
	// RequireContains requires that the value contains a substring
	//
	// when attempting to check contains, the value (or resolved value) is "stringified"
	RequireContains(value any, s string) Method_
	// RequireType requires that the value (or resolved value) is of the supplied type
	RequireType(value any, typ Type_) Method_
	// RequireNil requires that the value (or resolved value) is nil
	RequireNil(value any) Method_
	// RequireNotNil requires that the value (or resolved value) is not nil
	RequireNotNil(value any) Method_
	// RequireLen requires that the value (or resolved value) has the supplied length
	//
	// the value (or resolved value) must be a string, map or slice
	RequireLen(value any, length int) Method_
	// RequireHasProperties requires that the value (or resolved value) has the supplied properties
	//
	// the value (or resolved value) must be a map
	RequireHasProperties(value any, propertyNames ...string) Method_
	// RequireOnlyHasProperties requires that the value (or resolved value) only has the supplied properties
	//
	// the value (or resolved value) must be a map
	RequireOnlyHasProperties(value any, propertyNames ...string) Method_

	// AssertMockServiceCalled asserts that a specific mock service endpoint+method was called
	AssertMockServiceCalled(svcName string, path string, method MethodName) Method_
	// RequireMockServiceCalled requires that a specific mock service endpoint+method was called
	RequireMockServiceCalled(svcName string, path string, method MethodName) Method_

	// AssertVarSet asserts that a named variable has been set
	AssertVarSet(v Var) Method_
	// RequireVarSet requires that a named variable has been set
	RequireVarSet(v Var) Method_

	// AssertTrue asserts that the value is true
	//
	// the value (or resolved value) must be a bool, otherwise this fails
	//
	// the value can also be an Expectation (e.g. ExpectEqual) - in which case the boolean is evaluated based on that
	// expectation being met
	AssertTrue(value any) Method_
	// RequireTrue requires that the value is true
	//
	// the value (or resolved value) must be a bool, otherwise this fails
	//
	// the value can also be an Expectation (e.g. ExpectEqual) - in which case the boolean is evaluated based on that
	// expectation being met
	RequireTrue(value any) Method_
	// AssertFalse asserts that the value is false
	//
	// the value (or resolved value) must be a bool, otherwise this fails
	//
	// the value can also be an Expectation (e.g. ExpectEqual) - in which case the boolean is evaluated based on that
	// expectation being unmet
	AssertFalse(value any) Method_
	// RequireFalse requires that the value is false
	//
	// the value (or resolved value) must be a bool, otherwise this fails
	//
	// the value can also be an Expectation (e.g. ExpectEqual) - in which case the boolean is evaluated based on that
	// expectation being unmet
	RequireFalse(value any) Method_
}

type Method_

type Method_ interface {
	common.Method

	// QueryParam sets a http query param to value(s) for the method call
	QueryParam(name string, values ...any) Method_
	// PathParam sets a URL path param for the method call
	//
	// path params are specified in the order in which they appear in the url template
	PathParam(value any) Method_
	// RequestHeader sets a http header for the method call
	RequestHeader(name string, value any) Method_
	// AuthHeader sets the "Authorization" header for the method call
	AuthHeader(scheme AuthScheme, value any) Method_
	// RequestBody sets the http request body for the method call
	RequestBody(value any) Method_
	// UseCookie sets a named cookie to use on the method call
	//
	// the named cookie has to have been previously stored in the Context
	UseCookie(name string) Method_
	// SetCookie sets a cookie to be used for the method call
	SetCookie(cookie *http.Cookie) Method_
	// StoreCookie stores a named cookie from the response in the Context
	StoreCookie(name string) Method_
	// Authorize provides a function that can be used to authorize a http request
	//
	// the func is passed the current Context, and can obtain the built request using Context.CurrentRequest and manipulate it
	//
	// Notes:
	//  * multiple authorize functions can be added.
	//  * authorize functions are called after pre-captures (i.e. Before's) and after the request has been built
	Authorize(func(ctx Context) error) Method_

	MethodExpectations
	MethodCaptures

	// If runs the operations when the condition arg is met
	//
	// Notes:
	//   * the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
	//   * if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the operations are just not performed
	//   * any condition that is not a bool or Expectation will cause an error during tests
	//   * the operations arg can be anything Runnable - any of them that are an Expectation, is run as an expectation (and treated as required) and any unmet or failure errors will be reported
	If(when When, condition any, operations ...Runnable) Method_
	// IfNot runs the operations when the condition arg is not met
	//
	// Notes:
	//   * the condition arg can be a bool value (or value that resolves to a bool) or an Expectation (e.g. ExpectEqual, ExpectNotEqual, etc.)
	//   * if the condition arg is an Expectation, and the expectation is unmet, this does not report a failure or unmet, instead the operations are just not performed
	//   * any condition that is not a bool or Expectation will cause an error during tests
	//   * the operations arg can be anything Runnable - any of them that are an Expectation, is run as an expectation (and treated as required) and any unmet or failure errors will be reported
	IfNot(when When, condition any, operations ...Runnable) Method_
	// ForEach iterates over the value (or resolved value)
	//
	// if the value (or resolved value) is not a slice - an error occurs
	//
	// on each iteration a var is set - use the iterVar arg to set the name of this variable (if the iterVar arg is nil - a var name of "." is used)
	ForEach(when When, value any, iterVar any, ops ...Runnable) Method_

	// FailFast instructs the method to fail on unmet assertions
	//
	// i.e. treat all `Assert...()` as `Require...()`
	FailFast() Method_

	// RequestMarshal provides an override function to build (marshal) the request body
	//
	// only one func is used, so if this is called multiple times - last one wins
	RequestMarshal(fn func(ctx Context, body any) ([]byte, error)) Method_
	// ResponseUnmarshal provides an override function to unmarshal the response body
	//
	// only one func is used, so if this is called multiple times - last one wins
	ResponseUnmarshal(fn func(response *http.Response) (any, error)) Method_
	Runnable
	fmt.Stringer
}

Method_ is the interface implemented by an instantiated Method (see Method(), Get(), Post(), etc.)

func Delete

func Delete(desc string, ops ...BeforeAfter) Method_

Delete instantiates a new DELETE method test

synonymous with calling Method(DELETE, ...)

func Get

func Get(desc string, ops ...BeforeAfter) Method_

Get instantiates a new GET method test

synonymous with calling Method(GET, ...)

func Head(desc string, ops ...BeforeAfter) Method_

Head instantiates a new HEAD method test

synonymous with calling Method(HEAD, ...)

func Method

func Method(verb MethodName, desc string, ops ...BeforeAfter) Method_

Method instantiates a new method test

verb arg is the http method, e.g. "GET", "PUT", "POST" etc.

desc arg is the description of the method test

ops args are any before/after operations to be run as part of the method test

func Patch

func Patch(desc string, ops ...BeforeAfter) Method_

Patch instantiates a new PATCH method test

synonymous with calling Method(PATCH, ...)

func Post

func Post(desc string, ops ...BeforeAfter) Method_

Post instantiates a new POST method test

synonymous with calling Method(POST, ...)

func Put

func Put(desc string, ops ...BeforeAfter) Method_

Put instantiates a new PUT method test

synonymous with calling Method(PUT, ...)

type MultipartField added in v1.5.2

type MultipartField struct {
	Name  string
	Value any
}

type MultipartFile added in v1.5.2

type MultipartFile struct {
	FieldName   string
	FileName    string
	Source      any
	ContentType string
}

type MultipartPart added in v1.5.2

type MultipartPart interface {
	// contains filtered or unexported methods
}

func Field added in v1.5.2

func Field(name string, value any) MultipartPart

Field creates a MultipartPart for use in Multipart

the value can be any type including a resolvable value

func FileField added in v1.5.2

func FileField(fieldName string, fileName string, source any, contentType string) MultipartPart

FileField creates a MultipartPart for use in Multipart

the source is the source data of the file - it can be a resolvable and the type must be either []byte or string. A string value indicates a filename to load the source data from

type NthValue added in v1.5.0

type NthValue struct {
	Value any
	Index int
}

func Nth added in v1.5.0

func Nth(value any, index int) NthValue

Nth resolves to the nth item (element) of the value (or resolved value)

if the value (or resolved value) is not a slice, an empty slice or the index is out-of-bounds - this always resolves to nil

func (NthValue) ResolveValue added in v1.5.0

func (v NthValue) ResolveValue(ctx Context) (av any, err error)

func (NthValue) String added in v1.5.0

func (v NthValue) String() string

type OperandValue

type OperandValue struct {
	Original      any
	Resolved      any
	Coerced       any
	CoercionError error
}

OperandValue is a representation of an operand value - giving the original, resolved & coerced value

func (OperandValue) TestFormat

func (v OperandValue) TestFormat() string

type OrValue added in v1.5.0

type OrValue struct {
	Values []any
}

func Or added in v1.5.0

func Or(values ...any) OrValue

Or is a resolvable value

it resolves by boolean ORing all the supplied values (or their resolved value)

Notes:

  • if any of the values is not a bool, it errors
  • short-circuits on first true
  • if a value is an Expectation, the boolean is deduced from whether the expectation was met
  • nil values are ignored

func (OrValue) ResolveValue added in v1.5.0

func (v OrValue) ResolveValue(ctx Context) (av any, err error)

func (OrValue) String added in v1.5.0

func (v OrValue) String() string

type QueryRowsValue

type QueryRowsValue struct {
	DbName string
	Query  string
	Args   []any
}

func QueryRows

func QueryRows(dbName string, query string, args ...any) QueryRowsValue

QueryRows resolves to a value obtained by executing the query and args against the named database

Notes:

  • if only one supporting database is used in tests, the dbName can be just ""
  • the query **must** start with "SELECT "
  • the resolved value is a `[]map[string]any` representation of the selected rows and columns

func (QueryRowsValue) ResolveValue

func (v QueryRowsValue) ResolveValue(ctx Context) (av any, err error)

type QueryValue

type QueryValue struct {
	DbName string
	Query  string
	Args   []any
}

func Query

func Query(dbName string, query string, args ...any) QueryValue

Query resolves to a value obtained by executing the query and args against the named database

Notes:

  • if only one supporting database is used in tests, the dbName can be just ""
  • the query **must** start with "SELECT "
  • if there is only one selected column, the resolved value will be the value in that column
  • if there are multiple columns selected, the resolved value will be a `map[string]any` representation of the row

func (QueryValue) ResolveValue

func (v QueryValue) ResolveValue(ctx Context) (av any, err error)

func (QueryValue) String

func (v QueryValue) String() string

type RawQuery

type RawQuery string

type Resolvable

type Resolvable interface {
	ResolveValue(ctx Context) (av any, err error)
}

Resolvable is an interface to be implemented by any type where the value is to be resolved

func Auth added in v1.6.0

func Auth(scheme AuthScheme, value any) Resolvable

func AuthUsernamePassword added in v1.6.0

func AuthUsernamePassword(username any, password any) Resolvable

func Jwt added in v1.6.0

func Jwt(secret any, claims ...ClaimValue) Resolvable

Jwt creates an HS256-signed JWT with the given secret and claims

this returns a resolvable value that can be used with Auth - which can then be used by Method_.AuthHeader example:

Method(GET, "do get").
    AuthHeader(BearerAuth, Jwt(
        Var("my-secret"),
        SubjectClaim(Var("my-user")),
        ExpireAfterClaim(5 * time.Minute))

func JwtHS384 added in v1.6.0

func JwtHS384(secret any, claims ...ClaimValue) Resolvable

JwtHS384 creates an HS384-signed JWT with the given secret and claims

this returns a resolvable value that can be used with Auth - which can then be used by Method_.AuthHeader example:

Method(GET, "do get").
    AuthHeader(BearerAuth, JwtHS384(
        Var("my-secret"),
        SubjectClaim(Var("my-user")),
        ExpireAfterClaim(5 * time.Minute))

func JwtHS512 added in v1.6.0

func JwtHS512(secret any, claims ...ClaimValue) Resolvable

JwtHS512 creates an HS512-signed JWT with the given secret and claims

this returns a resolvable value that can be used with Auth - which can then be used by Method_.AuthHeader example:

Method(GET, "do get").
    AuthHeader(BearerAuth, JwtHS512(
        Var("my-secret"),
        SubjectClaim(Var("my-user")),
        ExpireAfterClaim(5 * time.Minute))

type ResponseCookie

type ResponseCookie string

ResponseCookie is a type that will resolve to the specified named cookie in the current Context response

example:

ResponseCookie("session")

will resolve to the named cookie "session" in the current Context response

The resolved value is a `map[string]any` representation of a http.Cookie

func (ResponseCookie) ResolveValue

func (v ResponseCookie) ResolveValue(ctx Context) (av any, err error)

type ResponseHeader

type ResponseHeader string

ResponseHeader is a type that will resolve to the specified header in the current Context response

example:

ResponseHeader("Content-Type")

will resolve to the "Content-Type" header vale in the current Context response

func (ResponseHeader) ResolveValue

func (v ResponseHeader) ResolveValue(ctx Context) (av any, err error)

type Runnable

type Runnable interface {
	Run(ctx Context) error
	framing.Framed
}

type Status

type Status int

type StatusCode

type StatusCode int

StatusCode is a type that indicates resolve to the current Context response status code

func (StatusCode) ResolveValue

func (StatusCode) ResolveValue(ctx Context) (av any, err error)

type Suite_

type Suite_ interface {
	// Init initializes the Suite using the provided withs
	//
	// a with can be from any provided by the [with] package -
	// with.ApiImage, with.Make, with.Database, with.HttpDo, with.ApiHost, with.Testing, with.Var, with.Cookie, with.ReportCoverage, with.CoverageCollector, with.OAS, with.Repeats, with.Logging
	//
	// a with can also be supporting image - see [images] package
	//
	// Note: Init takes a clone of the Suite, so that multiple runners with independent initialisation can be run from the same test endpoint definitions
	Init(withs ...with.With) Suite_
	// Run runs the test suite
	//
	// only critical errors are returned - unmet expectations are not (use coverage to inspect test failures and unmet expectations)
	Run() error
}

Suite_ is the interface for the main API tests runner

func Suite

func Suite(endpoints ...Endpoint_) Suite_

Suite instantiates a new test suite for the provided Endpoint's

type TemplateString

type TemplateString string

TemplateString is a string type that can contain variable markers - which are resolved to produce the final string

variable markers are in the format "{$name}" - or as a concatenated string, e.g. "{$var1}-{$var2}"

markers can also be in the format...

  • "{$env:name}" - where "name" is the name of an environment variable
  • "{$svc:name:token}" - where "name" is the name of a registered supporting image and token is the setting in that service e.g. "host", "port", "mport" (mapped port), "username", "password" (and some supporting services support other tokens, e.g. "{$svc:aws:region}")

when being resolved (against a Context), any variables not found will cause an error in the test

to escape the marker start, use "\{$"

type Type_

type Type_ interface {
	Type() reflect.Type
}

func Type

func Type[T any]() Type_

Type is a generic func to determine a type (as used by Method.AssertType/Method.RequireType)

example:

Method(GET, "").AssertType(Var("foo"), Type[string]())

asserts that the resolved value of Var("foo") is of type string

type UnmetError

type UnmetError interface {
	Error
	Expected() OperandValue
	Actual() OperandValue
	IsComparator() bool
	Comparator() string
	Left() OperandValue
	Right() OperandValue
}

UnmetError represents specific information about an expectation (assert/require) that was unmet

type Var

type Var string

Var is the name of a variable in the current Context

when resolved, if the variable name is not set in the current Context it will cause an error in the test

func (Var) ResolveValue

func (v Var) ResolveValue(ctx Context) (av any, err error)

func (Var) String

func (v Var) String() string

type When

type When int

When is a type that indicates Before or After

const (
	Before When = iota // an operation to run before primary operations (e.g. the actual method http request)
	After              // an operation to be run after primary operations (e.g. the actual method http request)
)

Directories

Path Synopsis
images
localstack module
mysql module
mocks
Package with - provides various options/setups that can be used by marrow.Suite
Package with - provides various options/setups that can be used by marrow.Suite

Jump to

Keyboard shortcuts

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