mock

package
v0.1.29 Latest Latest
Warning

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

Go to latest
Published: Aug 27, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Call added in v0.1.4

type Call struct {
	Op   string
	Args model.Encodable
}

Call records an invocation of a Caller operation.

type Caller added in v0.1.4

type Caller struct {
	Calls []Call

	// CannedResult is the wire response decoded into the Call's `into` target.
	// The mock backs the decode with the real codec (tinywasm/json) so a test
	// exercises the same round-trip a deployed transport performs. A mock — like
	// any router implementation — is infrastructure, so naming a concrete codec
	// here is allowed; a domain module or a view never does.
	CannedResult []byte
	// CannedError is passed to the Call callback.
	CannedError error
}

Caller fakes the call-side contract, recording operations and allowing canned responses to be configured.

func (*Caller) Call added in v0.1.4

func (c *Caller) Call(op string, args model.Encodable, into model.Decodable, done func(err error))

func (*Caller) Dispatch added in v0.1.4

func (c *Caller) Dispatch(op string, args model.Encodable)

type Config added in v0.1.10

type Config struct {
	// Authn establishes identity. It runs BEFORE the access gate: a gate that runs first
	// can never be satisfied, and every guarded route becomes a permanent 403.
	Authn router.Middleware

	// Authorize answers whether an identity holds a permission. nil DENIES.
	Authorize model.Authorizer
}

Config declares WHO the caller is and WHAT they may do — the same two seams the real implementations expose (server/httpd, goflare/edge). The zero value is legal and means "no authentication, no authorizer": public routes work, and every guarded route denies.

type Context

type Context struct {
	InMethod string
	InPath   string
	InBody   []byte

	Status int
	// contains filtered or unexported fields
}

Context buffers the response and lets tests set the request fields. Unlike the base router.Context contract (single-goroutine ownership), this mock IS safe for concurrent use: its role is to let the test goroutine observe (ResponseBody) while a handler goroutine writes.

func (*Context) Body

func (c *Context) Body() []byte

func (*Context) Cookie

func (c *Context) Cookie(name string) (router.Cookie, bool)

func (*Context) Decode added in v0.1.12

func (c *Context) Decode(into model.Decodable) error

Decode reads the request body as JSON into a typed destination. The mock backs Decode with a real codec (tinywasm/json) rather than a fake, so a test proves the same round-trip a deployed transport performs.

func (*Context) Encode added in v0.1.12

func (c *Context) Encode(v model.Encodable) error

Encode writes v as the JSON response body, through the same real codec as Decode.

func (*Context) GetHeader

func (c *Context) GetHeader(key string) string

func (*Context) Method

func (c *Context) Method() string

func (*Context) Param added in v0.1.29

func (c *Context) Param(name string) string

func (*Context) Path

func (c *Context) Path() string

func (*Context) ResponseBody

func (c *Context) ResponseBody() []byte

ResponseBody returns a copy of the buffered response body.

func (*Context) SetCookie

func (c *Context) SetCookie(cookie router.Cookie)

func (*Context) SetHeader

func (c *Context) SetHeader(key, value string)

func (*Context) SetParams added in v0.1.29

func (c *Context) SetParams(names, values []string)

func (*Context) SetUserID added in v0.1.2

func (c *Context) SetUserID(id string)

func (*Context) SetValue

func (c *Context) SetValue(key, value string)

func (*Context) UserID added in v0.1.2

func (c *Context) UserID() string

func (*Context) Value

func (c *Context) Value(key string) string

func (*Context) Write

func (c *Context) Write(b []byte) (int, error)

func (*Context) WriteStatus

func (c *Context) WriteStatus(code int)

type Route

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

Route implements router.Route for the mock, recording permission annotations.

func (*Route) Accepts added in v0.1.12

func (r *Route) Accepts(args model.Fielder) router.Route

func (*Route) Authenticated added in v0.1.9

func (r *Route) Authenticated() router.Route

func (*Route) Public added in v0.1.2

func (r *Route) Public() router.Route

func (*Route) Requires

func (r *Route) Requires(resource model.Resource, action model.Action) router.Route

type Router

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

Router is an in-memory implementation of router.Router for tests.

It is NOT a recorder. It enforces the same contract the deployed implementations do — method routing, closed-by-default access, identity before the gate, middleware behind it — and it proves that by passing router/conformance, exactly like they must.

It used to be a recorder: Invoke called the handler directly and Use was discarded. That made it a fake that could not fail, so every consumer testing against it was testing a fantasy — a guarded route "worked" in their tests and answered 403 in production. That is not a hypothetical: it is how goflare shipped an unusable file API with a green suite.

Stores *Route, not RouteInfo: permission annotations (Public/Requires) are chained AFTER registering the route, so a copy by value taken at registration would never see them and the mock would assert that every route is private.

func (*Router) Configure added in v0.1.10

func (r *Router) Configure(cfg Config)

Configure installs the identity and authorization seams. Call it before dispatching.

func (*Router) Delete

func (r *Router) Delete(path string, h router.HandlerFunc) router.Route

func (*Router) Get

func (r *Router) Get(path string, h router.HandlerFunc) router.Route

func (*Router) Handle

func (r *Router) Handle(method, path string, h router.HandlerFunc) router.Route

func (*Router) Invoke

func (r *Router) Invoke(method, path string, ctx router.Context)

Invoke drives one request through the FULL pipeline: identity, access gate, middleware, handler — the same order a deployed implementation uses.

It used to call the handler directly, skipping the gate. That is why it is worth saying out loud: a fake that cannot reject is not testing your access control, it is hiding it.

func (*Router) Op added in v0.1.12

func (r *Router) Op(name string, h router.HandlerFunc) router.Route

Op registers a route by logical operation name — the provider-side counterpart of Caller.Call(name, args, cb). Internally it reuses the same method+path matching as every other verb, under the synthetic method "OP" and path "/"+name: an implementation detail this mock owns, invisible to a caller that only uses Router.Op and Route.

func (*Router) Options

func (r *Router) Options(path string, h router.HandlerFunc) router.Route

func (*Router) Post

func (r *Router) Post(path string, h router.HandlerFunc) router.Route

func (*Router) PublicAsset added in v0.1.7

func (r *Router) PublicAsset(path string, h router.HandlerFunc)

PublicAsset registers a file served to the browser: public by construction, without Route to return — no permission to attach.

func (*Router) PublicDir added in v0.1.7

func (r *Router) PublicDir(prefix string, dir string)

PublicDir registers a directory served under a prefix.

func (*Router) Put

func (r *Router) Put(path string, h router.HandlerFunc) router.Route

func (*Router) Routes

func (r *Router) Routes() []router.RouteInfo

Routes projects the registered routes at query time, with their permission annotations applied.

func (*Router) Socket

func (r *Router) Socket(path string, h router.SocketFunc) router.Route

func (*Router) Stream

func (r *Router) Stream(path string, h router.StreamFunc) router.Route

func (*Router) Use

func (r *Router) Use(m ...router.Middleware)

Use registers middleware. It runs BEHIND the access gate: a rejected request must not execute business logic.

func (*Router) Verify added in v0.1.10

func (r *Router) Verify() error

Verify reports the contradictions an implementation must refuse to start with. Both deny every caller forever, on a route that looks protected — and a silent 403 in production is the worst possible way to find that out.

Jump to

Keyboard shortcuts

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