Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 186 additions & 58 deletions src/users/users.controller.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -468,10 +468,21 @@ describe('UsersAdminController', () => {

describe('addPhoto', () => {
const userId = new Types.ObjectId().toString();
const photoDto = {
userId,
photo: 'new-photo-url.jpg',
};
const photoDto = { userId, photo: 'new-photo-url.jpg' };
const mockReq = { user: createUserMock() };

it('should add a photo to user profile', async () => {
const expectedResult = createUserMock({ photo: photoDto.photo });
jest.spyOn(usersService, 'addPhoto').mockResolvedValue(expectedResult);

const result = await adminController.addPhoto(mockReq, userId, photoDto);

expect(result).toEqual(expectedResult);
expect(usersService.addPhoto).toHaveBeenCalledWith(
photoDto.userId,
photoDto,
);
});

it('should throw error when invalid photo format', async () => {
const mockReq = { user: createUserMock() };
Expand All @@ -486,12 +497,9 @@ describe('UsersAdminController', () => {
).rejects.toThrow(BadRequestException);
});

it('should throw error when photo size exceeds limit', async () => {
const mockReq = { user: createUserMock() };

jest
.spyOn(usersService, 'addPhoto')
.mockRejectedValue(new BadRequestException('Photo size exceeds limit'));
.mockRejectedValue(new BadRequestException());

await expect(
adminController.addPhoto(mockReq, userId, photoDto),
Expand All @@ -501,14 +509,12 @@ describe('UsersAdminController', () => {

describe('RequestVerificationToken', () => {
const userId = new Types.ObjectId().toString();
const mockReq = { user: createUserMock() };

it('should request new verification token', async () => {
const mockReq = { user: createUserMock() };

// Mocking the requestVerification method to resolve successfully
jest
.spyOn(usersService, 'requestVerification')
.mockResolvedValue(undefined); // or just don't mock return value
.mockResolvedValue(undefined);

await adminController.RequestVerificationToken(mockReq, userId);

Expand All @@ -518,56 +524,14 @@ describe('UsersAdminController', () => {
);
});

it('should throw error when user not found', async () => {
const mockReq = { user: createUserMock() };

jest
.spyOn(usersService, 'requestVerification')
.mockRejectedValue(new Error('User not found'));

await expect(
adminController.RequestVerificationToken(mockReq, userId),
).rejects.toThrow('User not found');
});

it('should throw error when verification request not allowed', async () => {
const mockReq = { user: createUserMock() };

it('should handle verification errors', async () => {
jest
.spyOn(usersService, 'requestVerification')
.mockRejectedValue(
new Error('Verification request not allowed at this time'),
);
.mockRejectedValue(new Error('User not found'));

await expect(
adminController.RequestVerificationToken(mockReq, userId),
).rejects.toThrow('Verification request not allowed at this time');
});

it('should throw error when user already verified', async () => {
const mockReq = {
user: createUserMock({ applicationStatus: ApplicationStatus.APPROVED }),
};

jest
.spyOn(usersService, 'requestVerification')
.mockRejectedValue(new Error('User is already verified'));

await expect(
adminController.RequestVerificationToken(mockReq, userId),
).rejects.toThrow('User is already verified');
});

it('should throw error when too many requests', async () => {
const mockReq = { user: createUserMock() };

jest
.spyOn(usersService, 'requestVerification')
.mockRejectedValue(new Error('Too many verification requests'));

await expect(
adminController.RequestVerificationToken(mockReq, userId),
).rejects.toThrow('Too many verification requests');
).rejects.toThrow('User not found');
});
});

Expand Down Expand Up @@ -612,7 +576,6 @@ describe('UsersAdminController', () => {
it('should throw error when updating non-existent user', async () => {
const statusDto = { status: UserStatus.ACTIVE };
const mockReq = { user: createUserMock() };

// Mocking the service to throw an error when the user is not found
jest
.spyOn(usersService, 'updateStatus')
Expand Down Expand Up @@ -731,4 +694,169 @@ describe('UsersAdminController', () => {
});
});
});

describe('Deactivate User Account', () => {
const userId = new Types.ObjectId().toString();
const deactivateDto = { reason: 'Taking a break' };
const mockReq = { user: createUserMock() };

it('should deactivate a user account', async () => {
const expectedResult = createUserMock({ status: UserStatus.DEACTIVATED });
jest
.spyOn(usersService, 'deactivateAccount')
.mockResolvedValue(expectedResult);

const result = await controller.deactivateAccount(
mockReq,
userId,
deactivateDto,
);

expect(result).toEqual(expectedResult);
expect(usersService.deactivateAccount).toHaveBeenCalledWith(userId);
});

it('should handle deactivation errors', async () => {
jest
.spyOn(usersService, 'deactivateAccount')
.mockRejectedValue(new NotFoundException());

await expect(
controller.deactivateAccount(mockReq, userId, deactivateDto),
).rejects.toThrow(NotFoundException);
});
});

describe('Request Reactivation', () => {
const userId = new Types.ObjectId().toString();
const reactivationDto = { message: 'Ready to come back' };

it('should request reactivation of a user account', async () => {
const expectedResult = createUserMock({ status: UserStatus.ACTIVE });
jest
.spyOn(usersService, 'requestReactivation')
.mockResolvedValue(expectedResult);

const result = await controller.requestReactivation(
userId,
reactivationDto,
);

expect(result).toEqual(expectedResult);
expect(usersService.requestReactivation).toHaveBeenCalledWith(userId);
});

it('should handle reactivation errors', async () => {
jest
.spyOn(usersService, 'requestReactivation')
.mockRejectedValue(new NotFoundException());

await expect(
controller.requestReactivation(userId, reactivationDto),
).rejects.toThrow(NotFoundException);
});
});

describe('Lead Registration', () => {
const tempLeadDto = {
email: '[email protected]',
leadPosition: 'Senior Developer',
firstName: 'John',
lastName: 'Doe',
createdAt: new Date(),
};

it('should successfully register a temporary lead', async () => {
const expectedResult = 'Application sent';
jest
.spyOn(usersService, 'createTempRegistration')
.mockResolvedValue(expectedResult);

const result = await controller.createLead(tempLeadDto);

expect(result).toEqual(expectedResult);
expect(usersService.createTempRegistration).toHaveBeenCalledWith(
tempLeadDto.email,
tempLeadDto.leadPosition,
);
});

it('should throw BadRequestException when registration not allowed', async () => {
jest
.spyOn(usersService, 'createTempRegistration')
.mockRejectedValue(new BadRequestException());

await expect(controller.createLead(tempLeadDto)).rejects.toThrow(
BadRequestException,
);
});
});

describe('Register New User Form', () => {
const encryptedData = 'encryptedString';
const userId = new Types.ObjectId().toString();
const email = '[email protected]';

it('should redirect to create lead page when user exists', async () => {
const mockUser = createUserMock({
_id: new Types.ObjectId(userId),
email,
});

jest
.spyOn(usersService, 'paraseEncryptedParams')
.mockReturnValue({ userId, email });
jest.spyOn(usersService, 'findById').mockResolvedValue(mockUser);

const result = await controller.register(encryptedData);

expect(result).toEqual({ url: `/leads/createLead?email=${email}` });
});

it('should handle invalid links', async () => {
jest
.spyOn(usersService, 'paraseEncryptedParams')
.mockImplementation(() => {
throw new Error('Decryption failed');
});

await expect(controller.register(encryptedData)).rejects.toThrow(
NotFoundException,
);
});
});

describe('User Invite Link', () => {
const encryptedData = 'encryptedInviteString';
const userId = new Types.ObjectId().toString();
const email = '[email protected]';

it('should redirect to create lead page when user exists', async () => {
const mockUser = createUserMock({
_id: new Types.ObjectId(userId),
email,
});

jest
.spyOn(usersService, 'paraseEncryptedParams')
.mockReturnValue({ userId, email });
jest.spyOn(usersService, 'findById').mockResolvedValue(mockUser);

const result = await controller.register(encryptedData);

expect(result).toEqual({ url: `/leads/createLead?email=${email}` });
});

it('should redirect to new user form when userId is missing', async () => {
jest
.spyOn(usersService, 'paraseEncryptedParams')
.mockReturnValue({ userId: '', email });

const result = await controller.register(encryptedData);

expect(result).toEqual({
url: `/leads/new-user-form?email=${encodeURIComponent(email)}`,
});
});
});
});
4 changes: 2 additions & 2 deletions src/users/users.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,6 @@ export class UsersService {
async createUser(userData: CreateUserDto) {
return (this.userModel as any).signUp(userData);
}

async requestVerification(req: ApiReq, userId: string) {
const user = await this.userModel.findById(userId);
if (!user) {
Expand All @@ -679,6 +678,7 @@ export class UsersService {
throw new BadRequestException('You are already verified.');
}


// Update user state
user.applicationStatus = ApplicationStatus.PENDING;
user.nextVerificationRequestDate = new Date(
Expand All @@ -698,7 +698,7 @@ export class UsersService {
nextTryDate: format(user.nextVerificationRequestDate, 'PPPP'),
},
});

return {
message: 'Verification request sent.',
nextAllowedRequest: user.nextVerificationRequestDate,
Expand Down