add e2e with docker-compose support
This commit is contained in:
41
test/global-setup.ts
Normal file
41
test/global-setup.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { exec } from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { DockerComposeEnvironment, Wait } from 'testcontainers';
|
||||
|
||||
export default async () => {
|
||||
const composeFilePath = path.resolve(__dirname, '../environment/e2e');
|
||||
|
||||
const environment = await new DockerComposeEnvironment(
|
||||
composeFilePath,
|
||||
'docker-compose.yaml',
|
||||
)
|
||||
.withWaitStrategy('postgres_1', Wait.forHealthCheck())
|
||||
.up();
|
||||
|
||||
// Store the environment details for teardown
|
||||
(global as any).__TESTCONTAINERS_ENVIRONMENT__ = environment;
|
||||
|
||||
// Run migrations
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
console.info("running migration")
|
||||
exec(
|
||||
'env && npm run migration:run',
|
||||
{ env: { ...process.env, ...readEnvFile() } },
|
||||
(err, stdout, stderr) => {
|
||||
if (err) {
|
||||
console.error(stderr);
|
||||
return reject(err);
|
||||
}
|
||||
console.log(stdout);
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
function readEnvFile() {
|
||||
const fs = require('fs');
|
||||
const dotenv = require('dotenv');
|
||||
const envConfig = dotenv.parse(fs.readFileSync('.env.e2e'));
|
||||
return envConfig;
|
||||
}
|
||||
10
test/global-teardown.ts
Normal file
10
test/global-teardown.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { DockerComposeEnvironment } from 'testcontainers';
|
||||
|
||||
export default async () => {
|
||||
const environment: DockerComposeEnvironment = (global as any)
|
||||
.__TESTCONTAINERS_ENVIRONMENT__;
|
||||
|
||||
if (environment) {
|
||||
await environment.down();
|
||||
}
|
||||
};
|
||||
@@ -5,5 +5,7 @@
|
||||
"testRegex": ".e2e-spec.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
}
|
||||
},
|
||||
"globalSetup": "<rootDir>/global-setup.ts",
|
||||
"globalTeardown": "<rootDir>/global-teardown.ts"
|
||||
}
|
||||
|
||||
133
test/user.e2e-spec.ts
Normal file
133
test/user.e2e-spec.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { INestApplication, ValidationPipe } from '@nestjs/common';
|
||||
import request from 'supertest';
|
||||
import { AppModule } from '../src/app.module';
|
||||
import { CreateUserDto } from '../src/user/dto/create-user.dto';
|
||||
import { Role } from '../src/auth/role.enum';
|
||||
import { UserService } from '../src/user/user.service';
|
||||
import { User } from '../src/entity/user';
|
||||
import { UpdateUserDto } from '../src/user/dto/update-user.dto';
|
||||
import * as dotenv from 'dotenv';
|
||||
|
||||
dotenv.config({ path: '.env.e2e' });
|
||||
|
||||
describe('UserController (e2e)', () => {
|
||||
let app: INestApplication;
|
||||
let jwtToken: string;
|
||||
let adminUserId: number;
|
||||
|
||||
beforeAll(async () => {
|
||||
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||
imports: [AppModule],
|
||||
}).compile();
|
||||
|
||||
app = moduleFixture.createNestApplication();
|
||||
app.useGlobalPipes(new ValidationPipe());
|
||||
await app.init();
|
||||
|
||||
const userService = moduleFixture.get<UserService>(UserService);
|
||||
const adminUser = await userService.create({
|
||||
username: 'e2e_admin',
|
||||
password: 'password',
|
||||
roles: [Role.Admin],
|
||||
});
|
||||
adminUserId = adminUser.id;
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/auth/login')
|
||||
.send({ username: 'e2e_admin', password: 'password' });
|
||||
|
||||
jwtToken = response.body.access_token;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
const userService = app.get<UserService>(UserService);
|
||||
await userService.remove(adminUserId);
|
||||
await app.close();
|
||||
});
|
||||
|
||||
describe('/users', () => {
|
||||
it('(GET) should get all users', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.get('/users')
|
||||
.set('Authorization', `Bearer ${jwtToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(Array.isArray(response.body)).toBe(true);
|
||||
});
|
||||
|
||||
it('(POST) should create a user', async () => {
|
||||
const createUserDto: CreateUserDto = {
|
||||
username: 'e2e_user',
|
||||
password: 'password',
|
||||
roles: [Role.User],
|
||||
};
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.post('/users')
|
||||
.set('Authorization', `Bearer ${jwtToken}`)
|
||||
.send(createUserDto);
|
||||
|
||||
expect(response.status).toBe(201);
|
||||
expect(response.body.username).toEqual(createUserDto.username);
|
||||
|
||||
const userService = app.get<UserService>(UserService);
|
||||
await userService.remove(response.body.id);
|
||||
});
|
||||
});
|
||||
|
||||
describe('/users/:id', () => {
|
||||
let user: User;
|
||||
let userService: UserService;
|
||||
|
||||
beforeEach(async () => {
|
||||
userService = app.get<UserService>(UserService);
|
||||
user = await userService.create({
|
||||
username: 'e2e_test_user',
|
||||
password: 'password',
|
||||
roles: [Role.User],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
const userExists = await userService.findOne(user.id);
|
||||
if (userExists) {
|
||||
await userService.remove(user.id);
|
||||
}
|
||||
});
|
||||
|
||||
it('(GET) should get a user by id', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.get(`/users/${user.id}`)
|
||||
.set('Authorization', `Bearer ${jwtToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.id).toEqual(user.id);
|
||||
});
|
||||
|
||||
it('(PATCH) should update a user', async () => {
|
||||
const updateUserDto: UpdateUserDto = {
|
||||
username: 'e2e_updated_user',
|
||||
};
|
||||
|
||||
const response = await request(app.getHttpServer())
|
||||
.patch(`/users/${user.id}`)
|
||||
.set('Authorization', `Bearer ${jwtToken}`)
|
||||
.send(updateUserDto);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.body.username).toEqual(updateUserDto.username);
|
||||
});
|
||||
|
||||
it('(DELETE) should delete a user', async () => {
|
||||
const response = await request(app.getHttpServer())
|
||||
.delete(`/users/${user.id}`)
|
||||
.set('Authorization', `Bearer ${jwtToken}`);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
const deletedUser = await userService.findOne(user.id);
|
||||
expect(deletedUser).toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user