public void GivenInvalidPassword_ThrowsSubmarineArgumentException()
            {
                // Arrange
                var          userId       = Guid.NewGuid();
                const string emailAddress = "This is an email address";

                var authentication = new TestAuthenticationDtoBuilder()
                                     .WithEmailAddress(emailAddress)
                                     .Build();

                var user = new TestUserEntityBuilder()
                           .WithId(userId)
                           .WithEmailAddress(emailAddress)
                           .Build();

                _mediator.SetupHandler <GetUserByEmailQuery, UserEntity>().ReturnsAsync(user);

                // Act & Assert
                Assert.Multiple(() =>
                {
                    var exception = Assert.ThrowsAsync <DataMismatchException>(() =>
                                                                               _classUnderTest.AuthenticateAsync(authentication, CancellationToken.None));

                    Assert.That(exception.ExceptionCode, Is.EqualTo((int)ExceptionCode.DataMismatchException));
                    Assert.That(exception.TechnicalMessage, Is.Not.Null);
                    Assert.That(exception.UserMessage, Is.EqualTo(ExceptionMessages.Authentication.PasswordIsIncorrect));
                });

                _mediator.VerifyHandler <GetUserByEmailQuery, UserEntity>(query => query.EmailAddress == emailAddress, Times.Once());
            }
            public async Task GivenValidCredentials_ReturnsBearerToken()
            {
                // Arrange
                var          userId            = Guid.NewGuid();
                const string emailAddress      = "This is an email address";
                const string plainTextPassword = "******";
                const string licenseKey        = "This is a license key";

                var authentication = new TestAuthenticationDtoBuilder()
                                     .WithEmailAddress(emailAddress)
                                     .WithPlainTextPassword(plainTextPassword)
                                     .Build();

                var user = new TestUserEntityBuilder()
                           .WithId(userId)
                           .WithEmailAddress(emailAddress)
                           .WithRole(UserRole.Standard)
                           .Build();

                const bool isPasswordValid = true;

                var unexpiredProduct = new TestLicenseProductEntityBuilder()
                                       .WithName("Unexpired Product Name")
                                       .WithExpiration(DateTime.UtcNow.AddDays(1))
                                       .Build();

                var expiredProduct = new TestLicenseProductEntityBuilder()
                                     .WithName("Expired Product Name")
                                     .WithExpiration(DateTime.UtcNow.AddDays(-2))
                                     .Build();

                var license = new TestLicenseEntityBuilder()
                              .WithKey(licenseKey)
                              .WithProduct(unexpiredProduct)
                              .WithProduct(expiredProduct)
                              .Build();

                const string bearerToken = "This is a bearer token";

                _mediator.SetupHandler <GetUserByEmailQuery, UserEntity>().ReturnsAsync(user);
                _mediator.SetupHandler <CompareHashTextQuery, bool>().ReturnsAsync(isPasswordValid);
                _mediator.SetupHandler <GetLicenseByUserIdQuery, LicenseEntity>().ReturnsAsync(license);
                _mediator.SetupHandler <GenerateBearerTokenQuery, string>().ReturnsAsync(bearerToken);

                // Act
                var result = await _classUnderTest.AuthenticateAsync(authentication, CancellationToken.None);

                // Assert
                Assert.That(result.BearerToken, Is.EqualTo(bearerToken));

                _mediator.VerifyHandler <GetUserByEmailQuery, UserEntity>(query => query.EmailAddress == emailAddress, Times.Once());
                _mediator.VerifyHandler <CompareHashTextQuery, bool>(query => query.Hash == user.Password && query.Text == plainTextPassword, Times.Once());
                _mediator.VerifyHandler <GenerateBearerTokenQuery, string>(query => ValidateGenerateBearerTokenQuery(query, user, licenseKey), Times.Once());
            }
            public void GivenInvalidUser_ThrowsSubmarineEntityNotFoundException()
            {
                // Arrange
                const string emailAddress = "This is an email address";

                var authentication = new TestAuthenticationDtoBuilder()
                                     .WithEmailAddress(emailAddress)
                                     .Build();

                // Act & Assert
                Assert.Multiple(() =>
                {
                    var exception = Assert.ThrowsAsync <EntityNotFoundException>(() => _classUnderTest.AuthenticateAsync(authentication, CancellationToken.None));

                    Assert.That(exception.TechnicalMessage, Is.Not.Null);
                    Assert.That(exception.UserMessage, Is.EqualTo(ExceptionMessages.User.UserNotFound));
                });

                _mediator.Verify(x =>
                                 x.Send(It.Is <GetUserByEmailQuery>(query => query.EmailAddress == authentication.EmailAddress), CancellationToken.None), Times.Once);
            }
            public void GivenNoLicenseForUser_ThrowsSubmarineEntityNotFoundException()
            {
                // Arrange
                var          userId            = Guid.NewGuid();
                const string emailAddress      = "This is an email address";
                const string plainTextPassword = "******";

                var authentication = new TestAuthenticationDtoBuilder()
                                     .WithEmailAddress(emailAddress)
                                     .WithPlainTextPassword(plainTextPassword)
                                     .Build();

                var user = new TestUserEntityBuilder()
                           .WithId(userId)
                           .WithEmailAddress(emailAddress)
                           .Build();

                const bool isPasswordValid = true;

                _mediator.SetupHandler <GetUserByEmailQuery, UserEntity>().ReturnsAsync(user);
                _mediator.SetupHandler <CompareHashTextQuery, bool>().ReturnsAsync(isPasswordValid);

                // Act & Assert
                Assert.Multiple(() =>
                {
                    var exception = Assert.ThrowsAsync <EntityNotFoundException>(() =>
                                                                                 _classUnderTest.AuthenticateAsync(authentication, CancellationToken.None));

                    Assert.That(exception.ExceptionCode, Is.EqualTo((int)ExceptionCode.EntityNotFound));
                    Assert.That(exception.TechnicalMessage, Is.Not.Null);
                    Assert.That(exception.UserMessage, Is.EqualTo(ExceptionMessages.License.NoLicenseWithUserId));
                });

                _mediator.VerifyHandler <GetUserByEmailQuery, UserEntity>(query => query.EmailAddress == emailAddress, Times.Once());
                _mediator.VerifyHandler <CompareHashTextQuery, bool>(query => query.Hash == user.Password && query.Text == plainTextPassword, Times.Once());
            }