Help us shape the future of Go! Take the 2026 Go Developer Survey

tests

package
v1.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 37 Imported by: 0

Documentation

Overview

Package tests provides common helpers and mocks used in PocketBase application tests.

Index

Constants

View Source
const (
	// TestDatabasePrefix is the name prefix of the per test databases.
	TestDatabasePrefix = "popgres_t_"

	// FixturesDatabasePrefix is the name prefix of the databases with preloaded fixtures.
	FixturesDatabasePrefix = "popgres_fx_"
)
View Source
const (
	GoldenDynamic = "<dynamic>"
	GoldenJWT     = "<jwt>"
	GoldenNow     = "<now>"
)
View Source
const FixturesFile = "data.pg.sql"

FixturesFile is the name of the SQL fixtures file in the tests data directory (generated with scripts/gen-fixtures.sh).

View Source
const GoldenEnvVar = "POPGRES_GOLDEN"

GoldenEnvVar is the env variable that controls the capture of the API golden files used to verify the response compatibility with PocketBase.

The response of every passing ApiScenario is saved in tests/golden/api/<package>/<test>/<subtest>.json when it is set to:

  • "write" - overwrites any existing golden file;
  • "merge" - compares with the existing golden file (if any) and replaces every value that differs with GoldenDynamic.

The expected workflow is a "write" run followed by a "merge" run so that the values that change between executions (generated ids, random ports, etc.) are masked.

Object keys are sorted because PocketBase doesn't guarantee the order of the keys of map values (encoding/json/v2 without json.Deterministic).

View Source
const TestDatabaseURLEnv = "POPGRES_TEST_URL"

