Skip to content

Commit

Permalink
Use testcontainers for API integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
textbook committed Aug 23, 2024
1 parent 3c8443e commit 5c297c0
Show file tree
Hide file tree
Showing 7 changed files with 1,151 additions and 12 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ jobs:
node-version: ${{ matrix.node }}
- uses: textbook/take-action@playwright
- run: npm run lint
- run: npm run migration up
- run: npm run test:cover
env:
FORCE_COLOR: true
- run: npm run migration up
- run: npm run e2e
- run: npm run e2e:dev
docker:
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- [x] [React] client with [Vite]
- [x] Client-side routing with [React Router]
- [x] Linting with [ESLint] and [Prettier]
- [x] Unit and integration testing with [Vitest] and [Jest] (with [SuperTest])
- [x] Unit and integration testing with [Vitest] and [Jest] (with [SuperTest] and [TestContainers])
- [x] E2E testing with [Playwright]
- [x] Dev mode (watch modes for client and server, proxy to avoid CORS issues)
- [x] Production build (single deployment artifact)
Expand Down Expand Up @@ -47,6 +47,7 @@ commonly use:
[React Router]: https://reactrouter.com/en/main
[Render]: https://render.com/
[SuperTest]: https://github.com/visionmedia/supertest
[TestContainers]: https://testcontainers.com/
[Vercel]: https://vercel.com/
[Vite]: https://vitejs.dev/
[Vitest]: https://vitest.dev/
Expand Down
19 changes: 13 additions & 6 deletions api/db.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import pg from "pg";

import config from "./utils/config.cjs";
import logger from "./utils/logger.js";

const pool = new pg.Pool(config.dbConfig);
/** @type {pg.Pool} */
let pool;

pool.on("error", (err) => logger.error("%O", err));

export const connectDb = async () => {
/**
* @param {import("pg").ClientConfig} config
*/
export const connectDb = async (config) => {
pool = new pg.Pool(config);
pool.on("error", (err) => logger.error("%O", err));
const client = await pool.connect();
logger.info("connected to %s", client.database);
client.release();
};

export const disconnectDb = async () => await pool.end();
export const disconnectDb = async () => {
if (pool) {
await pool.end();
}
};

export default {
query(...args) {
Expand Down
1 change: 1 addition & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"winston": "^3.14.2"
},
"devDependencies": {
"@testcontainers/postgresql": "^10.11.0",
"eslint-plugin-jest": "^28.8.0",
"eslint-plugin-n": "^17.10.2",
"supertest": "^7.0.0"
Expand Down
2 changes: 1 addition & 1 deletion api/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ import logger from "./utils/logger.js";

const { port } = config;

await connectDb();
await connectDb(config.dbConfig);

app.listen(port, () => logger.info(`listening on ${port}`));
34 changes: 32 additions & 2 deletions api/setupTests.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,35 @@
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";

import { PostgreSqlContainer } from "@testcontainers/postgresql";
import { runner } from "node-pg-migrate";

import { connectDb, disconnectDb } from "./db.js";

beforeAll(() => connectDb());
const __dirname = dirname(fileURLToPath(import.meta.url));

/** @type {import("@testcontainers/postgresql").StartedPostgreSqlContainer} */
let dbContainer;

beforeAll(async () => {
dbContainer = await new PostgreSqlContainer().start();
const connectionString = dbContainer.getConnectionUri();
await applyMigrations(connectionString);
await connectDb({ connectionString });
}, 60_000);

afterAll(async () => {
await disconnectDb();
if (dbContainer) {
await dbContainer.stop();
}
});

afterAll(() => disconnectDb());
async function applyMigrations(databaseUrl) {
await runner({
databaseUrl,
dir: join(__dirname, "migrations"),
direction: "up",
ignorePattern: "(config|template)\\.cjs$",
});
}
Loading

0 comments on commit 5c297c0

Please sign in to comment.