Skip to content

Commit

Permalink
test: allow running e2e tests with different DBs
Browse files Browse the repository at this point in the history
This commits adds infrastructure for running the E2E tests
with databases other than sqlite.

Initially, support for Postgres is added.

Signed-off-by: David Mehren <[email protected]>
  • Loading branch information
davidmehren committed Mar 6, 2022
1 parent 35075bd commit f0e6f61
Show file tree
Hide file tree
Showing 3 changed files with 232 additions and 8 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
"passport": "0.5.2",
"passport-http-bearer": "1.0.1",
"passport-local": "1.0.0",
"pg": "^8.7.3",
"raw-body": "2.5.1",
"reflect-metadata": "0.1.13",
"rimraf": "3.0.2",
Expand All @@ -73,6 +74,7 @@
"@types/jest": "27.4.1",
"@types/node": "16.11.26",
"@types/passport-local": "1.0.34",
"@types/pg": "^8",
"@types/source-map-support": "0.5.4",
"@types/supertest": "2.0.11",
"@typescript-eslint/eslint-plugin": "5.13.0",
Expand Down
102 changes: 94 additions & 8 deletions test/test-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import { ConfigModule, ConfigService } from '@nestjs/config';
import { NestExpressApplication } from '@nestjs/platform-express';
import { Test, TestingModule, TestingModuleBuilder } from '@nestjs/testing';
import { TypeOrmModule } from '@nestjs/typeorm';
import { TypeOrmModule, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { RouterModule, Routes } from 'nest-router';
import { Connection, createConnection } from 'typeorm';

import { PrivateApiModule } from '../src/api/private/private-api.module';
import { PublicApiModule } from '../src/api/public/public-api.module';
Expand All @@ -32,6 +33,7 @@ import { HistoryModule } from '../src/history/history.module';
import { HistoryService } from '../src/history/history.service';
import { IdentityModule } from '../src/identity/identity.module';
import { IdentityService } from '../src/identity/identity.service';
import { ConsoleLoggerService } from '../src/logger/console-logger.service';
import { LoggerModule } from '../src/logger/logger.module';
import { MediaModule } from '../src/media/media.module';
import { MediaService } from '../src/media/media.service';
Expand All @@ -46,6 +48,7 @@ import { User } from '../src/users/user.entity';
import { UsersModule } from '../src/users/users.module';
import { UsersService } from '../src/users/users.service';
import { setupSessionMiddleware } from '../src/utils/session';
import { setupValidationPipe } from '../src/utils/setup-pipes';

export class TestSetup {
moduleRef: TestingModule;
Expand All @@ -65,6 +68,36 @@ export class TestSetup {
authTokens: AuthTokenWithSecretDto[] = [];
anonymousNotes: Note[] = [];
ownedNotes: Note[] = [];

/**
* Cleans up remnants from a test run from the database
*/
public async cleanup() {
const appConnection = this.app.get<Connection>(Connection);
const connectionOptions = appConnection.options;
if (!connectionOptions.database) {
throw new Error('Database name not set in connection options');
}
if (connectionOptions.type === 'sqlite') {
// Bail out early, as SQLite runs from memory anyway
return;
}
if (appConnection.isConnected) {
await appConnection.close();
}
switch (connectionOptions.type) {
case 'postgres': {
const connection = await createConnection({
type: 'postgres',
username: 'hedgedoc',
password: 'hedgedoc',
database: 'postgres',
});
await connection.query(`DROP DATABASE ${connectionOptions.database}`);
await connection.close();
}
}
}
}

/**
Expand All @@ -80,11 +113,66 @@ export class TestSetupBuilder {
private testingModuleBuilder: TestingModuleBuilder;
private testSetup = new TestSetup();

private testId: string;

/**
* Prepares a test database
* @param dbName The name of the database to use
* @private
*/
private static async setupTestDB(dbName: string) {
switch (process.env.HEDGEDOC_TEST_DB_TYPE || 'sqlite') {
case 'sqlite':
return;
case 'postgres': {
// Create a connection to internal postgres database to then create a test db
const connection = await createConnection({
type: 'postgres',
username: 'hedgedoc',
password: 'hedgedoc',
database: 'postgres',
});
await connection.query(`CREATE DATABASE ${dbName}`);
await connection.close();
return;
}
default:
throw new Error('Unknown database type in HEDGEDOC_TEST_DB_TYPE');
}
}

private static getTestDBConf(dbName: string): TypeOrmModuleOptions {
switch (process.env.HEDGEDOC_TEST_DB_TYPE || 'sqlite') {
case 'sqlite':
return {
type: 'sqlite',
database: ':memory:',
autoLoadEntities: true,
synchronize: true,
dropSchema: true,
};
case 'postgres':
return {
type: 'postgres',
database: dbName,
username: 'hedgedoc',
password: 'hedgedoc',
autoLoadEntities: true,
synchronize: true,
dropSchema: true,
};
default:
throw new Error('Unknown database type in HEDGEDOC_TEST_DB_TYPE');
}
}

/**
* Creates a new instance of TestSetupBuilder
*/
public static create(): TestSetupBuilder {
const testSetupBuilder = new TestSetupBuilder();
testSetupBuilder.testId =
'hedgedoc_test_' + Math.random().toString(36).substring(2, 15);
const routes: Routes = [
{
path: '/api/v2',
Expand All @@ -98,13 +186,9 @@ export class TestSetupBuilder {
testSetupBuilder.testingModuleBuilder = Test.createTestingModule({
imports: [
RouterModule.forRoutes(routes),
TypeOrmModule.forRoot({
type: 'sqlite',
database: ':memory:',
autoLoadEntities: true,
synchronize: true,
dropSchema: true,
}),
TypeOrmModule.forRoot(
TestSetupBuilder.getTestDBConf(testSetupBuilder.testId),
),
ConfigModule.forRoot({
isGlobal: true,
load: [
Expand Down Expand Up @@ -146,6 +230,8 @@ export class TestSetupBuilder {
* Builds the final TestSetup from the configured builder
*/
public async build(): Promise<TestSetup> {
await TestSetupBuilder.setupTestDB(this.testId);

for (const setupFunction of this.setupPreCompile) {
await setupFunction();
}
Expand Down
136 changes: 136 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1796,6 +1796,17 @@ __metadata:
languageName: node
linkType: hard

"@types/pg@npm:^8":
version: 8.6.4
resolution: "@types/pg@npm:8.6.4"
dependencies:
"@types/node": "*"
pg-protocol: "*"
pg-types: ^2.2.0
checksum: cebc40d6f034ff5651a8415e38aeacf86925d6a7eebfd3d20a7db9e7935b0a376a81ecdfffcbeb54425344ecc9a5a8886955bcbb3501226521209900d7a57aef
languageName: node
linkType: hard

"@types/prettier@npm:^2.1.5":
version: 2.4.4
resolution: "@types/prettier@npm:2.4.4"
Expand Down Expand Up @@ -3022,6 +3033,13 @@ __metadata:
languageName: node
linkType: hard

"buffer-writer@npm:2.0.0":
version: 2.0.0
resolution: "buffer-writer@npm:2.0.0"
checksum: 11736b48bb75106c52ca8ec9f025e7c1b3b25ce31875f469d7210eabd5c576c329e34f6b805d4a8d605ff3f0db1e16342328802c4c963e9c826b0e43a4e631c2
languageName: node
linkType: hard

"buffer-xor@npm:^1.0.3":
version: 1.0.3
resolution: "buffer-xor@npm:1.0.3"
Expand Down Expand Up @@ -5361,6 +5379,7 @@ __metadata:
"@types/node-fetch": 2.6.1
"@types/passport-http-bearer": 1.0.37
"@types/passport-local": 1.0.34
"@types/pg": ^8
"@types/source-map-support": 0.5.4
"@types/supertest": 2.0.11
"@typescript-eslint/eslint-plugin": 5.13.0
Expand Down Expand Up @@ -5389,6 +5408,7 @@ __metadata:
passport: 0.5.2
passport-http-bearer: 1.0.1
passport-local: 1.0.0
pg: ^8.7.3
prettier: 2.5.1
raw-body: 2.5.1
reflect-metadata: 0.1.13
Expand Down Expand Up @@ -7918,6 +7938,13 @@ __metadata:
languageName: node
linkType: hard

"packet-reader@npm:1.0.0":
version: 1.0.0
resolution: "packet-reader@npm:1.0.0"
checksum: 0b7516f0cbf3e322aad591bed29ba544220088c53943145c0d9121a6f59182ad811f7fd6785a8979a34356aca69d97653689029964c5998dc02645633d88ffd7
languageName: node
linkType: hard

"parent-module@npm:^1.0.0":
version: 1.0.1
resolution: "parent-module@npm:1.0.1"
Expand Down Expand Up @@ -8107,6 +8134,78 @@ __metadata:
languageName: node
linkType: hard

"pg-connection-string@npm:^2.5.0":
version: 2.5.0
resolution: "pg-connection-string@npm:2.5.0"
checksum: a6f3a068f7c9416a5b33a326811caf0dfaaee045c225b7c628b4c9b4e9a2b25bdd12a21e4c48940e1000ea223a4e608ca122d2ff3dd08c8b1db0fc9f5705133a
languageName: node
linkType: hard

"pg-int8@npm:1.0.1":
version: 1.0.1
resolution: "pg-int8@npm:1.0.1"
checksum: a1e3a05a69005ddb73e5f324b6b4e689868a447c5fa280b44cd4d04e6916a344ac289e0b8d2695d66e8e89a7fba023affb9e0e94778770ada5df43f003d664c9
languageName: node
linkType: hard

"pg-pool@npm:^3.5.1":
version: 3.5.1
resolution: "pg-pool@npm:3.5.1"
peerDependencies:
pg: ">=8.0"
checksum: 42833c25f18fee41a1b2d955978f1403e93164762a7e57d3a870429103d302f1899b393ab021bb8144272037eb3f13bdb9f16a4c4afaa3efd3d2c3689738038f
languageName: node
linkType: hard

"pg-protocol@npm:*, pg-protocol@npm:^1.5.0":
version: 1.5.0
resolution: "pg-protocol@npm:1.5.0"
checksum: b839d12cafe942ef9cbc5b13c174eb2356804fb4fe8ead8279f46a36be90722d19a91409955beb8a3d5301639c44854e49749de4aef02dc361fee3e2a61fb1e4
languageName: node
linkType: hard

"pg-types@npm:^2.1.0, pg-types@npm:^2.2.0":
version: 2.2.0
resolution: "pg-types@npm:2.2.0"
dependencies:
pg-int8: 1.0.1
postgres-array: ~2.0.0
postgres-bytea: ~1.0.0
postgres-date: ~1.0.4
postgres-interval: ^1.1.0
checksum: bf4ec3f594743442857fb3a8dfe5d2478a04c98f96a0a47365014557cbc0b4b0cee01462c79adca863b93befbf88f876299b75b72c665b5fb84a2c94fbd10316
languageName: node
linkType: hard

"pg@npm:^8.7.3":
version: 8.7.3
resolution: "pg@npm:8.7.3"
dependencies:
buffer-writer: 2.0.0
packet-reader: 1.0.0
pg-connection-string: ^2.5.0
pg-pool: ^3.5.1
pg-protocol: ^1.5.0
pg-types: ^2.1.0
pgpass: 1.x
peerDependencies:
pg-native: ">=2.0.0"
peerDependenciesMeta:
pg-native:
optional: true
checksum: d0e7040967779b9ccea16897f099510bcaf6bc86f77a6d8fa7e293c24d8bd2fd2ec46d99d6d1adc9be4cc8f254aa909361346b693088c1ba4501414f7afb2fe3
languageName: node
linkType: hard

"pgpass@npm:1.x":
version: 1.0.5
resolution: "pgpass@npm:1.0.5"
dependencies:
split2: ^4.1.0
checksum: 947ac096c031eebdf08d989de2e9f6f156b8133d6858c7c2c06c041e1e71dda6f5f3bad3c0ec1e96a09497bbc6ef89e762eefe703b5ef9cb2804392ec52ec400
languageName: node
linkType: hard

"picocolors@npm:^1.0.0":
version: 1.0.0
resolution: "picocolors@npm:1.0.0"
Expand Down Expand Up @@ -8144,6 +8243,36 @@ __metadata:
languageName: node
linkType: hard

"postgres-array@npm:~2.0.0":
version: 2.0.0
resolution: "postgres-array@npm:2.0.0"
checksum: 0e1e659888147c5de579d229a2d95c0d83ebdbffc2b9396d890a123557708c3b758a0a97ed305ce7f58edfa961fa9f0bbcd1ea9f08b6e5df73322e683883c464
languageName: node
linkType: hard

"postgres-bytea@npm:~1.0.0":
version: 1.0.0
resolution: "postgres-bytea@npm:1.0.0"
checksum: d844ae4ca7a941b70e45cac1261a73ee8ed39d72d3d74ab1d645248185a1b7f0ac91a3c63d6159441020f4e1f7fe64689ac56536a307b31cef361e5187335090
languageName: node
linkType: hard

"postgres-date@npm:~1.0.4":
version: 1.0.7
resolution: "postgres-date@npm:1.0.7"
checksum: 5745001d47e51cd767e46bcb1710649cd705d91a24d42fa661c454b6dcbb7353c066a5047983c90a626cd3bbfea9e626cc6fa84a35ec57e5bbb28b49f78e13ed
languageName: node
linkType: hard

"postgres-interval@npm:^1.1.0":
version: 1.2.0
resolution: "postgres-interval@npm:1.2.0"
dependencies:
xtend: ^4.0.0
checksum: 746b71f93805ae33b03528e429dc624706d1f9b20ee81bf743263efb6a0cd79ae02a642a8a480dbc0f09547b4315ab7df6ce5ec0be77ed700bac42730f5c76b2
languageName: node
linkType: hard

"prelude-ls@npm:^1.2.1":
version: 1.2.1
resolution: "prelude-ls@npm:1.2.1"
Expand Down Expand Up @@ -8972,6 +9101,13 @@ __metadata:
languageName: node
linkType: hard

"split2@npm:^4.1.0":
version: 4.1.0
resolution: "split2@npm:4.1.0"
checksum: ec581597cb74c13cdfb5e2047543dd40cb1e8e9803c7b1e0c29ede05f2b4f049b2d6e7f2788a225d544549375719658b8f38e9366364dec35dc7a12edfda5ee5
languageName: node
linkType: hard

"sprintf-js@npm:~1.0.2":
version: 1.0.3
resolution: "sprintf-js@npm:1.0.3"
Expand Down

0 comments on commit f0e6f61

Please sign in to comment.