Skip to content

Commit

Permalink
Merge pull request #5 from vicheanath/git-repo
Browse files Browse the repository at this point in the history
Add Authentication UnitTest
  • Loading branch information
vicheanath authored Sep 12, 2024
2 parents 0a3e44e + 2096b87 commit 0a1bb40
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
using FluentAssertions;
using Moq;
using SearchBugs.Application.Authentications.Login;
using SearchBugs.Domain.Services;
using SearchBugs.Domain.Users;
using Shared.Results;

namespace SearchBugs.Application.UnitTests.AuthenicationsTest;

public class LoginCommandHandlerTest
{
private readonly Mock<IUserRepository> _userRepository;
private readonly Mock<IJwtProvider> _jwtProvider;
private readonly Mock<IPasswordHashingService> _hasher;
private readonly LoginCommandHandler _sut;

public LoginCommandHandlerTest()
{
_userRepository = new();
_jwtProvider = new();
_hasher = new();
_sut = new LoginCommandHandler(_userRepository.Object, _jwtProvider.Object, _hasher.Object);
}

[Fact]
public async Task Handle_WhenUserNotFound_ShouldReturnFailure_WithNotFoundByEmailError()
{
// Arrange
var email = "[email protected]";
var password = "password";
var command = new LoginCommand(email, password);
_userRepository.Setup(x => x.GetUserByEmailAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure<User>(UserErrors.NotFoundByEmail(email)));

// Act
var result = await _sut.Handle(command, CancellationToken.None);

// Assert
result.IsSuccess.Should().BeFalse();
result.Error.Should().Be(UserErrors.NotFoundByEmail(email));
}

[Fact]
public async Task Handle_WhenPasswordIsInvalid_ShouldReturnFailure_WithInvalidPasswordError()
{
// Arrange
var email = "[email protected]";
var password = "password";
var command = new LoginCommand(email, password);
_userRepository.Setup(x => x.GetUserByEmailAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Success(User.Create(Name.Create("First", "Last"), Email.Create(email), "hashedPassword").Value));

_hasher.Setup(x => x.VerifyPassword(It.IsAny<string>(), It.IsAny<string>()))
.Returns(false);

// Act
var result = await _sut.Handle(command, CancellationToken.None);
result.IsSuccess.Should().BeFalse();
result.Error.Should().Be(UserErrors.InvalidPassword);
}

[Fact]
public async Task Handle_WhenUserFound_ShouldReturnSuccess_WithJwtToken()
{
// Arrange
var email = "[email protected]";
var password = "password";
var command = new LoginCommand(email, password);
var user = User.Create(Name.Create("First", "Last"), Email.Create(email), "hashedPassword").Value;
_userRepository.Setup(x => x.GetUserByEmailAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Success(user));

_hasher.Setup(x => x.VerifyPassword(It.IsAny<string>(), It.IsAny<string>()))
.Returns(true);

_jwtProvider.Setup(x => x.GenerateJwtToken(It.IsAny<User>()))
.Returns("jwtToken");

// Act
var result = await _sut.Handle(command, CancellationToken.None);
result.IsSuccess.Should().BeTrue();
result.Value.Token.Should().Be("jwtToken");

}

}

Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using FluentAssertions;
using Moq;
using SearchBugs.Application.Authentications;
using SearchBugs.Application.Authentications.Register;
using SearchBugs.Domain;
using SearchBugs.Domain.Roles;
using SearchBugs.Domain.Services;
using SearchBugs.Domain.Users;
using Shared.Results;

namespace SearchBugs.Application.UnitTests.AuthenicationsTest;

