Skip to content

Commit

Permalink
Merge pull request #3 from henriqueweiand/user-crud
Browse files Browse the repository at this point in the history
added all crud for users
  • Loading branch information
henriqueweiand authored Nov 1, 2023
2 parents dd7f84c + c656573 commit bb3ff80
Show file tree
Hide file tree
Showing 27 changed files with 897 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ class PrismaServiceMock {
user = {
findUnique: jest.fn(),
create: jest.fn(),
findMany: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
};
}

Expand Down Expand Up @@ -34,38 +37,59 @@ describe('PrismaUserRepository', () => {
expect(prismaUserRepository).toBeDefined();
});

it('should call prismaService.findUnique when findOne is called', async () => {
const where: Prisma.UserWhereUniqueInput = {
id: 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf',
};
const user = {
id: 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf',
username: 'John Doe',
password: '123456',
} as User;
prismaService.user.findUnique = jest.fn().mockReturnValueOnce(user);
const result = await prismaUserRepository.findOne(where);
it('should call prismaService.findMany when findMany is called', async () => {
const users = [
{
id: 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf',
username: 'John Doe',
password: '123456',
},
{
id: 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf',
username: 'Jane Doe',
password: '123456',
},
] as User[];
prismaService.user.findMany = jest.fn().mockReturnValueOnce(users);

const result = await prismaUserRepository.findMany();

expect(result).toEqual(user);
expect(prismaService.user.findUnique).toHaveBeenCalledWith({ where });
expect(result).toEqual(users);
expect(prismaService.user.findMany).toHaveBeenCalled();
});

it('should call prismaService.create when create is called', async () => {
const userData: Prisma.UserCreateInput = {
it('should call prismaService.update when update is called', async () => {
const id = 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf';
const data: Prisma.UserUpdateInput = {
username: 'Alice',
password: '123456',
};
const createdUser = {
const updatedUser = {
id: 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf',
username: 'Alice',
password: '123456',
} as User;

prismaService.user.create = jest.fn().mockReturnValueOnce(createdUser);
prismaService.user.update = jest.fn().mockReturnValueOnce(updatedUser);

const result = await prismaUserRepository.create(userData);
const result = await prismaUserRepository.update(id, data);

expect(result).toEqual(createdUser);
expect(prismaService.user.create).toHaveBeenCalledWith({ data: userData });
expect(result).toEqual(updatedUser);
expect(prismaService.user.update).toHaveBeenCalledWith({
where: { id },
data,
});
});

it('should call prismaService.delete when delete is called', async () => {
const id = 'fsdfsd-sdfsdfsd-sdfsdfsd-sdfsdf';

prismaService.user.delete = jest.fn().mockResolvedValueOnce(undefined);

await prismaUserRepository.delete(id);

expect(prismaService.user.delete).toHaveBeenCalledWith({
where: { id },
});
});

});
Original file line number Diff line number Diff line change
@@ -1,25 +1,71 @@
import { Injectable } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Prisma, User } from '@prisma/client';
import { UserRepository } from '../../repository/user.repositoy';
import { PrismaService } from '../prisma.service';

@Injectable()
export class PrismaUserRepository implements UserRepository {
constructor(private prisma: PrismaService) { }

async findOne(where: Prisma.UserWhereUniqueInput) {
async findById(id: string): Promise<User | null> {
const user = await this.prisma.user.findUnique({
where,
});
where: {
id,
},
})

if (!user) {
return null
}

return user;
}

async findByUsername(username: string): Promise<User | null> {
const user = await this.prisma.user.findUnique({
where: {
username,
},
})

if (!user) {
return null
}

return user;
}

async findMany(): Promise<User[]> {
const users = await this.prisma.user.findMany()

return users;
}

async create(data: Prisma.UserCreateInput) {
const user = await this.prisma.user.create({
data,
});

return user;
}

async update(id: string, data: Prisma.UserUpdateInput): Promise<User> {
const user = this.prisma.user.update({
where: {
id
},
data,
});

return user
}

async delete(id: string): Promise<void> {
await this.prisma.user.delete({
where: {
id,
},
})
}

}
8 changes: 6 additions & 2 deletions libs/common/src/database/repository/user.repositoy.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { Prisma, User } from "@prisma/client";

export abstract class UserRepository {
abstract findOne(where: Prisma.UserWhereUniqueInput): Promise<User | null>
abstract create(user: any): Promise<User>
abstract findById(id: string): Promise<User | null>
abstract findByUsername(username: string): Promise<User | null>
abstract findMany(): Promise<User[]>
abstract create(data: Prisma.UserCreateInput): Promise<User>
abstract update(id: string, data: Prisma.UserUpdateInput): Promise<User>
abstract delete(id: string): Promise<void>
}
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
"test:e2e": "jest --config ./jest-e2e.json"
},
"dependencies": {
"@aws-sdk/client-s3": "^3.417.0",
"@nestjs/common": "^10.2.5",
"@nestjs/config": "^3.1.1",
"@nestjs/core": "^10.0.0",
Expand Down Expand Up @@ -85,4 +84,4 @@
"^@app/common(|/.*)$": "<rootDir>/libs/common/src/$1"
}
}
}
}
2 changes: 1 addition & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ async function bootstrap() {
const configService = app.get(EnvService)
const port = configService.get('PORT')

app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
app.useGlobalPipes(new ValidationPipe());

const config = new DocumentBuilder()
.setTitle('API')
Expand Down
54 changes: 48 additions & 6 deletions src/modules/users/controllers/create-user.controller.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { INestApplication } from '@nestjs/common';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { UsersModule } from '../users.module';
import { DatabaseModule, PrismaService } from '@app/common';
import { randomUUID } from 'node:crypto'

describe('User (E2E)', () => {
describe('User (E2E) Create', () => {
let app: INestApplication;
let prisma: PrismaService;
let httpServer: any;
let UUID: string;

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
Expand All @@ -17,26 +19,66 @@ describe('User (E2E)', () => {

prisma = moduleRef.get(PrismaService);
app = moduleRef.createNestApplication();
app.useGlobalPipes(new ValidationPipe());
httpServer = app.getHttpServer();

await app.init();
});

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

beforeEach(() => {
UUID = randomUUID();
})

test('[POST] /user', async () => {
const response = await request(httpServer).post(`/user/create`).send({});
const response = await request(httpServer)
.post(`/user`)
.send({
username: `user-${UUID}`,
password: '123456',
});

expect(response.statusCode).toBe(200);
expect(response.statusCode).toBe(201);

const userOnDatabase = await prisma.user.findFirst({
where: {
username: 'henrique',
username: `user-${UUID}`
},
});

expect(userOnDatabase).toBeTruthy();
expect(response.body).toEqual(userOnDatabase);
});

test('[POST] /user with invalid data', async () => {
const response = await request(httpServer)
.post(`/user`)
.send({
username: '',
password: '123456',
});

expect(response.statusCode).toBe(400);
});

test('[POST] /user with already existing username', async () => {
await prisma.user.create({
data: {
username: `user-${UUID}`,
password: '123456',
},
});

const response = await request(httpServer)
.post(`/user`)
.send({
username: `user-${UUID}`,
password: '123456',
});

expect(response.statusCode).toBe(409);
});
});
24 changes: 17 additions & 7 deletions src/modules/users/controllers/create-user.controller.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import {
Body,
ConflictException,
Controller,
HttpCode,
HttpException,
HttpStatus,
Post
} from '@nestjs/common';
import { CreateUserUseCase } from '../use-case/create-user';
import { CreateUserDto } from '../dto/create-user.dto';
import { ApiOkResponse, ApiTags } from '@nestjs/swagger';
import { CreateUserDto } from '../dto/create-user.dto';
import { UserDto } from '../dto/user.dto';
import { CreateUserUseCase } from '../use-case/create-user';

@Controller('user')
@Controller('/user')
@ApiTags('user')
export class CreateUserController {
constructor(private createUserUseCase: CreateUserUseCase) { }

@HttpCode(HttpStatus.OK)
@ApiOkResponse({ type: UserDto })
@Post('create')
create(@Body() createUserDto: CreateUserDto) {
return this.createUserUseCase.create();
@HttpCode(HttpStatus.CREATED)
@Post('')
handle(@Body() createUserDto: CreateUserDto) {
try {
const user = this.createUserUseCase.execute(createUserDto);
return user;
} catch (e) {
if (e instanceof ConflictException) {
throw new HttpException('This username is already in use', HttpStatus.CONFLICT);
}
throw new HttpException('Was not possible to register', HttpStatus.BAD_REQUEST);
}
}
}
59 changes: 59 additions & 0 deletions src/modules/users/controllers/delete-user.controller.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { INestApplication, ValidationPipe } from '@nestjs/common';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import { UsersModule } from '../users.module';
import { DatabaseModule, PrismaService } from '@app/common';
import { randomUUID } from 'node:crypto'

describe('User (E2E) Delete', () => {
let app: INestApplication;
let prisma: PrismaService;
let httpServer: any;
let UUID: string;

beforeAll(async () => {
const moduleRef = await Test.createTestingModule({
imports: [UsersModule, DatabaseModule],
providers: [],
}).compile();

prisma = moduleRef.get(PrismaService);
app = moduleRef.createNestApplication();
app.useGlobalPipes(new ValidationPipe());
httpServer = app.getHttpServer();

await app.init();
});

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

beforeEach(() => {
UUID = randomUUID();
})

test('[DELETE] /user/:id', async () => {
const user = await prisma.user.create({
data: {
username: `user-${UUID}`,
password: '123456',
},
});

const response = await request(httpServer)
.delete(`/user/${user.id}`)
.send();

expect(response.statusCode).toBe(200);

const userOnDatabase = await prisma.user.findUnique({
where: {
id: user.id,
},
});

expect(userOnDatabase).toBeNull();
});

});
Loading

0 comments on commit bb3ff80

Please sign in to comment.