feat(auth): #127 forgot-password + reset-password API (BDD + mail)
Made-with: Cursor
This commit is contained in:
@@ -18,18 +18,38 @@ describe('AuthService (#118 create-password API)', () => {
|
||||
const usersRepoMock = {
|
||||
findOne: jest.fn(),
|
||||
createQueryBuilder: jest.fn(),
|
||||
update: jest.fn(),
|
||||
};
|
||||
|
||||
const mailServiceMock = {
|
||||
sendPasswordResetEmail: jest.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const appConfigMock = {
|
||||
get: jest.fn().mockReturnValue(7),
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
const qbChain: any = {};
|
||||
qbChain.where = jest.fn().mockReturnValue(qbChain);
|
||||
qbChain.select = jest.fn().mockReturnValue(qbChain);
|
||||
qbChain.getOne = jest.fn().mockResolvedValue(null);
|
||||
qbChain.update = jest.fn().mockReturnValue(qbChain);
|
||||
qbChain.set = jest.fn().mockReturnValue(qbChain);
|
||||
qbChain.andWhere = jest.fn().mockReturnValue(qbChain);
|
||||
qbChain.execute = jest.fn().mockResolvedValue({ affected: 0 });
|
||||
usersRepoMock.createQueryBuilder.mockReturnValue(qbChain);
|
||||
usersRepoMock.update.mockResolvedValue({ affected: 1, raw: [] });
|
||||
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [
|
||||
AuthService,
|
||||
{ provide: UserService, useValue: {} },
|
||||
{ provide: JwtService, useValue: {} },
|
||||
{ provide: ConfigService, useValue: { get: jest.fn() } },
|
||||
{ provide: AppConfigService, useValue: {} },
|
||||
{ provide: MailService, useValue: {} },
|
||||
{ provide: AppConfigService, useValue: appConfigMock },
|
||||
{ provide: MailService, useValue: mailServiceMock },
|
||||
{ provide: NumeroDossierService, useValue: {} },
|
||||
{ provide: getRepositoryToken(Parents), useValue: {} },
|
||||
{ provide: getRepositoryToken(Users), useValue: usersRepoMock },
|
||||
@@ -61,4 +81,59 @@ describe('AuthService (#118 create-password API)', () => {
|
||||
message: 'Token valide',
|
||||
});
|
||||
});
|
||||
|
||||
describe('#127 forgot / reset password', () => {
|
||||
it('requestPasswordReset returns generic message when email unknown', async () => {
|
||||
const r = await service.requestPasswordReset('unknown@test.fr');
|
||||
expect(r.message).toContain('Si cette adresse');
|
||||
expect(mailServiceMock.sendPasswordResetEmail).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('requestPasswordReset sends mail when user has password', async () => {
|
||||
usersRepoMock.createQueryBuilder.mockReturnValueOnce({
|
||||
where: jest.fn().mockReturnThis(),
|
||||
select: jest.fn().mockReturnThis(),
|
||||
getOne: jest.fn().mockResolvedValue({
|
||||
id: 'u1',
|
||||
email: 'a@test.fr',
|
||||
prenom: 'A',
|
||||
nom: 'B',
|
||||
password: 'hashed',
|
||||
}),
|
||||
});
|
||||
const r = await service.requestPasswordReset('a@test.fr');
|
||||
expect(r.message).toContain('Si cette adresse');
|
||||
expect(usersRepoMock.update).toHaveBeenCalled();
|
||||
expect(mailServiceMock.sendPasswordResetEmail).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ email: 'a@test.fr', token: expect.any(String) }),
|
||||
);
|
||||
});
|
||||
|
||||
it('resetPasswordWithResetToken throws when token unknown', async () => {
|
||||
usersRepoMock.findOne.mockResolvedValue(null);
|
||||
await expect(service.resetPasswordWithResetToken('bad', 'Password1')).rejects.toThrow(
|
||||
NotFoundException,
|
||||
);
|
||||
});
|
||||
|
||||
it('resetPasswordWithResetToken succeeds when update affects row', async () => {
|
||||
usersRepoMock.findOne.mockResolvedValue({
|
||||
id: 'u1',
|
||||
password: 'oldhash',
|
||||
password_reset_expires: new Date(Date.now() + 60_000),
|
||||
});
|
||||
const exec = jest.fn().mockResolvedValue({ affected: 1 });
|
||||
const chain: any = {};
|
||||
chain.update = jest.fn().mockReturnValue(chain);
|
||||
chain.set = jest.fn().mockReturnValue(chain);
|
||||
chain.where = jest.fn().mockReturnValue(chain);
|
||||
chain.andWhere = jest.fn().mockReturnValue(chain);
|
||||
chain.execute = exec;
|
||||
usersRepoMock.createQueryBuilder.mockReturnValueOnce(chain);
|
||||
|
||||
const r = await service.resetPasswordWithResetToken('good-token', 'Password1');
|
||||
expect(r.message.toLowerCase()).toContain('mis à jour');
|
||||
expect(exec).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user