public class RegisterCommandHandlerTest
{
private readonly Mock<IUserRepository> _userRepository;
private readonly Mock<IPasswordHashingService> _hasher;
private readonly Mock<IUnitOfWork> _unitOfWork;
private readonly RegisterCommandHandler _sut;

public RegisterCommandHandlerTest()
{
_userRepository = new();
_hasher = new();
_unitOfWork = new();
_sut = new RegisterCommandHandler(_userRepository.Object, _hasher.Object, _unitOfWork.Object);
}

[Fact]
public async Task Handle_WhenEmailIsNotUnique_ShouldReturnFailure_WithDuplicateEmailError()
{
// Arrange
var email = "[email protected]";
var password = "password";

var command = new RegisterCommand(email, password, "First", "Last");

_userRepository.Setup(x => x.IsEmailUniqueAsync(Email.Create(email), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Failure<User>(AuthValidationErrors.EmailAlreadyExists));

// Act
var result = await _sut.Handle(command, CancellationToken.None);

// Assert
result.IsSuccess.Should().BeFalse();
result.Error.Should().Be(AuthValidationErrors.EmailAlreadyExists);
}

[Fact]
public async Task Handle_WhenEmailIsUnique_ShouldReturnSuccess()
{
// Arrange
var email = "[email protected]";
var password = "password";

var command = new RegisterCommand(email, password, "First", "Last");

_userRepository.Setup(x => x.IsEmailUniqueAsync(Email.Create(email), It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Success<User>(User.Create(Name.Create("First", "Last"), Email.Create(email), "hashedPassword").Value));


_userRepository.Setup(x => x.GetRoleByIdAsync(Role.Guest.Id, It.IsAny<CancellationToken>()))
.ReturnsAsync(Result.Success<Role>(Role.Guest));

// Act
var result = await _sut.Handle(command, CancellationToken.None);

// Assert
result.IsSuccess.Should().BeTrue();
_userRepository.Verify(x => x.Add(It.IsAny<User>()), Times.Once);
_unitOfWork.Verify(x => x.SaveChangesAsync(It.IsAny<CancellationToken>()), Times.Once);
_userRepository.Verify(x => x.GetRoleByIdAsync(Role.Guest.Id, It.IsAny<CancellationToken>()), Times.Once);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,18 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
<PackageReference Include="xunit" Version="2.5.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3" />
<PackageReference Include="coverlet.collector" Version="6.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="FluentAssertions" Version="6.12.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
Expand All @@ -24,4 +32,10 @@
<Folder Include="Data\Users\" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\SearchBugs.Application\SearchBugs.Application.csproj" />
<ProjectReference Include="..\SearchBugs.Domain\SearchBugs.Domain.csproj" />
<ProjectReference Include="..\Shared\Shared.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ public async Task<Result> Handle(RegisterCommand request, CancellationToken canc
Name.Create(request.FirstName, request.LastName),
Email.Create(request.Email),
passwordHashingService.HashPassword(request.Password));
var emailIsUnique = await CheckIfEmailIsUniqueAsync(user.Value.Email, cancellationToken);
if (!emailIsUnique.IsSuccess)
{
return Result.Failure(AuthValidationErrors.EmailAlreadyExists);
}

var role = await _userRepository.GetRoleByIdAsync(Role.Guest.Id, cancellationToken);
user.Value.AddRole(role.Value);
Expand All @@ -36,6 +41,6 @@ public async Task<Result> Handle(RegisterCommand request, CancellationToken canc

}

private async Task<Result<User>> CheckIfEmailIsUniqueAsync(User user, CancellationToken cancellationToken) =>
await _userRepository.IsEmailUniqueAsync(user.Email, cancellationToken);
private async Task<Result<User>> CheckIfEmailIsUniqueAsync(Email email, CancellationToken cancellationToken) =>
await _userRepository.IsEmailUniqueAsync(email, cancellationToken);
}
1 change: 0 additions & 1 deletion SearchBugs.Ui/src/Route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ const router = createBrowserRouter([
path: "/projects/:projectId",
element: <ProjectDetailsPage />,
},

{
path: "/users",
element: <UsersPage />,
Expand Down

0 comments on commit 0a1bb40

Please sign in to comment.