-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #94 from zhumeisongsong/feature/get-user-by-email
feat: ✨ add findByEmail use case
- Loading branch information
Showing
13 changed files
with
187 additions
and
60 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
export * from './lib/use-cases/get-user.use-case'; | ||
export * from './lib/use-cases/get-user-by-id.use-case'; | ||
export * from './lib/use-cases/get-user-by-email.use-case'; | ||
|
||
// service | ||
export * from './lib/users.service'; |
41 changes: 41 additions & 0 deletions
41
libs/users/application/src/lib/use-cases/get-user-by-email.use-case.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { GetUserByEmailUseCase } from './get-user-by-email.use-case'; | ||
import { UsersRepository } from '@users/domain'; | ||
|
||
describe('GetUserByEmailUseCase', () => { | ||
let getUserByEmailUseCase: GetUserByEmailUseCase; | ||
let usersRepository: UsersRepository; | ||
|
||
beforeEach(() => { | ||
usersRepository = { | ||
findById: jest.fn(), | ||
findByEmail: jest.fn(), | ||
}; | ||
getUserByEmailUseCase = new GetUserByEmailUseCase(usersRepository); | ||
}); | ||
|
||
describe('execute', () => { | ||
it('should return user when found', async () => { | ||
const mockUser = { | ||
id: '1', | ||
email: '[email protected]', | ||
firstName: 'John', | ||
lastName: 'Doe', | ||
}; | ||
(usersRepository.findByEmail as jest.Mock).mockResolvedValue(mockUser); | ||
|
||
const result = await getUserByEmailUseCase.execute('[email protected]'); | ||
|
||
expect(result).toEqual(mockUser); | ||
expect(usersRepository.findByEmail).toHaveBeenCalledWith("[email protected]"); | ||
}); | ||
|
||
it('should return null when user not found', async () => { | ||
(usersRepository.findByEmail as jest.Mock).mockResolvedValue(null); | ||
|
||
const result = await getUserByEmailUseCase.execute('[email protected]'); | ||
|
||
expect(result).toBeNull(); | ||
expect(usersRepository.findByEmail).toHaveBeenCalledWith("[email protected]"); | ||
}); | ||
}); | ||
}); |
14 changes: 14 additions & 0 deletions
14
libs/users/application/src/lib/use-cases/get-user-by-email.use-case.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { Inject, Injectable } from "@nestjs/common"; | ||
import { User, USERS_REPOSITORY, UsersRepository } from "@users/domain"; | ||
|
||
@Injectable() | ||
export class GetUserByEmailUseCase { | ||
constructor( | ||
@Inject(USERS_REPOSITORY) | ||
private readonly usersRepository: UsersRepository, | ||
) {} | ||
|
||
async execute(email: string): Promise<User | null> { | ||
return this.usersRepository.findByEmail(email); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,25 @@ | ||
import { Test, TestingModule } from '@nestjs/testing'; | ||
import { UsersService } from './users.service'; | ||
import { GetUserUseCase } from './use-cases/get-user.use-case'; | ||
import { User } from '@users/domain'; | ||
import { GetUserByIdUseCase } from './use-cases/get-user-by-id.use-case'; | ||
import { GetUserByEmailUseCase } from './use-cases/get-user-by-email.use-case'; | ||
|
||
describe('UsersService', () => { | ||
let service: UsersService; | ||
let getUserUseCase: GetUserUseCase; | ||
let getUserByIdUseCase: GetUserByIdUseCase; | ||
let getUserByEmailUseCase: GetUserByEmailUseCase; | ||
|
||
beforeEach(async () => { | ||
const module: TestingModule = await Test.createTestingModule({ | ||
providers: [ | ||
UsersService, | ||
{ | ||
provide: GetUserUseCase, | ||
provide: GetUserByIdUseCase, | ||
useValue: { | ||
execute: jest.fn(), | ||
}, | ||
}, | ||
{ | ||
provide: GetUserByEmailUseCase, | ||
useValue: { | ||
execute: jest.fn(), | ||
}, | ||
|
@@ -21,32 +28,59 @@ describe('UsersService', () => { | |
}).compile(); | ||
|
||
service = module.get<UsersService>(UsersService); | ||
getUserUseCase = module.get<GetUserUseCase>(GetUserUseCase); | ||
getUserByIdUseCase = module.get<GetUserByIdUseCase>(GetUserByIdUseCase); | ||
getUserByEmailUseCase = module.get<GetUserByEmailUseCase>(GetUserByEmailUseCase); | ||
}); | ||
|
||
it('should be defined', () => { | ||
expect(service).toBeDefined(); | ||
describe('getUserById', () => { | ||
it('should return user when found', async () => { | ||
const mockUser = { | ||
id: '1', | ||
email: '[email protected]', | ||
firstName: 'John', | ||
lastName: 'Doe', | ||
}; | ||
(getUserByIdUseCase.execute as jest.Mock).mockResolvedValue(mockUser); | ||
|
||
const result = await service.findById('1'); | ||
|
||
expect(result).toEqual(mockUser); | ||
expect(getUserByIdUseCase.execute).toHaveBeenCalledWith('1'); | ||
}); | ||
|
||
it('should return null when user not found', async () => { | ||
(getUserByIdUseCase.execute as jest.Mock).mockResolvedValue(null); | ||
|
||
const result = await service.findById('1'); | ||
|
||
expect(result).toBeNull(); | ||
expect(getUserByIdUseCase.execute).toHaveBeenCalledWith('1'); | ||
}); | ||
}); | ||
|
||
describe('findById', () => { | ||
it('should return a user if found', async () => { | ||
const user: User = { | ||
describe('getUserByEmail', () => { | ||
it('should return user when found', async () => { | ||
const mockUser = { | ||
id: '1', | ||
email: '[email protected]', | ||
firstName: 'John', | ||
lastName: 'Doe', | ||
}; | ||
jest.spyOn(getUserUseCase, 'execute').mockResolvedValue(user); | ||
(getUserByEmailUseCase.execute as jest.Mock).mockResolvedValue(mockUser); | ||
|
||
const result = await service.findById('1'); | ||
expect(result).toEqual(user); | ||
const result = await service.findByEmail('[email protected]'); | ||
|
||
expect(result).toEqual(mockUser); | ||
expect(getUserByEmailUseCase.execute).toHaveBeenCalledWith('[email protected]'); | ||
}); | ||
|
||
it('should return null if user not found', async () => { | ||
jest.spyOn(getUserUseCase, 'execute').mockResolvedValue(null); | ||
it('should return null when user not found', async () => { | ||
(getUserByEmailUseCase.execute as jest.Mock).mockResolvedValue(null); | ||
|
||
const result = await service.findByEmail('[email protected]'); | ||
|
||
const result = await service.findById('2'); | ||
expect(result).toBeNull(); | ||
expect(getUserByEmailUseCase.execute).toHaveBeenCalledWith('[email protected]'); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,21 @@ | ||
import { Injectable } from '@nestjs/common'; | ||
import { User } from '@users/domain'; | ||
|
||
import { GetUserUseCase } from './use-cases/get-user.use-case'; | ||
import { GetUserByIdUseCase } from './use-cases/get-user-by-id.use-case'; | ||
import { GetUserByEmailUseCase } from './use-cases/get-user-by-email.use-case'; | ||
|
||
@Injectable() | ||
export class UsersService { | ||
constructor(private readonly getUserUseCase: GetUserUseCase) {} | ||
constructor( | ||
private readonly getUserByIdUseCase: GetUserByIdUseCase, | ||
private readonly getUserByEmailUseCase: GetUserByEmailUseCase, | ||
) {} | ||
|
||
async findById(id: string): Promise<User | null> { | ||
return this.getUserUseCase.execute(id); | ||
return this.getUserByIdUseCase.execute(id); | ||
} | ||
|
||
async findByEmail(email: string): Promise<User | null> { | ||
// TODO: refactor getUserUseCase | ||
return this.getUserUseCase.execute(email); | ||
return this.getUserByEmailUseCase.execute(email); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,10 @@ class MockUsersRepository implements UsersRepository { | |
async findById(id: string): Promise<User | null> { | ||
return this.users.find((user) => user.id === id) || null; | ||
} | ||
|
||
async findByEmail(email: string): Promise<User | null> { | ||
return this.users.find((user) => user.email === email) || null; | ||
} | ||
} | ||
|
||
describe('UsersRepository', () => { | ||
|
@@ -38,4 +42,19 @@ describe('UsersRepository', () => { | |
const user = await usersRepository.findById('3'); | ||
expect(user).toBeNull(); | ||
}); | ||
|
||
test('findByEmail should return a user by email', async () => { | ||
const user = await usersRepository.findByEmail('[email protected]'); | ||
expect(user).toEqual({ | ||
id: '2', | ||
email: '[email protected]', | ||
firstName: 'Jane', | ||
lastName: 'Smith', | ||
}); | ||
}); | ||
|
||
test('findByEmail should return null if user not found', async () => { | ||
const user = await usersRepository.findByEmail('[email protected]'); | ||
expect(user).toBeNull(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.