{"id":13799747,"url":"https://github.com/seamapi/ava-postgres","last_synced_at":"2025-07-28T08:42:57.678Z","repository":{"id":79046952,"uuid":"531657377","full_name":"seamapi/ava-postgres","owner":"seamapi","description":"🐘 instantly stand up full Postgres databases in your AVA tests","archived":false,"fork":false,"pushed_at":"2025-02-10T22:41:36.000Z","size":604,"stargazers_count":5,"open_issues_count":7,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-05T20:15:44.076Z","etag":null,"topics":["ava","postgres","testcontainers"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seamapi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-09-01T19:23:24.000Z","updated_at":"2024-11-23T06:26:00.000Z","dependencies_parsed_at":"2024-01-02T23:41:38.709Z","dependency_job_id":"97e7638e-1883-4894-979c-ce6f3f2e90f6","html_url":"https://github.com/seamapi/ava-postgres","commit_stats":{"total_commits":116,"total_committers":6,"mean_commits":"19.333333333333332","dds":0.2931034482758621,"last_synced_commit":"728e596444c99450a4aefc7e846f3e4e7a032d84"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fava-postgres","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fava-postgres/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fava-postgres/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seamapi%2Fava-postgres/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seamapi","download_url":"https://codeload.github.com/seamapi/ava-postgres/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248788855,"owners_count":21161726,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ava","postgres","testcontainers"],"created_at":"2024-08-04T00:01:05.700Z","updated_at":"2025-04-13T21:51:07.685Z","avatar_url":"https://github.com/seamapi.png","language":"TypeScript","readme":"# ava-postgres\n\n`ava-postgres` is a test fixture for [AVA](https://github.com/avajs/ava) that provides you with nearly-instant access to a fresh Postgres database for every test.\n\n`ava-postgres`'s only dependency is a running instance of Docker.\n\n## Installation\n\n```sh\nnpm install --save-dev ava-postgres\n```\n\nor\n\n```sh\nyarn add --dev ava-postgres\n```\n\n## Usage\n\n`ava-postgres`'s main export is a factory function, so you'll probably want to create a file like `tests/fixtures/get-test-database.ts`:\n\n```ts\nimport { getTestPostgresDatabaseFactory } from \"ava-postgres\"\n\nexport const getTestDatabase = getTestPostgresDatabaseFactory({\n  // Any tag for the official Postgres Docker image, defaults to \"14\"\n  postgresVersion: \"14\",\n})\n```\n\nThen, in your tests, you can use the `getTestDatabase()` function to get a fresh database for each test:\n\n```ts\nimport test from \"ava\"\nimport { getTestDatabase } from \"./fixtures/get-test-database\"\n\ntest(\"foo bar\", async (t) =\u003e {\n  const { pool } = await getTestDatabase()\n\n  await pool.query(\"SELECT 1\")\n\n  t.pass()\n})\n```\n\n[Full list of connection details returned by `getTestDatabase`](https://github.com/seamapi/ava-postgres/blob/e0de63b2d1f5562e33ae355848cf23bca08b82bb/src/public-types.ts#L6)\n\n### Database setup\n\n`ava-postgres` uses [Postgres templates](https://www.postgresql.org/docs/current/manage-ag-templatedbs.html) so you only pay the setup cost once. After a template has been created, Postgres can create a new database from it in milliseconds.\n\nIf you want to perform common database setup, you can use a hook and pass parameters to the `getTestDatabase()` function:\n\n```ts\nimport { getTestPostgresDatabaseFactory } from \"ava-postgres\"\n\ntype GetTestDatabaseParams = {\n  shouldMigrate?: boolean\n  shouldSeed?: boolean\n}\n\nexport const getTestDatabase =\n  getTestPostgresDatabaseFactory\u003cGetTestDatabaseParams\u003e({\n    beforeTemplateIsBaked: async ({\n      connection: { pool },\n      params: { shouldMigrate, shouldSeed },\n    }) =\u003e {\n      if (shouldMigrate) {\n        await pool.query(\"CREATE TABLE foo (id int)\")\n      }\n\n      if (shouldSeed) {\n        await pool.query(\"INSERT INTO foo VALUES (1)\")\n      }\n    },\n  })\n```\n\nThen, in your tests, you can pass parameters to the `getTestDatabase()` function:\n\n```ts\nimport test from \"ava\"\nimport { getTestDatabase } from \"./fixtures/get-test-database\"\n\ntest(\"foo bar\", async (t) =\u003e {\n  const { pool } = await getTestDatabase({\n    shouldMigrate: true,\n    shouldSeed: true,\n  })\n\n  await pool.query(\"SELECT * FROM foo\")\n\n  t.pass()\n})\n```\n\n## Advanced Usage\n\n### Postgres container de-duping\n\nIn rare cases, you may want to spawn more than one Postgres container.\n\nInternally, 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.\n\nTo spawn separate shared workers and thus additional Postgres containers, you have two options:\n\n**Specify different version strings for the `postgresVersion` option in the factory function**:\n\n```ts\nconst getTestPostgresDatabase = getTestPostgresDatabaseFactory({\n  postgresVersion: \"14\",\n})\n```\n\nEach unique version will map to a unique shared worker.\n\n**Set the `workerDedupeKey` option in the factory function**:\n\n```ts\nconst getTestPostgresDatabase = getTestPostgresDatabaseFactory({\n  workerDedupeKey: \"foo\",\n})\n```\n\nEach unique key will map to a unique shared worker.\n\n### Database de-duping\n\nBy 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:\n\n```ts\nimport test from \"ava\"\nconst getTestPostgresDatabase = getTestPostgresDatabaseFactory({})\n\ntest(\"foo\", async (t) =\u003e {\n  const connection1 = await getTestPostgresDatabase(t, null, {\n    databaseDedupeKey: \"foo\",\n  })\n  const connection2 = await getTestPostgresDatabase(t, null, {\n    databaseDedupeKey: \"foo\",\n  })\n  t.is(connection1.database, connection2.database)\n})\n```\n\nThis works across the entire test suite.\n\nNote that if unique parameters are passed to the `beforeTemplateIsBaked` (`null` in the above example), separate databases will still be created.\n\n### Manual template creation\n\nIn 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:\n\n```ts\nimport test from \"ava\"\n\nconst getTestDatabase = getTestPostgresDatabaseFactory\u003cDatabaseParams\u003e({\n  beforeTemplateIsBaked: async ({\n    params,\n    connection: { pool },\n    manuallyBuildAdditionalTemplate,\n  }) =\u003e {\n    await pool.query(`CREATE TABLE \"bar\" (\"id\" SERIAL PRIMARY KEY)`)\n\n    const fooTemplateBuilder = await manuallyBuildAdditionalTemplate()\n    await fooTemplateBuilder.connection.pool.query(\n      `CREATE TABLE \"foo\" (\"id\" SERIAL PRIMARY KEY)`\n    )\n    const { templateName: fooTemplateName } = await fooTemplateBuilder.finish()\n\n    return { fooTemplateName }\n  },\n})\n\ntest(\"foo\", async (t) =\u003e {\n  const barDatabase = await getTestDatabase({ type: \"bar\" })\n\n  // the \"bar\" database has the \"bar\" table...\n  await t.notThrowsAsync(async () =\u003e {\n    await barDatabase.pool.query(`SELECT * FROM \"bar\"`)\n  })\n\n  // ...but not the \"foo\" table...\n  await t.throwsAsync(async () =\u003e {\n    await barDatabase.pool.query(`SELECT * FROM \"foo\"`)\n  })\n\n  // ...and we can obtain a separate database with the \"foo\" table\n  const fooDatabase = await getTestDatabase.fromTemplate(\n    t,\n    barDatabase.beforeTemplateIsBakedResult.fooTemplateName\n  )\n  await t.notThrowsAsync(async () =\u003e {\n    await fooDatabase.pool.query(`SELECT * FROM \"foo\"`)\n  })\n})\n```\n\n### Bind mounts \u0026 `exec`ing in the container\n\n`ava-postgres` uses [testcontainers](https://www.npmjs.com/package/testcontainers) under the hood to manage the Postgres container.\n\nIn some scenarios you might want to mount a SQL script into the container and manually load it using `psql`.\n\nYou can do this with the `bindMounts` option:\n\n```ts\nconst getTestPostgresDatabase = getTestPostgresDatabaseFactory({\n  container: {\n    bindMounts: [\n      {\n        source: \"/path/on/host\",\n        target: \"/test.sql\",\n      },\n    ],\n  },\n  beforeTemplateIsBaked: async ({\n    connection: { username, database },\n    containerExec,\n  }) =\u003e {\n    const { exitCode } = await containerExec(\n      `psql -U ${username} -d ${database} -f /test.sql`.split(\" \")\n    )\n\n    if (exitCode !== 0) {\n      throw new Error(`Failed to load test file`)\n    }\n  },\n})\n```\n","funding_links":[],"categories":["Official Projects","Packages"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fava-postgres","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseamapi%2Fava-postgres","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseamapi%2Fava-postgres/lists"}