TestDatabaseURLEnv is the env variable with the connection string of the template database used by the tests (eg. postgres://user:pass@localhost:5433/popgres_test).

The template database itself is never modified. Each test app works on its own "popgres_t_*" copy that is created and dropped through the "postgres" maintenance database of the same server.

Variables

This section is empty.

Functions

func DropOrphanTestDatabases

func DropOrphanTestDatabases() ([]string, error)

DropOrphanTestDatabases drops all test and fixtures databases of the TestDatabaseURLEnv server and returns the names of the dropped ones.

It must be used only when there are no running tests (eg. "make test-clean").

func DropOrphanTestRoles

func DropOrphanTestRoles() ([]string, error)

DropOrphanTestRoles drops the leftover test roles ("popgres_t_*", eg. created by the replication fallback tests) of the TestDatabaseURLEnv server and returns the names of the dropped ones.

It must be used only when there are no running tests and after the orphan test databases drop (eg. "make test-clean").

func DropTestDatabase

func DropTestDatabase(name string) error

DropTestDatabase drops the specified test database (closing any remaining connection to it).

Only the databases with the TestDatabasePrefix or FixturesDatabasePrefix are allowed to be dropped.

func MockMultipartData

func MockMultipartData(data map[string]string, fileFields ...string) (*bytes.Buffer, *multipart.Writer, error)

MockMultipartData creates a mocked multipart/form-data payload.

Example

data, mp, err := tests.MockMultipartData(
	map[string]string{"title": "new"},
	"file1",
	"file2",
	...
)

func RunWithRLSRole

func RunWithRLSRole(app core.App, role string, token string, fn func(txApp core.App) error) error

RunWithRLSRole executes fn in a transaction (always rolled back) as the provided external RLS role (core.RLSAnonRole or core.RLSAuthenticatedRole).

The connection role of the tests is a superuser (locally) or the tables owner (in the CI) and both bypass the RLS policies, so the policies must be checked only after switching the role. Before calling fn it verifies that the current role is the expected one and that it can't bypass RLS.

If token is not empty, it is verified and set with popgres_rls.set_claims.

func StubLogsData

func StubLogsData(app *TestApp) error

func StubMFARecords

func StubMFARecords(app core.App) error

func StubOTPRecords

func StubOTPRecords(app core.App) error

func TempDirClone

func TempDirClone(dirToClone string) (string, error)

TempDirClone creates a new temporary directory copy from the provided directory path.

It is the caller's responsibility to call `os.RemoveAll(tempDir)` when the directory is no longer needed!

func TestValidationErrors

func TestValidationErrors(t *testing.T, rawErrors error, expectedErrors []string)

TestValidationErrors checks whether the provided rawErrors are instance of validation.Errors and contains the expectedErrors keys.

Types

type ApiScenario

type ApiScenario struct {
	// Name is the test name.
	Name string

	// Method is the HTTP method of the test request to use.
	Method string

	// URL is the url/path of the endpoint you want to test.
	URL string

	// Body specifies the body to send with the request.
	//
	// For example:
	//
	//	strings.NewReader(`{"title":"abc"}`)
	Body io.Reader

	// Headers specifies the headers to send with the request (e.g. "Authorization": "abc")
	Headers map[string]string

	// Delay adds a delay before checking the expectations usually
	// to ensure that all fired non-awaited go routines have finished
	Delay time.Duration

	// Timeout specifies how long to wait before cancelling the request context.
	//
	// A zero or negative value means that there will be no timeout.
	Timeout time.Duration

	// DisableTestAppCleanup disables the builtin TestApp cleanup at
	// the end of the ApiScenario execution.
	//
	// This option works only when explicit TestAppFactory is specified
	// and means that the developer is responsible to do the necessary
	// after test cleanup on their own (e.g. by manually calling testApp.Cleanup()).
	DisableTestAppCleanup bool

	// ExpectedStatus specifies the expected response HTTP status code.
	ExpectedStatus int

	// List of keywords that MUST exist in the response body.
	//
	// Either ExpectedContent or NotExpectedContent must be set if the response body is non-empty.
	// Leave both fields empty if you want to ensure that the response didn't have any body (e.g. 204).
	ExpectedContent []string

	// List of keywords that MUST NOT exist in the response body.
	//
	// Either ExpectedContent or NotExpectedContent must be set if the response body is non-empty.
	// Leave both fields empty if you want to ensure that the response didn't have any body (e.g. 204).
	NotExpectedContent []string

	// List of hook events to check whether they were fired or not.
	//
	// You can use the wildcard "*" event key if you want to ensure
	// that no other hook events except those listed have been fired.
	//
	// For example:
	//
	//	map[string]int{ "*": 0 } // no hook events were fired
	//	map[string]int{ "*": 0, "EventA": 2 } // no hook events, except EventA were fired
	//	map[string]int{ "EventA": 2, "EventB": 0 } // ensures that EventA was fired exactly 2 times and EventB exactly 0 times.
	ExpectedEvents map[string]int

	TestAppFactory func(t testing.TB) *TestApp
	BeforeTestFunc func(t testing.TB, app *TestApp, e *core.ServeEvent)
	AfterTestFunc  func(t testing.TB, app *TestApp, res *http.Response)
}

ApiScenario defines a single api request test case/scenario.

func (*ApiScenario) Benchmark

func (scenario *ApiScenario) Benchmark(b *testing.B)

Benchmark benchmarks the test scenario.

Example:

func BenchmarkListExample(b *testing.B) {
    scenario := tests.ApiScenario{
        Name:           "list example collection",
        Method:         http.MethodGet,
        URL:            "/api/collections/example/records",
        ExpectedStatus: 200,
        ExpectedContent: []string{
            `"totalItems":3`,
            `"id":"0yxhwia2amd8gec"`,
            `"id":"achvryl401bhse3"`,
            `"id":"llvuca81nly1qls"`,
        },
        ExpectedEvents: map[string]int{
            "OnRecordsListRequest": 1,
            "OnRecordEnrich":       3,
        },
    }

    scenario.Benchmark(b)
}

func (*ApiScenario) Test

func (scenario *ApiScenario) Test(t *testing.T)

Test executes the test scenario.

Example:

func TestListExample(t *testing.T) {
    scenario := tests.ApiScenario{
        Name:           "list example collection",
        Method:         http.MethodGet,
        URL:            "/api/collections/example/records",
        ExpectedStatus: 200,
        ExpectedContent: []string{
            `"totalItems":3`,
            `"id":"0yxhwia2amd8gec"`,
            `"id":"achvryl401bhse3"`,
            `"id":"llvuca81nly1qls"`,
        },
        ExpectedEvents: map[string]int{
            "OnRecordsListRequest": 1,
            "OnRecordEnrich":       3,
        },
    }

    scenario.Test(t)
}

type TestApp

type TestApp struct {
	*core.BaseApp

	// EventCalls defines a map to inspect which app events
	// (and how many times) were triggered.
	EventCalls map[string]int

	TestMailer *TestMailer
	// contains filtered or unexported fields
}

TestApp is a wrapper app instance used for testing.

func NewEmptyTestApp

func NewEmptyTestApp() (*TestApp, error)

NewEmptyTestApp creates and initializes a test application instance with an empty database (only the system migrations, without the test fixtures).

It is the caller's responsibility to call app.Cleanup() when the app is no longer needed.

func NewTestApp

func NewTestApp(optTestDataDir ...string) (*TestApp, error)

NewTestApp creates and initializes a test application instance.

It is the caller's responsibility to call app.Cleanup() when the app is no longer needed.

func NewTestAppWithConfig

func NewTestAppWithConfig(config core.BaseAppConfig) (*TestApp, error)

NewTestAppWithConfig creates and initializes a test application instance from the provided config.

If config.DataDir is not set it fallbacks to the default internal test data directory.

config.DataDir is cloned for each new test application instance.

If config.DatabaseURL is not set, a new database with the default test fixtures is created (see NewFixturesTestDatabase) and dropped on app.Cleanup().

It is the caller's responsibility to call app.Cleanup() when the app is no longer needed.

func (*TestApp) Cleanup

func (t *TestApp) Cleanup()

Cleanup resets the test application state and removes the test app's dataDir from the filesystem and its temporary database.

After this call, the app instance shouldn't be used anymore.

func (*TestApp) ResetEventCalls

func (t *TestApp) ResetEventCalls()

ResetEventCalls resets the EventCalls counter.

type TestDatabase

type TestDatabase struct {
	// Name is the database name.
	Name string

	// URL is the connection string of the database.
	URL string
}

TestDatabase describes a single temporary test database.

func NewFixturesTestDatabase

func NewFixturesTestDatabase() (*TestDatabase, error)

NewFixturesTestDatabase creates a new test database with the default test fixtures (see FixturesFile).

It is the caller's responsibility to call DropTestDatabase when the database is no longer needed.

func NewTestDatabase

func NewTestDatabase() (*TestDatabase, error)

NewTestDatabase creates a new empty database (only the extensions and no tables) from the TestDatabaseURLEnv template database.

It is the caller's responsibility to call DropTestDatabase when the database is no longer needed.

type TestMailer

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

TestMailer is a mock mailer.Mailer implementation.

func (*TestMailer) FirstMessage

func (tm *TestMailer) FirstMessage() mailer.Message

FirstMessage returns a shallow copy of the first sent message.

Returns an empty mailer.Message struct if there are no sent messages.

func (*TestMailer) LastMessage

func (tm *TestMailer) LastMessage() mailer.Message

LastMessage returns a shallow copy of the last sent message.

Returns an empty mailer.Message struct if there are no sent messages.

func (*TestMailer) Messages

func (tm *TestMailer) Messages() []*mailer.Message

Messages returns a shallow copy of all of the collected test messages.

func (*TestMailer) Reset

func (tm *TestMailer) Reset()

Reset clears any previously test collected data.

func (*TestMailer) Send

func (tm *TestMailer) Send(m *mailer.Message) error

Send implements mailer.Mailer interface.

func (*TestMailer) TotalSend

func (tm *TestMailer) TotalSend() int

TotalSend returns the total number of sent messages.

Directories

Path Synopsis
cmd
parity command
Command parity compares the output of "go test -json ./..." with the list of the passing tests of PocketBase v0.40.6 (tests/golden/pocketbase-v0.40.6-tests.txt).
Command parity compares the output of "go test -json ./..." with the list of the passing tests of PocketBase v0.40.6 (tests/golden/pocketbase-v0.40.6-tests.txt).
testclean command
Command testclean drops the leftover test databases ("popgres_t_*" and "popgres_fx_*") and test roles ("popgres_t_*") of the POPGRES_TEST_URL server.
Command testclean drops the leftover test databases ("popgres_t_*" and "popgres_fx_*") and test roles ("popgres_t_*") of the POPGRES_TEST_URL server.

Jump to

Keyboard shortcuts

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