Documentation
¶
Overview ¶
Package tests provides common helpers and mocks used in PocketBase application tests.
Index ¶
- Constants
- func DropOrphanTestDatabases() ([]string, error)
- func DropOrphanTestRoles() ([]string, error)
- func DropTestDatabase(name string) error
- func MockMultipartData(data map[string]string, fileFields ...string) (*bytes.Buffer, *multipart.Writer, error)
- func RunWithRLSRole(app core.App, role string, token string, fn func(txApp core.App) error) error
- func StubLogsData(app *TestApp) error
- func StubMFARecords(app core.App) error
- func StubOTPRecords(app core.App) error
- func TempDirClone(dirToClone string) (string, error)
- func TestValidationErrors(t *testing.T, rawErrors error, expectedErrors []string)
- type ApiScenario
- type TestApp
- type TestDatabase
- type TestMailer
Constants ¶
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_" )
const ( GoldenDynamic = "<dynamic>" GoldenJWT = "<jwt>" GoldenNow = "<now>" )
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).
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).
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 ¶
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 ¶
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 ¶
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 ¶
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 StubMFARecords ¶
func StubOTPRecords ¶
func TempDirClone ¶
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 ¶
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 ¶
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 ¶
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.
Source Files
¶
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. |