public async Task GetAttemptsAsync_GivenInvalidGoalId_ShouldReturnNotFound()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(new User());

            // Act.
            var result = await testObject.GetAttemptsAsync(123);

            // Assert.
            Assert.IsInstanceOf <NotFoundResult>(result);
        }
        public async Task DeleteLastAttemptAsync_GivenAnotherUsersGoal_ShouldReturnBadRequest()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);
            var currentUser  = new User {
                Id = 1
            };
            var otherUsersGoal = new Goal {
                UserId = 100
            };

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(currentUser);
            goalStore.GetGoalAsync(123).Returns(otherUsersGoal);

            // Act.
            var result = await testObject.DeleteLastAttemptAsync(123);

            // Assert.
            var notFoundResult = result as NotFoundResult;

            Assert.NotNull(notFoundResult);
        }
        public async Task DeleteLastAttemptAsync_GivenValidTokenButNoUser_ShouldReturnInternalServerError()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());

            // Act.
            var result = await testObject.DeleteLastAttemptAsync(123);

            // Assert.
            var serverErrorResult = result as InternalServerErrorResult;

            Assert.NotNull(serverErrorResult);
        }
        public async Task CreateAttemptAsync_GivenUnknownGoalId_ShouldReturnNotFound()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(new User());

            var attempt = new GoalAttemptData
            {
                GoalId = 123
            };

            // Act.
            var result = await testObject.CreateAttemptAsync(attempt);

            // Assert.
            var notFoundResult = result as NotFoundResult;

            Assert.NotNull(notFoundResult);
        }
        public async Task CreateAttemptAsync_GivenNoAuthToken_ShouldReturnBadRequest()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            var attempt = new GoalAttemptData
            {
                GoalId = 123
            };

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };

            // Act.
            var result = await testObject.CreateAttemptAsync(attempt);

            // Assert.
            var badRequestResult = result as BadRequestErrorMessageResult;

            Assert.NotNull(badRequestResult);
            Assert.AreEqual("No token provided.", badRequestResult.Message);
        }
        public async Task GetAttemptsAsync_GivenValidGoal_ShouldReturnAttempts()
        {
            // Arrange.
            MapperConfig.Initialise();

            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(new User());
            goalStore.GetGoalAsync(123).Returns(new Goal());

            var attempts = new List <GoalAttempt>
            {
                new GoalAttempt
                {
                    Id        = 1,
                    GoalId    = 123,
                    Timestamp = DateTime.Now
                },
                new GoalAttempt
                {
                    Id        = 2,
                    GoalId    = 123,
                    Timestamp = DateTime.Now
                }
            };

            attemptStore.GetAttempts(123).Returns(
                new MockDbAsyncEnumerable <GoalAttempt>(attempts));

            // Act.
            var result = await testObject.GetAttemptsAsync(123);

            // Assert.
            var okResult = result as OkNegotiatedContentResult <string>;

            Assert.NotNull(okResult);

            var attemptDatas = new List <GoalAttemptData>();

            attempts.ForEach(a => attemptDatas.Add(Mapper.Map <GoalAttemptData>(a)));

            Assert.AreEqual(JsonConvert.SerializeObject(attemptDatas), okResult.Content);
        }
        public async Task DeleteLastAttemptAsync_GivenValidAttempt_ShouldRemoveFromDb()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);
            var user         = new User {
                Id = 1
            };
            var goal = new Goal {
                UserId = 1
            };

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(user);
            goalStore.GetGoalAsync(Arg.Any <int>()).Returns(goal);

            attemptStore.GetAttempts(101).Returns(
                new MockDbAsyncEnumerable <GoalAttempt>(
                    new List <GoalAttempt>
            {
                new GoalAttempt
                {
                    Id        = 2,
                    Timestamp = new DateTime(2018, 1, 2),
                },
                new GoalAttempt
                {
                    Id        = 1,
                    Timestamp = new DateTime(2018, 1, 1)
                }
            }));

            // Act.
            var result = await testObject.DeleteLastAttemptAsync(101);

            // Assert.
            var okResult = result as OkResult;

            Assert.NotNull(okResult);

            await attemptStore.Received(0).RemoveAttemptAsync(1);

            await attemptStore.Received(1).RemoveAttemptAsync(2);
        }
        public async Task GetAttemptsAsync_GivenNoHeaderToken_ShouldReturnBadRequest()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);

            // Act.
            var result = await testObject.GetAttemptsAsync(123);

            // Assert.
            Assert.IsInstanceOf <BadRequestErrorMessageResult>(result);
        }
        public async Task CreateAttemptAsync_GivenValidAttempt_ShouldAddToDb()
        {
            // Arrange.
            var attemptStore = Substitute.For <IGoalAttemptStore>();
            var goalStore    = Substitute.For <IGoalStore>();
            var tokenStore   = Substitute.For <ITokenStore>();
            var userStore    = Substitute.For <IUserStore>();
            var log          = Substitute.For <ILogger>();
            var testObject   = new GoalAttemptController(attemptStore, goalStore, tokenStore, userStore, log);
            var user         = new User {
                Id = 1
            };
            var goal = new Goal {
                UserId = 1
            };

            testObject.ControllerContext = new HttpControllerContext
            {
                Request = new HttpRequestMessage()
            };
            testObject.ControllerContext.Request.Headers.Add("auth", Guid.NewGuid().ToString());

            tokenStore.GetExistingValidTokenByGuidAsync(Arg.Any <Guid>()).Returns(new Token());
            userStore.GetUserAsync(Arg.Any <Token>()).Returns(user);
            goalStore.GetGoalAsync(123).Returns(goal);

            var attempt = new GoalAttemptData
            {
                GoalId = 123
            };

            // Act.
            var result = await testObject.CreateAttemptAsync(attempt);

            // Assert.
            var statusResult = result as StatusCodeResult;

            Assert.NotNull(statusResult);
            Assert.AreEqual(HttpStatusCode.Created, statusResult.StatusCode);

            await attemptStore.Received(1).CreateAttemptAsync(123);
        }