Skip to content

Commit

Permalink
Setup Test Database (#31)
Browse files Browse the repository at this point in the history
* Hardcode bun version for github action

* Bun scripting seems to work, start fleshing out compose file for the test postgres instance

* Set up of postgres instance for testingi runnning on docker complete with its tear up and tear down

* Start working on base server test

* Add Github Action for running tests

* Ensure to run test script

* Fix initial error with tests starting much faster than postgres initialization

* Get tests to pass by breaking cyclic dependancy on createApplicationServer

* Purge unused dependencies from index.ts

* Fix workflows

* Setup deliberately failing test

* Use exit code on running tests to fail github action on failed tests

* Remove failing test as assertions on failed tests correctly failing action
  • Loading branch information
nigelnindodev authored Mar 12, 2024
1 parent 1be3449 commit 40ee068
Show file tree
Hide file tree
Showing 12 changed files with 102 additions and 23 deletions.
8 changes: 8 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
APPLICATION_PORT=3000
BASE_URL="http://localhost:3000"
JWT_SECRET="jwt_secret"
POSTGRES_USER="testing_user"
POSTGRES_PASSWORD="testing_password"
POSTGRES_HOST="localhost"
POSTGRES_PORT="5000"
POSTGRES_DATABASE_NAME="testing_db"
4 changes: 2 additions & 2 deletions .github/workflows/tsc.yml → .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ on:
branches: [ "master" ]

jobs:
tsc:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
with:
bun-version: latest
bun-version: 1.0.30
- name: bun install
run: bun install
20 changes: 20 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run Server Tests

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1
with:
bun-version: 1.0.30
- name: bun install
run: bun install
- name: bun run test_script
run: bun run test_script.ts
2 changes: 2 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[test]
coverage = true # always enable coverage
9 changes: 9 additions & 0 deletions compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
services:
postgres:
image: "postgres:14-alpine"
ports:
- "5000:5432"
environment:
- POSTGRES_DB=testing_db
- POSTGRES_USER=testing_user
- POSTGRES_PASSWORD=testing_password
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
"name": "elysia",
"version": "1.0.50",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"test": "source .env.test && bun test",
"dev": "bun run --watch src/index.ts",
"test-server": "source .env.test && bun run --watch src/index.ts",
"build": "tsc"
},
"dependencies": {
Expand Down
21 changes: 3 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import "reflect-metadata"; // required for TypeORM

import { PostgresDataSourceSingleton } from "./postgres";
import { createApplicationServer } from "./server";
import { ILogObj, Logger } from "tslog";
import { startServer } from "./start_server";

/**
* Application configuration object.
Expand All @@ -20,7 +19,7 @@ export interface Config {
}

/**
* Helper function that fetches reads applicaion config values and returns it as a `Config`
* Helper function that fetches reads application config values and returns it as a `Config`
* object.
*/
export function getConfig(): Config {
Expand All @@ -44,18 +43,4 @@ export const logger: Logger<ILogObj> = new Logger({
// Bun automatically masks sensitive password fields
logger.info("App Configuration", getConfig());

/**
* Initialize Postgres database connector, to be passed on to the application server creator.
*/
const dataSource = await PostgresDataSourceSingleton.getInstance();

/**
* Create the application server, passing in the TypeORM data source.
*/
const app = createApplicationServer(dataSource);

app.listen(getConfig().applicationPort);

logger.info(
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port} with NODE_ENV ${process.env.NODE_ENV}`,
);
startServer();
2 changes: 2 additions & 0 deletions src/postgres/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class PostgresDataSourceSingleton {

public static async getInstance(): Promise<DataSource> {
logger.info("Fetching postgres datasource instance");
logger.trace("Config", config);
if (!PostgresDataSourceSingleton.dataSource) {
const dataSource = new DataSource({
type: "postgres",
Expand Down Expand Up @@ -37,6 +38,7 @@ export class PostgresDataSourceSingleton {

const result = await dataSource.initialize();
if (result.isInitialized) {
logger.trace("Postgres dataSource successfully initialized");
PostgresDataSourceSingleton.dataSource = result;
return PostgresDataSourceSingleton.dataSource;
} else {
Expand Down
2 changes: 0 additions & 2 deletions src/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import "reflect-metadata"; // required for TypeORM

import { DataSource } from "typeorm";
import { Elysia } from "elysia";
import { cookie } from "@elysiajs/cookie";
Expand Down
13 changes: 13 additions & 0 deletions src/start_server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { logger } from ".";
import { PostgresDataSourceSingleton } from "./postgres";
import { createApplicationServer } from "./server";

export const startServer = async () => {
const dataSource = await PostgresDataSourceSingleton.getInstance();

const app = createApplicationServer(dataSource);

logger.info(
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port} with NODE_ENV ${process.env.NODE_ENV}`,
);
};
19 changes: 19 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import "reflect-metadata"; // required for TypeORM

import { describe, expect, it } from "bun:test";

import { createApplicationServer } from "../src/server.ts";
import { PostgresDataSourceSingleton } from "../src/postgres/index.ts";

describe("Server Testing", async () => {
console.log("NODE_ENV: ", process.env.NODE_ENV);
const dataSource = await PostgresDataSourceSingleton.getInstance();
console.log("Fetched postgres datasource");
const app = createApplicationServer(dataSource);
it("Correcly loads up the test server", async () => {
const response = await app
.handle(new Request("http://localhost:3000"))
.then((res) => res.status);
expect(response).toBe(200);
});
});
22 changes: 22 additions & 0 deletions test_script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { $ } from "bun";
import { setTimeout } from "timers/promises";

// Use docker compose to set up a postgres database as specified in compose.yaml
await $`docker compose up -d`;

// We might be running tests much faster than when our postgres container is ready to handle
// them. Set up a 5 second delay before starting testing.
await setTimeout(5000);

// Run tests
const testResult = await $`bun run test`;
if (testResult.exitCode !== 0) {
console.error(
"An error occured while running bun tests",
testResult.stderr.toString(),
);
throw new Error(testResult.stderr.toString());
}

// Destroy the postgres instance and ensure any created volumes are removed as well
await $`docker compose down --volumes`;

0 comments on commit 40ee068

Please sign in to comment.