mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-04-14 21:23:18 +00:00
feat(test-setup): restructure to synchronous builder
The previous pattern used async methods for the builder pattern, which were hideous to use when chained multiple times. This extracts the builder into a separate class and uses normal functions in the builder. These queue async functions in arrays, which are executed at the correct time, when the new async `build` function is called. Signed-off-by: David Mehren <git@herrmehren.de>
This commit is contained in:
parent
8f1aeab934
commit
d1dbd1bb22
13 changed files with 156 additions and 84 deletions
|
@ -9,7 +9,7 @@ import request from 'supertest';
|
|||
import { AliasCreateDto } from '../../src/notes/alias-create.dto';
|
||||
import { AliasUpdateDto } from '../../src/notes/alias-update.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Alias', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -22,7 +22,7 @@ describe('Alias', () => {
|
|||
let agent2: request.SuperAgentTest;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await (await TestSetup.create()).withUsers();
|
||||
testSetup = await TestSetupBuilder.create().withUsers().build();
|
||||
await testSetup.app.init();
|
||||
|
||||
forbiddenNoteId =
|
||||
|
|
|
@ -17,7 +17,7 @@ import { UpdatePasswordDto } from '../../src/identity/local/update-password.dto'
|
|||
import { UserRelationEnum } from '../../src/users/user-relation.enum';
|
||||
import { checkPassword } from '../../src/utils/password';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Auth', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -27,7 +27,7 @@ describe('Auth', () => {
|
|||
let password: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
const authConfig = testSetup.configService.get('authConfig') as AuthConfig;
|
||||
setupSessionMiddleware(testSetup.app, authConfig);
|
||||
|
|
|
@ -16,7 +16,7 @@ import { NotesService } from '../../src/notes/notes.service';
|
|||
import { User } from '../../src/users/user.entity';
|
||||
import { UsersService } from '../../src/users/users.service';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('History', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -30,7 +30,7 @@ describe('History', () => {
|
|||
let agent: request.SuperAgentTest;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
forbiddenNoteId =
|
||||
testSetup.configService.get('appConfig').forbiddenNoteIds[0];
|
||||
|
|
|
@ -12,7 +12,7 @@ import { Note } from '../../src/notes/note.entity';
|
|||
import { UserInfoDto } from '../../src/users/user-info.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Me', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -26,7 +26,7 @@ describe('Me', () => {
|
|||
let agent: request.SuperAgentTest;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
uploadPath =
|
||||
testSetup.configService.get('mediaConfig').backend.filesystem.uploadPath;
|
||||
|
|
|
@ -11,7 +11,7 @@ import request from 'supertest';
|
|||
import { AuthConfig } from '../../src/config/auth.config';
|
||||
import { ConsoleLoggerService } from '../../src/logger/console-logger.service';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
import { ensureDeleted } from '../utils';
|
||||
|
||||
describe('Media', () => {
|
||||
|
@ -22,7 +22,7 @@ describe('Media', () => {
|
|||
let user: User;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
uploadPath =
|
||||
testSetup.configService.get('mediaConfig').backend.filesystem.uploadPath;
|
||||
|
|
|
@ -11,7 +11,7 @@ import { AuthConfig } from '../../src/config/auth.config';
|
|||
import { NotInDBError } from '../../src/errors/errors';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Notes', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -25,7 +25,7 @@ describe('Notes', () => {
|
|||
let agent: request.SuperAgentTest;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
forbiddenNoteId =
|
||||
testSetup.configService.get('appConfig').forbiddenNoteIds[0];
|
||||
|
|
|
@ -7,7 +7,7 @@ import request from 'supertest';
|
|||
|
||||
import { LoginDto } from '../../src/identity/local/login.dto';
|
||||
import { RegisterDto } from '../../src/identity/local/register.dto';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Register and Login', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -17,7 +17,7 @@ describe('Register and Login', () => {
|
|||
const PASSWORD = 'secure';
|
||||
|
||||
beforeEach(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
await testSetup.app.init();
|
||||
});
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import request from 'supertest';
|
|||
import { AuthConfig } from '../../src/config/auth.config';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { setupSessionMiddleware } from '../../src/utils/session';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Tokens', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -18,7 +18,7 @@ describe('Tokens', () => {
|
|||
let keyId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().build();
|
||||
|
||||
user = await testSetup.userService.createUser('hardcoded', 'Testy');
|
||||
await testSetup.identityService.createLocalIdentity(user, 'test');
|
||||
|
|
|
@ -7,8 +7,7 @@ import request from 'supertest';
|
|||
|
||||
import { AliasCreateDto } from '../../src/notes/alias-create.dto';
|
||||
import { AliasUpdateDto } from '../../src/notes/alias-update.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Alias', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -17,7 +16,7 @@ describe('Alias', () => {
|
|||
let forbiddenNoteId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await (await TestSetup.create(false)).withUsers();
|
||||
testSetup = await TestSetupBuilder.create().withUsers().withNotes().build();
|
||||
forbiddenNoteId =
|
||||
testSetup.configService.get('appConfig').forbiddenNoteIds[0];
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import { HistoryEntryUpdateDto } from '../../src/history/history-entry-update.dt
|
|||
import { HistoryEntryDto } from '../../src/history/history-entry.dto';
|
||||
import { NoteMetadataDto } from '../../src/notes/note-metadata.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
// TODO Tests have to be reworked using UserService functions
|
||||
|
||||
|
@ -22,7 +22,7 @@ describe('Me', () => {
|
|||
let user: User;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().withMockAuth().build();
|
||||
|
||||
uploadPath =
|
||||
testSetup.configService.get('mediaConfig').backend.filesystem.uploadPath;
|
||||
|
|
|
@ -10,7 +10,7 @@ import request from 'supertest';
|
|||
import { ConsoleLoggerService } from '../../src/logger/console-logger.service';
|
||||
import { Note } from '../../src/notes/note.entity';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
import { ensureDeleted } from '../utils';
|
||||
|
||||
describe('Media', () => {
|
||||
|
@ -20,7 +20,7 @@ describe('Media', () => {
|
|||
let user: User;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().withMockAuth().build();
|
||||
|
||||
uploadPath =
|
||||
testSetup.configService.get('mediaConfig').backend.filesystem.uploadPath;
|
||||
|
|
|
@ -10,7 +10,7 @@ import request from 'supertest';
|
|||
import { NotInDBError } from '../../src/errors/errors';
|
||||
import { NotePermissionsUpdateDto } from '../../src/notes/note-permissions.dto';
|
||||
import { User } from '../../src/users/user.entity';
|
||||
import { TestSetup } from '../test-setup';
|
||||
import { TestSetup, TestSetupBuilder } from '../test-setup';
|
||||
|
||||
describe('Notes', () => {
|
||||
let testSetup: TestSetup;
|
||||
|
@ -23,7 +23,7 @@ describe('Notes', () => {
|
|||
let testImage: Buffer;
|
||||
|
||||
beforeAll(async () => {
|
||||
testSetup = await TestSetup.create();
|
||||
testSetup = await TestSetupBuilder.create().withMockAuth().build();
|
||||
|
||||
forbiddenNoteId =
|
||||
testSetup.configService.get('appConfig').forbiddenNoteIds[0];
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*/
|
||||
import { ConfigModule, ConfigService } from '@nestjs/config';
|
||||
import { NestExpressApplication } from '@nestjs/platform-express';
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { Test, TestingModule, TestingModuleBuilder } from '@nestjs/testing';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { RouterModule, Routes } from 'nest-router';
|
||||
|
||||
|
@ -34,6 +34,7 @@ import { MediaModule } from '../src/media/media.module';
|
|||
import { MediaService } from '../src/media/media.service';
|
||||
import { MonitoringModule } from '../src/monitoring/monitoring.module';
|
||||
import { AliasService } from '../src/notes/alias.service';
|
||||
import { Note } from '../src/notes/note.entity';
|
||||
import { NotesModule } from '../src/notes/notes.module';
|
||||
import { NotesService } from '../src/notes/notes.service';
|
||||
import { PermissionsModule } from '../src/permissions/permissions.module';
|
||||
|
@ -58,9 +59,27 @@ export class TestSetup {
|
|||
|
||||
users: User[] = [];
|
||||
authTokens: AuthTokenWithSecretDto[] = [];
|
||||
notes: Note[] = [];
|
||||
}
|
||||
|
||||
public static async create(withMockAuth = true): Promise<TestSetup> {
|
||||
const testSetup = new TestSetup();
|
||||
/**
|
||||
* Builder class for TestSetup
|
||||
* Should be instantiated with the create() method
|
||||
* The useable TestSetup is genereated using build()
|
||||
*/
|
||||
export class TestSetupBuilder {
|
||||
// list of functions that should be executed before or after builing the TestingModule
|
||||
private setupPreCompile: (() => Promise<void>)[] = [];
|
||||
private setupPostCompile: (() => Promise<void>)[] = [];
|
||||
|
||||
private testingModuleBuilder: TestingModuleBuilder;
|
||||
private testSetup = new TestSetup();
|
||||
|
||||
/**
|
||||
* Creates a new instance of TestSetupBuilder
|
||||
*/
|
||||
public static create(): TestSetupBuilder {
|
||||
const testSetupBuilder = new TestSetupBuilder();
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '/api/v2',
|
||||
|
@ -71,8 +90,7 @@ export class TestSetup {
|
|||
module: PrivateApiModule,
|
||||
},
|
||||
];
|
||||
|
||||
const testingModule = Test.createTestingModule({
|
||||
testSetupBuilder.testingModuleBuilder = Test.createTestingModule({
|
||||
imports: [
|
||||
RouterModule.forRoutes(routes),
|
||||
TypeOrmModule.forRoot({
|
||||
|
@ -109,66 +127,121 @@ export class TestSetup {
|
|||
IdentityModule,
|
||||
],
|
||||
});
|
||||
|
||||
if (withMockAuth) {
|
||||
testingModule.overrideGuard(TokenAuthGuard).useClass(MockAuthGuard);
|
||||
}
|
||||
|
||||
testSetup.moduleRef = await testingModule.compile();
|
||||
|
||||
testSetup.userService = testSetup.moduleRef.get<UsersService>(UsersService);
|
||||
testSetup.configService =
|
||||
testSetup.moduleRef.get<ConfigService>(ConfigService);
|
||||
testSetup.identityService =
|
||||
testSetup.moduleRef.get<IdentityService>(IdentityService);
|
||||
testSetup.notesService =
|
||||
testSetup.moduleRef.get<NotesService>(NotesService);
|
||||
testSetup.mediaService =
|
||||
testSetup.moduleRef.get<MediaService>(MediaService);
|
||||
testSetup.historyService =
|
||||
testSetup.moduleRef.get<HistoryService>(HistoryService);
|
||||
testSetup.aliasService =
|
||||
testSetup.moduleRef.get<AliasService>(AliasService);
|
||||
testSetup.authService = testSetup.moduleRef.get<AuthService>(AuthService);
|
||||
|
||||
testSetup.app = testSetup.moduleRef.createNestApplication();
|
||||
|
||||
setupSessionMiddleware(
|
||||
testSetup.app,
|
||||
testSetup.configService.get<AuthConfig>('authConfig'),
|
||||
);
|
||||
|
||||
return testSetup;
|
||||
return testSetupBuilder;
|
||||
}
|
||||
|
||||
public async withUsers(): Promise<TestSetup> {
|
||||
// Create users
|
||||
this.users.push(
|
||||
await this.userService.createUser('testuser1', 'Test User 1'),
|
||||
);
|
||||
this.users.push(
|
||||
await this.userService.createUser('testuser2', 'Test User 2'),
|
||||
);
|
||||
this.users.push(
|
||||
await this.userService.createUser('testuser3', 'Test User 3'),
|
||||
/**
|
||||
* Builds the final TestSetup from the configured builder
|
||||
*/
|
||||
public async build(): Promise<TestSetup> {
|
||||
for (const setupFunction of this.setupPreCompile) {
|
||||
await setupFunction();
|
||||
}
|
||||
|
||||
this.testSetup.moduleRef = await this.testingModuleBuilder.compile();
|
||||
|
||||
this.testSetup.userService =
|
||||
this.testSetup.moduleRef.get<UsersService>(UsersService);
|
||||
this.testSetup.configService =
|
||||
this.testSetup.moduleRef.get<ConfigService>(ConfigService);
|
||||
this.testSetup.identityService =
|
||||
this.testSetup.moduleRef.get<IdentityService>(IdentityService);
|
||||
this.testSetup.notesService =
|
||||
this.testSetup.moduleRef.get<NotesService>(NotesService);
|
||||
this.testSetup.mediaService =
|
||||
this.testSetup.moduleRef.get<MediaService>(MediaService);
|
||||
this.testSetup.historyService =
|
||||
this.testSetup.moduleRef.get<HistoryService>(HistoryService);
|
||||
this.testSetup.aliasService =
|
||||
this.testSetup.moduleRef.get<AliasService>(AliasService);
|
||||
this.testSetup.authService =
|
||||
this.testSetup.moduleRef.get<AuthService>(AuthService);
|
||||
|
||||
this.testSetup.app = this.testSetup.moduleRef.createNestApplication();
|
||||
|
||||
setupSessionMiddleware(
|
||||
this.testSetup.app,
|
||||
this.testSetup.configService.get<AuthConfig>('authConfig'),
|
||||
);
|
||||
|
||||
// Create identities for login
|
||||
await this.identityService.createLocalIdentity(this.users[0], 'testuser1');
|
||||
await this.identityService.createLocalIdentity(this.users[1], 'testuser2');
|
||||
await this.identityService.createLocalIdentity(this.users[2], 'testuser3');
|
||||
for (const setupFunction of this.setupPostCompile) {
|
||||
await setupFunction();
|
||||
}
|
||||
return this.testSetup;
|
||||
}
|
||||
|
||||
// create auth tokens
|
||||
this.authTokens = await Promise.all(
|
||||
this.users.map(async (user) => {
|
||||
return await this.authService.createTokenForUser(
|
||||
user,
|
||||
'test',
|
||||
new Date().getTime() + 60 * 60 * 1000,
|
||||
);
|
||||
}),
|
||||
);
|
||||
/**
|
||||
* Enable mock authentication for the public API
|
||||
*/
|
||||
public withMockAuth() {
|
||||
this.setupPreCompile.push(async () => {
|
||||
this.testingModuleBuilder
|
||||
.overrideGuard(TokenAuthGuard)
|
||||
.useClass(MockAuthGuard);
|
||||
return await Promise.resolve();
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a few users, identities and auth tokens for testing
|
||||
*/
|
||||
public withUsers() {
|
||||
this.setupPostCompile.push(async () => {
|
||||
// Create users
|
||||
this.testSetup.users.push(
|
||||
await this.testSetup.userService.createUser('testuser1', 'Test User 1'),
|
||||
);
|
||||
this.testSetup.users.push(
|
||||
await this.testSetup.userService.createUser('testuser2', 'Test User 2'),
|
||||
);
|
||||
this.testSetup.users.push(
|
||||
await this.testSetup.userService.createUser('testuser3', 'Test User 3'),
|
||||
);
|
||||
|
||||
// Create identities for login
|
||||
await this.testSetup.identityService.createLocalIdentity(
|
||||
this.testSetup.users[0],
|
||||
'testuser1',
|
||||
);
|
||||
await this.testSetup.identityService.createLocalIdentity(
|
||||
this.testSetup.users[1],
|
||||
'testuser2',
|
||||
);
|
||||
await this.testSetup.identityService.createLocalIdentity(
|
||||
this.testSetup.users[2],
|
||||
'testuser3',
|
||||
);
|
||||
|
||||
// create auth tokens
|
||||
this.testSetup.authTokens = await Promise.all(
|
||||
this.testSetup.users.map(async (user) => {
|
||||
return await this.testSetup.authService.createTokenForUser(
|
||||
user,
|
||||
'test',
|
||||
new Date().getTime() + 60 * 60 * 1000,
|
||||
);
|
||||
}),
|
||||
);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a few notes for testing
|
||||
*/
|
||||
public withNotes(): TestSetupBuilder {
|
||||
this.setupPostCompile.push(async () => {
|
||||
this.testSetup.notes.push(
|
||||
await this.testSetup.notesService.createNote('Test Note 1', null),
|
||||
);
|
||||
this.testSetup.notes.push(
|
||||
await this.testSetup.notesService.createNote('Test Note 2', null),
|
||||
);
|
||||
this.testSetup.notes.push(
|
||||
await this.testSetup.notesService.createNote('Test Note 3', null),
|
||||
);
|
||||
});
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue