Skip to content

Commit

Permalink
Merge pull request #2 from nhandt2021/nhandt/tutorial
Browse files Browse the repository at this point in the history
Add e2e testing user APIs
  • Loading branch information
nhandt2021 authored Aug 14, 2022
2 parents 8b70733 + b0daadf commit a6e3aaa
Show file tree
Hide file tree
Showing 12 changed files with 212 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .env.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DATABASE_URL="postgresql://postgres:123@localhost:5435/nest?schema=public"
JWT_SECRET='super-secret'
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"db:dev:rm": "docker compose rm dev-db -s -f -v",
"db:dev:up": "docker compose up dev-db -d",
"db:dev:restart": "yarn db:dev:rm && yarn db:dev:up && sleep 1 && yarn prisma:dev:deploy",
"prisma:test:deploy": "prisma migrate deploy",
"prisma:test:deploy": "dotenv -e .env.test -- prisma migrate deploy",
"db:test:rm": "docker compose rm test-db -s -f -v",
"db:test:up": "docker compose up test-db -d",
"db:test:restart": "yarn db:test:rm && yarn db:test:up && sleep 1 && yarn prisma:test:deploy",
Expand All @@ -26,7 +26,8 @@
"test:watch": "jest --watch",
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --watch --no-cache --config ./test/jest-e2e.json"
"pretest:e2e": "yarn db:test:restart",
"test:e2e": "dotenv -e .env.test -- jest --watch --no-cache --config ./test/jest-e2e.json"
},
"dependencies": {
"@nestjs/common": "^9.0.0",
Expand Down
4 changes: 4 additions & 0 deletions src/bookmark/bookmark.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Controller } from '@nestjs/common';

@Controller('bookmark')
export class BookmarkController {}
7 changes: 6 additions & 1 deletion src/bookmark/bookmark.module.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Module } from '@nestjs/common';
import { BookmarkController } from './bookmark.controller';
import { BookmarkService } from './bookmark.service';

@Module({})
@Module({
controllers: [BookmarkController],
providers: [BookmarkService]
})
export class BookmarkModule {}
4 changes: 4 additions & 0 deletions src/bookmark/bookmark.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import { Injectable } from '@nestjs/common';

@Injectable()
export class BookmarkService {}
8 changes: 8 additions & 0 deletions src/prisma/prisma.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,12 @@ export class PrismaService extends PrismaClient {
},
});
}

// Make sure the deletion cascade
cleanDb() {
return this.$transaction([
this.user.deleteMany(),
this.bookmark.deleteMany(),
]);
}
}
15 changes: 15 additions & 0 deletions src/user/dto/edit-user.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IsEmail, IsOptional, IsString } from 'class-validator';

export class EditUserDto {
@IsEmail()
@IsOptional()
email?: string;

@IsString()
@IsOptional()
firstName?: string;

@IsString()
@IsOptional()
lastName?: string;
}
1 change: 1 addition & 0 deletions src/user/dto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './edit-user.dto';
11 changes: 8 additions & 3 deletions src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { Controller, Get, Patch, UseGuards } from '@nestjs/common';
import { Body, Controller, Get, Patch, UseGuards } from '@nestjs/common';
import { User } from '@prisma/client';
import { JwtGuard } from '../auth/guard';
import { GetUser } from '../auth/decorator';
import { EditUserDto } from './dto';
import { UserService } from './user.service';

@UseGuards(JwtGuard)
@Controller('users')
export class UserController {
constructor(private userService: UserService) {}

@Get('me')
getMe(@GetUser() user: User) {
console.log('req gi day:', user);
return user;
}

@Patch()
editUser() {}
editUser(@GetUser('id') userId: number, @Body() dto: EditUserDto) {
return this.userService.editUser(userId, dto);
}
}
2 changes: 2 additions & 0 deletions src/user/user.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { Module } from '@nestjs/common';
import { UserController } from './user.controller';
import { UserService } from './user.service';

@Module({
controllers: [UserController],
providers: [UserService],
})
export class UserModule {}
23 changes: 23 additions & 0 deletions src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { EditUserDto } from './dto';

@Injectable()
export class UserService {
constructor(private prisma: PrismaService) {}

async editUser(userId: number, dto: EditUserDto) {
const user = await this.prisma.user.update({
where: {
id: userId,
},
data: {
...dto,
},
});

delete user.hash;

return user;
}
}
138 changes: 136 additions & 2 deletions test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as pactum from 'pactum';
import { AppModule } from '../src/app.module';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { PrismaService } from '../src/prisma/prisma.service';
import { AuthDto } from '../src/auth/dto';
import { EditUserDto } from '../src/user/dto';

describe('App (e2e)', () => {
let app: INestApplication;
let prisma: PrismaService;
const HOST = 'http://localhost:3333';

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
Expand All @@ -17,11 +23,139 @@ describe('App (e2e)', () => {
}),
);
await app.init();
await app.listen(3333);

prisma = app.get(PrismaService);

// Clean db before testing
await prisma.cleanDb();

pactum.request.setBaseUrl(HOST);
});

afterAll(() => {
app.close();
});

it.todo('should pass');
describe('Auth', () => {
const dto: AuthDto = {
email: '[email protected]',
password: '123',
};

describe('Signup', () => {
it('should throw if email is empty', () => {
return pactum
.spec()
.post('/auth/signup')
.withBody({
password: dto.password,
})
.expectStatus(400);
});

it('should throw if password is empty', () => {
return pactum
.spec()
.post('/auth/signup')
.withBody({
password: dto.password,
})
.expectStatus(400);
});

it('should throw if no body provided', () => {
return pactum.spec().post('/auth/signup').expectStatus(400);
});

it('should signup', () => {
return pactum
.spec()
.post('/auth/signup')
.withBody(dto)
.expectStatus(201);
});
});

describe('Signin', () => {
it('should throw if email is empty', () => {
return pactum
.spec()
.post('/auth/signin')
.withBody({
password: dto.password,
})
.expectStatus(400);
});

it('should throw if password is empty', () => {
return pactum
.spec()
.post('/auth/signin')
.withBody({
password: dto.password,
})
.expectStatus(400);
});

it('should throw if no body provided', () => {
return pactum.spec().post('/auth/signin').expectStatus(400);
});

it('should signin', () => {
return pactum
.spec()
.post('/auth/signin')
.withBody(dto)
.expectStatus(200)
.stores('userAt', 'access_token');
});
});
});

describe('User', () => {
describe('Get me', () => {
it('should get current user', () => {
return pactum
.spec()
.get('/users/me')
.withHeaders({
Authorization: 'Bearer $S{userAt}',
})
.expectStatus(200);
});
});

describe('Edit user', () => {
const dto: EditUserDto = {
firstName: 'Nhan',
email: '[email protected]',
};

it('should edit user', () => {
return pactum
.spec()
.patch('/users')
.withHeaders({
Authorization: 'Bearer $S{userAt}',
})
.withBody(dto)
.expectStatus(200)
.expectBodyContains(dto.firstName)
.expectBodyContains(dto.email);
});
});
});

describe('Bookmark', () => {
describe('Create bookmark', () => {});

describe('Get bookmark', () => {});

describe('Get bookmark by id', () => {});

describe('Edit bookmark by id', () => {});

describe('Delete bookmark by id', () => {});
});
});

0 comments on commit a6e3aaa

Please sign in to comment.