Documentation
¶
Overview ¶
Package arandutest holds the helpers a test needs and an application must not use.
It is a browser (Client), the assertions worth having about what came back (Response), and the two pieces a test needs to say something about domain events (DrainOutbox, Collected).
This package is a bridge. It is removed in v1.0.0; import github.com/arandu-io/hesape/arandutest directly.
The helpers moved to github.com/arandu-io/hesape/arandutest -- the spelling is arandutest there too, because an import segment called "testing" shadows the standard library package every _test.go imports, and the precedent is net/http/httptest. What is left here is the old names pointing at them.
The death date above is what keeps this from being a second way to import one helper. Nothing here holds an implementation: the cookie jar, the CSRF token read off the last page, every comparison a Response makes and the pass the outbox drain runs are all hesape's. Where the name and the signature survived the move it is a Go alias, and where the design diverged it is an envelope that translates and nothing more.
Two hesape packages answer for it, and which one depends on the symbol:
hesape/arandutest Client, Response, DrainOutbox, Collected hesape/auth the subject a test acts as
One name is a plain alias. The rest are envelopes, and the divergence each one absorbs is worth naming:
Collected the alias. It has to satisfy framework/events.Publisher over
framework/events.Stored, and both of those are hesape's own
types under this module's names
Response every assertion was renamed -- Status becomes AssertStatus, OK
becomes AssertOk, See becomes AssertSee, DontSee becomes
AssertDontSee, RedirectsTo becomes AssertRedirect, Body becomes
GetContent. The envelope keeps the old names and forwards
Client Get and Post answer the Response above, so the client that
returns them is an envelope as well
ActingAs hesape deleted the package-level form and put the subject under
auth.WithSubject, which is the key a policy actually reads. The
old signature is kept and now writes that key
Subject the reader for the above; it is auth.SubjectFrom in hesape
DrainOutbox a forward and not an alias, so the parameters keep the names
this module spells them with. It carried an implementation for
as long as framework/events.Outbox was a type of its own; that
type is an alias now, so the two signatures name the same types
and there is nothing left to translate
What hesape has and this bridge does not re-export ¶
hesape/arandutest also has AssertDatabaseHas, AssertDatabaseMissing, AssertDatabaseCount, Match and Client.ActingAs. None of them ever existed under this import path, and adding them here would be a second place to learn the new API while the old one is being removed. Import hesape/arandutest for those.
Index ¶
- func ActingAs(ctx context.Context, s security.Subject) context.Context
- func DrainOutbox(t *testing.T, ctx context.Context, outbox *events.Outbox, ...)
- func Subject(ctx context.Context) (security.Subject, bool)
- type Client
- type Collected
- type Response
- func (r *Response) Body() string
- func (r *Response) DontSee(text string) *Response
- func (r *Response) Header(name string) string
- func (r *Response) OK() *Response
- func (r *Response) RedirectsTo(want string) *Response
- func (r *Response) See(text string) *Response
- func (r *Response) Status(want int) *Response
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ActingAs ¶ added in v0.18.0
ActingAs is a context carrying a subject, for the code paths that take one directly rather than through a session.
A service, a job and a seeder are all called with a Subject. A test that wants to be somebody for one call does not need a browser, and building a session for it is machinery that proves nothing about what is being tested.
It does NOT put anybody in a session: a request made with Client after this is still anonymous, and it has to be, or the two ways of being somebody would disagree. A test that wants a client to be somebody uses hesape/arandutest.Client.ActingAs, which puts the subject on the outgoing request.
Deleted on the way to hesape: there is no package-level form there, and a subject goes under auth.WithSubject -- the key the edge middleware writes and every policy reads. This is one call to it and nothing else, so the name is the only thing left here that hesape does not spell the same way. The signature is untouched, because security.Subject is an alias for auth.Subject.
It used to hold a context key of its own that no policy, no repository and no middleware ever read, which authenticated nothing: a test written against it passed while proving the opposite of what it said. Naming that is worth a line because it is the reason to reach for auth.WithSubject and not for a key that looks equivalent.
func DrainOutbox ¶
func DrainOutbox(t *testing.T, ctx context.Context, outbox *events.Outbox, publisher events.Publisher)
DrainOutbox publishes everything the outbox is holding, once.
It is the relay, executed inline instead of on a ticker:
arandutest.DrainOutbox(t, ctx, outbox, publisher)
A test that asserts on an event has to wait for it somehow, and the two alternatives are worse. Sleeping is flaky and slow. A synchronous publish path is a second implementation that will drift from the real one.
The parameters keep the names this module spells them with, so the call sites are untouched.
func Subject ¶ added in v0.18.0
Subject reads back what ActingAs put in, and reports whether there was one.
The second result is false when nothing put one there, which is a different fact from an anonymous reader: a public page has the Subject that security.Guest built.
Renamed on the way to hesape: it is auth.SubjectFrom there, and it is not in hesape/arandutest at all, because reading the subject out of a context is not a test-only question.
Types ¶
type Client ¶ added in v0.18.0
type Client struct {
// contains filtered or unexported fields
}
Client is a browser for a test: it keeps cookies and it does not follow redirects.
Not following them is deliberate. A test that asserts about a page after a redirect cannot tell a 200 from a 302 that happened to land somewhere with the same words on it, and "it redirected me to the sign-in screen" is the most common way a feature test passes while proving the opposite of what it says.
The jar, the CSRF token read off the last page, and the rule that a second Set-Cookie of a name replaces the first all live in hesape/arandutest.Client. This type holds nothing but that one.
It is declared here for one reason: Get and Post answer this package's Response, which keeps the assertion names hesape renamed. It becomes an alias the day Response does, and not before.
type Collected ¶
type Collected = arandutest.Collected
Collected is a Publisher that keeps what it received, for a test to assert on.
Its Events field, its Publish and its Names are hesape's, reached through this name. Declaring the struct again here would compile and pass every assertion written against it, and it would be a second recorder to keep in step with the first.
type Response ¶ added in v0.18.0
type Response struct {
// contains filtered or unexported fields
}
Response is what came back, with the assertions worth having.
Renamed on the way to hesape: every method below is spelled Assert* there, and Body is GetContent. Each one forwards to exactly one hesape method -- the comparison, the failure message and whether it stops the test are all decided by the code that runs there.
It is a declaration rather than an alias because of what an alias would carry: the new names, and only those. Every existing call of Status, OK, See, DontSee, RedirectsTo and Body would stop compiling on the day this type changed shape, which is the one thing a bridge exists to prevent. That is the condition, not a count of callers -- one call left anywhere is enough for it to hold, and it stops holding only when there are none.
func (*Response) Body ¶ added in v0.18.0
Body is what came back, for an assertion this package does not have.
Renamed on the way to hesape: it is Response.GetContent there.
func (*Response) DontSee ¶ added in v0.18.0
DontSee fails when the text is in the body.
It is the half people skip, and the half that catches a leak: a draft in a public listing, an address in a page that should not name one, a button somebody without the permission can see.
Renamed on the way to hesape: it is Response.AssertDontSee there.
func (*Response) OK ¶ added in v0.18.0
OK is Status(200).
Renamed on the way to hesape: it is Response.AssertOk there.
func (*Response) RedirectsTo ¶ added in v0.18.0
RedirectsTo fails unless the response sends the client to that address.
It reads HX-Redirect as well as Location, because a handler answering an HTMX request redirects with a header and a 204 -- and a test that only reads Location says "redirected to \"\"" for a response that is correct.
Renamed on the way to hesape: it is Response.AssertRedirect there.
func (*Response) See ¶ added in v0.18.0
See fails unless the text is in the body.
Renamed on the way to hesape: it is Response.AssertSee there.
func (*Response) Status ¶ added in v0.18.0
Status fails unless the status is the one expected.
The body is printed on failure, because the answer to "why is this a 500" is in it and finding out otherwise means running the test again with a print.
Renamed on the way to hesape: it is Response.AssertStatus there.