Skip to content

Commit

Permalink
Fix docs
Browse files Browse the repository at this point in the history
  • Loading branch information
codetheweb committed Apr 9, 2024
1 parent 43cd15f commit 26123da
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 101 deletions.
56 changes: 36 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,40 +148,56 @@ 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
### Manual template creation

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:
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 `manuallyBuildAdditionalTemplate()` function passed to your hook callback:

```ts
type DatabaseParams = {
type: "foo" | "bar"
}
import test from "ava"

const getTestServer = getTestPostgresDatabaseFactory<DatabaseParams>({
const getTestDatabase = getTestPostgresDatabaseFactory<DatabaseParams>({
beforeTemplateIsBaked: async ({
params,
connection: { pool },
beforeTemplateIsBaked,
manuallyBuildAdditionalTemplate,
}) => {
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`)
const fooTemplateBuilder = await manuallyBuildAdditionalTemplate()
await fooTemplateBuilder.connection.pool.query(
`CREATE TABLE "foo" ("id" SERIAL PRIMARY KEY)`
)
const { templateName: fooTemplateName } = await fooTemplateBuilder.finish()

return { fooTemplateName }
},
})

test("foo", async (t) => {
const barDatabase = await getTestDatabase({ type: "bar" })

// the "bar" database has the "bar" table...
await t.notThrowsAsync(async () => {
await barDatabase.pool.query(`SELECT * FROM "bar"`)
})

// ...but not the "foo" table...
await t.throwsAsync(async () => {
await barDatabase.pool.query(`SELECT * FROM "foo"`)
})

// ...and we can obtain a separate database with the "foo" table
const fooDatabase = await getTestDatabase.fromTemplate(
t,
barDatabase.beforeTemplateIsBakedResult.fooTemplateName
)
await t.notThrowsAsync(async () => {
await fooDatabase.pool.query(`SELECT * FROM "foo"`)
})
})
```

Be very careful when using this to avoid infinite loops.
Although it's not shown in the above example, because of `ava-postgres`'s automatic de-duping by parameter combinations, any returned template name is "linked" to the parameters passed to the `getTestDatabase()` function.

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

Expand Down
79 changes: 36 additions & 43 deletions src/public-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,37 +59,52 @@ export interface GetTestPostgresDatabaseFactoryOptions<
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.
*
* 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>({
* import test from "ava"
*
* const getTestDatabase = getTestPostgresDatabaseFactory<DatabaseParams>({
* beforeTemplateIsBaked: async ({
* params,
* connection: { pool },
* beforeTemplateIsBaked,
* manuallyBuildAdditionalTemplate,
* }) => {
* 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`)
*
* const fooTemplateBuilder = await manuallyBuildAdditionalTemplate()
* await fooTemplateBuilder.connection.pool.query(
* `CREATE TABLE "foo" ("id" SERIAL PRIMARY KEY)`
* )
* const { templateName: fooTemplateName } = await fooTemplateBuilder.finish()
*
* return { fooTemplateName }
* },
* })
*
* test("foo", async (t) => {
* const barDatabase = await getTestDatabase({ type: "bar" })
*
* // the "bar" database has the "bar" table...
* await t.notThrowsAsync(async () => {
* await barDatabase.pool.query(`SELECT * FROM "bar"`)
* })
*
* // ...but not the "foo" table...
* await t.throwsAsync(async () => {
* await barDatabase.pool.query(`SELECT * FROM "foo"`)
* })
*
* // ...and we can obtain a separate database with the "foo" table
* const fooDatabase = await getTestDatabase.fromTemplate(
* t,
* barDatabase.beforeTemplateIsBakedResult.fooTemplateName
* )
* await t.notThrowsAsync(async () => {
* await fooDatabase.pool.query(`SELECT * FROM "foo"`)
* })
* })
* ```
*/
manuallyBuildAdditionalTemplate: () => Promise<{
Expand All @@ -104,28 +119,6 @@ export interface GetTestPostgresDatabaseResult extends ConnectionDetails {
}

export type GetTestPostgresDatabaseOptions = {
/**
* 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)
* })
* ```
*/
/**
* 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.
Expand Down
35 changes: 0 additions & 35 deletions src/tests/cleanup/does-database-exist.ts

This file was deleted.

6 changes: 3 additions & 3 deletions src/tests/hooks.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,10 @@ test("beforeTemplateIsBaked (result isn't serializable)", async (t) => {
)
})

test("beforeTemplateIsBaked, get nested database", async (t) => {
test("beforeTemplateIsBaked with manual template build", async (t) => {
const getTestDatabase = getTestPostgresDatabaseFactory({
postgresVersion: process.env.POSTGRES_VERSION,
workerDedupeKey: "beforeTemplateIsBakedHookNestedDatabase",
workerDedupeKey: "beforeTemplateIsBakedHookManualTemplateBuild",
beforeTemplateIsBaked: async ({
connection: { pool },
manuallyBuildAdditionalTemplate,
Expand Down Expand Up @@ -178,7 +178,7 @@ test("beforeTemplateIsBaked, get nested database", async (t) => {

await t.notThrowsAsync(async () => {
await fooDatabase.pool.query('SELECT * FROM "foo"')
})
}, "foo table should exist on database manually created from template")

await t.throwsAsync(async () => {
await fooDatabase.pool.query('SELECT * FROM "bar"')
Expand Down

0 comments on commit 26123da

Please sign in to comment.