Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
codetheweb committed Apr 8, 2024
1 parent 12fbf7c commit c9a0af5
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 1 deletion.
86 changes: 86 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,92 @@ test("foo bar", async (t) => {

## Advanced Usage

### Postgres container de-duping

In rare cases, you may want to spawn more than one Postgres container.

Internally, this library uses an AVA "shared worker". A shared worker is a singleton shared with the entire running test suite, and so one `ava-postgres` shared worker maps to exactly one Postgres container.

To spawn separate shared workers and thus additional Postgres containers, you have two options:

**Specify different version strings for the `postgresVersion` option in the factory function**:

```ts
const getTestPostgresDatabase = getTestPostgresDatabaseFactory({
postgresVersion: "14",
})
```

Each unique version will map to a unique shared worker.

**Set the `workerDedupeKey` option in the factory function**:

```ts
const getTestPostgresDatabase = getTestPostgresDatabaseFactory({
workerDedupeKey: "foo",
})
```

Each unique key will map to a unique shared worker.

### Database de-duping

By default, `ava-postgres` will create a new database for each test. If you want to share a database between tests, you can use the `databaseDedupeKey` option:

```ts
import test from "ava"
const getTestPostgresDatabase = getTestPostgresDatabaseFactory({})

test("foo", async (t) => {
const connection1 = await getTestPostgresDatabase(t, null, {
databaseDedupeKey: "foo",
})
const connection2 = await getTestPostgresDatabase(t, null, {
databaseDedupeKey: "foo",
})
t.is(connection1.database, connection2.database)
})
```

This works across the entire test suite.

Note that if unique parameters are passed to the `beforeTemplateIsBaked` (`null` in the above example), separate databases will still be created.

### "Nested" `beforeTemplateIsBaked` calls

In some cases, if you do extensive setup in your `beforeTemplateIsBaked` hook, you might want to obtain a separate, additional database within it if your application uses several databases for different purposes. This is possible by using the passed `beforeTemplateIsBaked` to your hook callback:

```ts
type DatabaseParams = {
type: "foo" | "bar"
}

const getTestServer = getTestPostgresDatabaseFactory<DatabaseParams>({
beforeTemplateIsBaked: async ({
params,
connection: { pool },
beforeTemplateIsBaked,
}) => {
if (params.type === "foo") {
await pool.query(`CREATE TABLE "foo" ("id" SERIAL PRIMARY KEY)`)
// Important: return early to avoid infinite loop
return
}

await pool.query(`CREATE TABLE "bar" ("id" SERIAL PRIMARY KEY)`)
// This created database will be torn down at the end of the top-level `beforeTemplateIsBaked` call
const fooDatabase = await beforeTemplateIsBaked({
params: { type: "foo" },
})

// This works now
await fooDatabase.pool.query(`INSERT INTO "foo" DEFAULT VALUES`)
},
})
```

Be very careful when using this to avoid infinite loops.

### Bind mounts & `exec`ing in the container

`ava-postgres` uses [testcontainers](https://www.npmjs.com/package/testcontainers) under the hood to manage the Postgres container.
Expand Down
61 changes: 60 additions & 1 deletion src/public-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,50 @@ export interface GetTestPostgresDatabaseFactoryOptions<
}

/**
* Test workers will be de-duped by this key. You probably don't need to set this.
* In rare cases, you may want to spawn more than one Postgres container.
* Internally, this library uses an AVA "shared worker". A shared worker is a singleton shared with the entire running test suite, and so one `ava-postgres` shared worker maps to exactly one Postgres container.
* To spawn separate shared workers and thus additional Postgres containers, you can specify a custom key here.
* Each unique key will map to a unique shared worker/unique Postgres container.
*/
workerDedupeKey?: string
beforeTemplateIsBaked?: (options: {
connection: ConnectionDetails
params: Params
containerExec: (command: string[]) => Promise<ExecResult>
/**
*
* In some cases, if you do extensive setup in your `beforeTemplateIsBaked` hook, you might want to obtain a separate, additional database within it if your application uses several databases for different purposes. This is possible by using the passed `beforeTemplateIsBaked` to your hook callback.
* Be very careful when using this to avoid infinite loops.
* @example
* ```ts
* type DatabaseParams = {
* type: "foo" | "bar"
* }
* const getTestServer = getTestPostgresDatabaseFactory<DatabaseParams>({
* beforeTemplateIsBaked: async ({
* params,
* connection: { pool },
* beforeTemplateIsBaked,
* }) => {
* if (params.type === "foo") {
* await pool.query(`CREATE TABLE "foo" ("id" SERIAL PRIMARY KEY)`)
* // Important: return early to avoid infinite loop
* return
* }
* await pool.query(`CREATE TABLE "bar" ("id" SERIAL PRIMARY KEY)`)
* // This created database will be torn down at the end of the top-level `beforeTemplateIsBaked` call
* const fooDatabase = await beforeTemplateIsBaked({
* params: { type: "foo" },
* })
* // This works now
* await fooDatabase.pool.query(`INSERT INTO "foo" DEFAULT VALUES`)
* },
* })
* ```
*/
beforeTemplateIsBaked: (
options: {
params: Params
Expand All @@ -71,6 +108,28 @@ export type GetTestPostgresDatabaseOptions = {
/**
* If `getTestPostgresDatabase()` is called multiple times with the same `key` and `params`, the same database is guaranteed to be returned.
*/
/**
* By default, `ava-postgres` will create a new database for each test. If you want to share a database between tests, you can use the `databaseDedupeKey` option.
* This works across the entire test suite.
*
* Note that if unique parameters are passed to the `beforeTemplateIsBaked` (`null` in the above example), separate databases will still be created.
* @example
* ```ts
* import test from "ava"
*
* const getTestPostgresDatabase = getTestPostgresDatabaseFactory({})
*
* test("foo", async (t) => {
* const connection1 = await getTestPostgresDatabase(t, null, {
* databaseDedupeKey: "foo",
* })
* const connection2 = await getTestPostgresDatabase(t, null, {
* databaseDedupeKey: "foo",
* })
* t.is(connection1.database, connection2.database)
* })
* ```
*/
databaseDedupeKey?: string
}

Expand Down

0 comments on commit c9a0af5

Please sign in to comment.