public async Task UpdateProfile_ProfileUpdated_Success()
        {
            // Arrange
            var updateProfileDTO = DummyData.UpdateProfileDTOFaker.Generate();
            var user             = DummyData.UserFaker.Generate();
            var appUser          = FakeAppUser.For(user);

            _updateProfileValidator.SetupPass();
            _um.FindByNameAsync(appUser.Email).Returns(appUser);
            _um.UpdateAsync(appUser).Returns(IdentityResult.Success);

            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);

            // Act
            var result = await _sut.Update(updateProfileDTO);

            // Assert
            result.Should().BeOfType <OkObjectResult>()
            .Which.Value.Should().BeEquivalentTo(
                updateProfileDTO,
                options => options.Excluding(u => u.Friends)
                );
            _userRepository.Received().Update(user);
        }
        public void Post_ValidationFailed_ReturnsBadRequest()
        {
            // Arrange 
            var route = DummyData.RouteFaker.Generate();
            var user = DummyData.UserFaker.Generate();
            var routeRegistrationDTO = DummyData.RouteRegistrationDTOFaker.Generate();
            routeRegistrationDTO.OrderedShirt = true;
            routeRegistrationDTO.RouteId = route.Id;
            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);
            _routeRepository.GetBy(route.Id).Returns(route);

            _validator.SetupFail();

            // Act 
            var numberOfRegistrations = user.Registrations.Count;
            var result = _sut.Post(routeRegistrationDTO);

            // Assert 
            result.Should().BeOfType<BadRequestObjectResult>()
                .Which.Value.Should().BeOfType<ValidationResult>()
                .Which.IsValid.Should().BeFalse();

            _userRepository.DidNotReceive().GetBy(user.Email);
            user.Registrations.Count.Should().Be(numberOfRegistrations);
        }
        public async Task Delete_NoSuchRegistration_ReturnsBadRequest()
        {
            // Arrange 
            var user = DummyData.UserFaker.Generate();
            var registrationId = Guid.NewGuid();

            _sut.ControllerContext = FakeControllerContext.For(user);

            _userRepository.GetBy(user.Email).Returns(user);
            _registrationRepository.GetBy(Arg.Any<Guid>(), user.Email).ReturnsNull();

            var appUser = FakeAppUser.For(user).WithClaims("admin");
            _um.FindByNameAsync(user.Email).Returns(Task.FromResult(appUser));


            // Act 
            var numberOfRegistrations = user.Registrations.Count;
            var result = await _sut.DeleteAsync(registrationId);

            // Assert 
            result.Should().BeOfType<BadRequestResult>();

            user.Registrations.Count.Should().Be(numberOfRegistrations);
            _userRepository.Received().GetBy(user.Email);
            _registrationRepository.Received().GetBy(registrationId, user.Email);
            _registrationRepository.DidNotReceive().Delete(Arg.Any<Registration>(), user.Email);
        }
        public void Post_LoggedInUserWithGoodRoute_ShouldRegisterAndReturnsOk()
        {
            // Arrange 
            var route = DummyData.RouteFaker.Generate();
            var user = DummyData.UserFaker.Generate();
            var routeRegistrationDTO = DummyData.RouteRegistrationDTOFaker.Generate();
            routeRegistrationDTO.OrderedShirt = true;
            routeRegistrationDTO.RouteId = route.Id;
            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);
            _routeRepository.GetBy(route.Id).Returns(route);
            _validator.SetupPass();

            // Act 
            var numberOfRegistrations = user.Registrations.Count;
            var result = _sut.Post(routeRegistrationDTO);

            // Assert 
            result.Should().BeOfType<OkObjectResult>()
                .Which.Value.Should().BeEquivalentTo(
                    routeRegistrationDTO,
                    options => options.Using(new EnumAsStringAssertionRule()) //treat enums as strings
                );

            _userRepository.Received().GetBy(user.Email);
            _routeRepository.Received().GetBy(route.Id);
            //registration is added to user 
            user.Registrations.Count.Should().Be(numberOfRegistrations + 1);
        }
        public async Task Delete_LoggedInUserWithGoodRegistration_ShouldDeleteRegistrationAndReturnsOk()
        {
            // Arrange 
            var user = DummyData.UserFaker.Generate();
            var registration = user.Registrations.Last();

            _sut.ControllerContext = FakeControllerContext.For(user);

            _userRepository.GetBy(user.Email).Returns(user);
            _registrationRepository.GetBy(registration.Id, user.Email).Returns(registration);

            var appUser = FakeAppUser.For(user).WithClaims("admin");
            _um.FindByNameAsync(user.Email).Returns(Task.FromResult(appUser));

            // Act 
            var result = await _sut.DeleteAsync(registration.Id);

            // Assert 
            result.Should().BeOfType<OkObjectResult>()
                .Which.Value.Should().BeEquivalentTo(
                    registration,
                    options => options.Using(new EnumAsStringAssertionRule()) //treat enums as strings
                );


            _userRepository.Received().GetBy(user.Email);
            _registrationRepository.Received().Delete(registration, user.Email);
        }
        public void Post_RouteNotFound_ReturnsBadRequest()
        {
            // Arrange 
            var route = DummyData.RouteFaker.Generate();
            var user = DummyData.UserFaker.Generate();
            var routeRegistrationDTO = DummyData.RouteRegistrationDTOFaker.Generate();
            routeRegistrationDTO.OrderedShirt = true;
            routeRegistrationDTO.RouteId = route.Id;
            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);
            _routeRepository.GetBy(route.Id).ReturnsNull(); //!
            _validator.SetupPass();

            // Act 
            var numberOfRegistrations = user.Registrations.Count;
            var result = _sut.Post(routeRegistrationDTO);

            // Assert 
            result.Should().BeOfType<NotFoundObjectResult>();

            _userRepository.Received().GetBy(user.Email);
            _routeRepository.Received().GetBy(route.Id);

            user.Registrations.Count.Should().Be(numberOfRegistrations);
        }
        public void GetProfile_UserLoggedIn_FailsAndReturnsBadRequestResult()
        {
            // Arrange
            var user = DummyData.UserFaker.Generate();

            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).ReturnsNull();

            // Act
            var meResult = _sut.Get();

            // Assert
            meResult.Should().BeOfType <BadRequestObjectResult>();
        }
        public async Task DeleteProfile_UserNotFound_FailsAndReturnsBadRequestResult()
        {
            // Arrange
            var user = DummyData.UserFaker.Generate();

            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).ReturnsNull();

            // Act
            var result = await _sut.Delete();

            // Assert
            result.Should().BeOfType <BadRequestObjectResult>();
        }
        public void GetProfile_UserLoggedIn_ReceivesUser()
        {
            // Arrange
            var user = DummyData.UserFaker.Generate();

            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);

            // Act
            var meResult = _sut.Get();

            // Assert
            meResult.Should().BeOfType <OkObjectResult>();
            _userRepository.Received().GetBy(user.Email);
        }
        public async Task UpdateProfile_ValidationFailed_ShouldReturnBadRequest()
        {
            // Arrange
            var updateProfileDTO = DummyData.UpdateProfileDTOFaker.Generate();
            var user             = DummyData.UserFaker.Generate();

            _updateProfileValidator.SetupFail();

            _sut.ControllerContext = FakeControllerContext.For(user);

            // Act
            var result = await _sut.Update(updateProfileDTO);

            // Assert
            result.Should().BeOfType <BadRequestObjectResult>();
        }
        public void GetLast_NoRegistrations_ReturnsNotFound()
        {
            // Arrange 
            var user = DummyData.UserFaker.Generate();
            user.Registrations = new List<Registration>(); //empty

            _sut.ControllerContext = FakeControllerContext.For(user);

            _userRepository.GetBy(user.Email).Returns(user);
            _registrationRepository.GetLast(user.Email).ReturnsNull();

            //Act
            var result = _sut.GetLast();

            // Assert 
            result.Should().BeOfType<NotFoundObjectResult>();
        }
        public async Task DeleteProfile_ProfileDeleted_Succes()
        {
            // Arrange
            var user   = DummyData.UserFaker.Generate();
            var idUser = FakeAppUser.For(user);

            _um.FindByNameAsync(idUser.Email).Returns(idUser);
            _um.DeleteAsync(idUser).Returns(IdentityResult.Success);
            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);

            // Act
            var result = await _sut.Delete();

            // Assert
            result.Should().BeOfType <OkResult>();
            _userRepository.Received().Delete(user);
        }
        public async Task UpdateProfile_UserNotFound_ShouldReturnBadRequest()
        {
            // Arrange
            var updateProfileDTO = DummyData.UpdateProfileDTOFaker.Generate();
            var user             = DummyData.UserFaker.Generate();
            var appUser          = FakeAppUser.For(user);

            _um.FindByNameAsync(appUser.Email).Returns(appUser);
            _updateProfileValidator.SetupPass();
            _sut.ControllerContext = FakeControllerContext.For(user);

            _userRepository.GetBy(user.Email).ReturnsNull();

            // Act
            var result = await _sut.Update(updateProfileDTO);

            // Assert

            result.Should().BeOfType <BadRequestObjectResult>();
        }
        public void GetAll_AtLeastOneRegistration_ReturnsAllRegistrations()
        {
            // Arrange 
            var user = DummyData.UserFaker.Generate();

            _sut.ControllerContext = FakeControllerContext.For(user);

            _userRepository.GetBy(user.Email).Returns(user);
            _registrationRepository.GetAllFromUser(user.Email).Returns(user.Registrations);

            //Act
            var result = _sut.GetAllAsync();

            // Assert 
            result.Should().BeOfType<OkObjectResult>()
                .Which.Value.Should().BeEquivalentTo(
                    user.Registrations,
                    options => options.Using(new EnumAsStringAssertionRule()) //treat enums as strings
                );
        }
        public void CheckCurrentRegistered_LastRouteInPast_ReturnsFalse()
        {
            // Arrange 
            var user = DummyData.UserFaker.Generate();
            var registration = user.Registrations.Last();
            var route = new Route { Date = DateTime.Today.AddDays(-1), Id = registration.RouteId };

            _sut.ControllerContext = FakeControllerContext.For(user);
            _userRepository.GetBy(user.Email).Returns(user);
            _registrationRepository.GetLast(user.Email).Returns(registration);
            _routeRepository.GetBy(registration.RouteId).Returns(route);

            // Act 
            var result = _sut.CheckCurrentRegistered();

            // Assert 
            result.Should().BeOfType<OkObjectResult>().Which.Value.Should().Be(false);

            _userRepository.Received().GetBy(user.Email);
            _registrationRepository.Received().GetLast(user.Email);
            _routeRepository.Received().GetBy(registration.RouteId);
        }