public static async Task Does_not_send_emails_to_users_with_cancelled_requests()
        {
            var nextWorkingDate = 23.December(2020);

            var mockDateCalculator = new Mock <IDateCalculator>(MockBehavior.Strict);

            mockDateCalculator.Setup(c => c.GetNextWorkingDate()).Returns(nextWorkingDate);

            var mockEmailRepository = new Mock <IEmailRepository>();

            var requests = new[] { new Request("user1", nextWorkingDate, RequestStatus.Cancelled) };

            var mockRequestRepository = new Mock <IRequestRepository>(MockBehavior.Strict);

            mockRequestRepository
            .Setup(r => r.GetRequests(nextWorkingDate, nextWorkingDate))
            .ReturnsAsync(requests);

            var mockUserRepository = new Mock <IUserRepository>(MockBehavior.Strict);

            mockUserRepository.Setup(r => r.GetUsers()).ReturnsAsync(new List <User>());

            var dailyNotification = new DailyNotification(
                mockDateCalculator.Object,
                mockEmailRepository.Object,
                mockRequestRepository.Object,
                mockUserRepository.Object);

            await dailyNotification.Run();

            mockEmailRepository.VerifyNoOtherCalls();
        }
        public static void Body_contains_other_interrupted_user_count_when_interrupted()
        {
            var user      = CreateUser.With(userId: "user1", emailAddress: "*****@*****.**");
            var localDate = 1.April(2020);

            var requests = new[]
            {
                new Request(user.UserId, localDate, RequestStatus.Interrupted),
                new Request("user2", localDate, RequestStatus.Interrupted),
                new Request("user3", localDate, RequestStatus.SoftInterrupted),
                new Request("user4", localDate, RequestStatus.Allocated),
                new Request("user5", localDate, RequestStatus.Cancelled),
            };

            var template = new DailyNotification(requests, user, localDate);

            const string ExpectedPlainTextBody =
                "You have NOT been allocated a parking space for Wed 01 Apr.\r\n\r\n" +
                "If someone else cancels their request you may be allocated one later, but otherwise you can NOT park at the office.\r\n\r\n" +
                "Alternatively, if you make other arrangements TO COME IN to the office, you can choose to stay interrupted via the Summary page within the app.\r\n\r\n" +
                "There are currently 2 other people also waiting for a space.";
            const string ExpectedHtmlBody =
                "<p>You have <strong>not</strong> been allocated a parking space for Wed 01 Apr.</p>\r\n" +
                "<p>If someone else cancels their request you may be allocated one later, but otherwise you can <strong>not</strong> park at the office.</p>\r\n" +
                "<p>Alternatively, if you make other arrangements <strong>to come in</strong> to the office, you can choose to stay interrupted via the Summary page within the app.</p>\r\n" +
                "<p>There are currently 2 other people also waiting for a space.</p>";

            Assert.Equal(ExpectedPlainTextBody, template.PlainTextBody);
            Assert.Equal(ExpectedHtmlBody, template.HtmlBody);
        }
        public static void To_returns_email_address_of_corresponding_user(string emailAddress)
        {
            var template = new DailyNotification(
                new List <Request>(),
                CreateUser.With(userId: "user1", emailAddress: emailAddress),
                22.December(2020));

            Assert.Equal(emailAddress, template.To);
        }
        public static void ScheduledTaskType_returns_DailyNotification()
        {
            var dailyNotification = new DailyNotification(
                Mock.Of <IDateCalculator>(),
                Mock.Of <IEmailRepository>(),
                Mock.Of <IRequestRepository>(),
                Mock.Of <IUserRepository>());

            Assert.Equal(ScheduledTaskType.DailyNotification, dailyNotification.ScheduledTaskType);
        }
        public static void Subject_contains_request_status(RequestStatus requestStatus, string expectedSubject)
        {
            var user      = CreateUser.With(userId: "user1", emailAddress: "*****@*****.**");
            var localDate = 1.April(2020);

            var requests = new[] { new Request(user.UserId, localDate, requestStatus) };

            var template = new DailyNotification(requests, user, localDate);

            Assert.Equal(expectedSubject, template.Subject);
        }
        public static async Task Sends_emails_to_users_with_requests()
        {
            var nextWorkingDate = 23.December(2020);

            var mockDateCalculator = new Mock <IDateCalculator>(MockBehavior.Strict);

            mockDateCalculator.Setup(c => c.GetNextWorkingDate()).Returns(nextWorkingDate);

            var mockEmailRepository = new Mock <IEmailRepository>();

            var requests = new[]
            {
                new Request("user1", nextWorkingDate, RequestStatus.Allocated),
                new Request("user2", nextWorkingDate, RequestStatus.Interrupted)
            };

            var mockRequestRepository = new Mock <IRequestRepository>(MockBehavior.Strict);

            mockRequestRepository
            .Setup(r => r.GetRequests(nextWorkingDate, nextWorkingDate))
            .ReturnsAsync(requests);

            var users = new[]
            {
                CreateUser.With(userId: "user1", emailAddress: "*****@*****.**"),
                CreateUser.With(userId: "user2", emailAddress: "*****@*****.**")
            };

            var mockUserRepository = new Mock <IUserRepository>(MockBehavior.Strict);

            mockUserRepository.Setup(r => r.GetUsers()).ReturnsAsync(users);

            var dailyNotification = new DailyNotification(
                mockDateCalculator.Object,
                mockEmailRepository.Object,
                mockRequestRepository.Object,
                mockUserRepository.Object);

            await dailyNotification.Run();

            mockEmailRepository.Verify(
                r => r.Send(It.Is <IEmailTemplate>(e =>
                                                   e.To == "*****@*****.**" && e.Subject == "Parking status for Wed 23 Dec: Allocated")),
                Times.Once);
            mockEmailRepository.Verify(
                r => r.Send(It.Is <IEmailTemplate>(e =>
                                                   e.To == "*****@*****.**" && e.Subject == "Parking status for Wed 23 Dec: INTERRUPTED")),
                Times.Once);

            mockEmailRepository.VerifyNoOtherCalls();
        }
        public static void GetNextRunTime_uses_London_time_zone()
        {
            var dateCalculator = CreateDateCalculator(27.March(2020).At(11, 2, 0).Utc());

            var actual = new DailyNotification(
                dateCalculator,
                Mock.Of <IEmailRepository>(),
                Mock.Of <IRequestRepository>(),
                Mock.Of <IUserRepository>()).GetNextRunTime();

            var expected = 30.March(2020).At(10, 2, 0).Utc();

            Assert.Equal(expected, actual);
        }
        public static void Subject_contains_requests_date(int month, int day, string expectedSubject)
        {
            var user      = CreateUser.With(userId: "user1", emailAddress: "*****@*****.**");
            var localDate = new LocalDate(2020, month, day);

            var requests = new[] { new Request(user.UserId, localDate, RequestStatus.Allocated) };

            var template = new DailyNotification(
                requests,
                CreateUser.With(userId: "user1", emailAddress: "*****@*****.**"),
                localDate);

            Assert.Equal(expectedSubject, template.Subject);
        }
        public static void GetNextRunTime_returns_1102_am_on_next_working_day(int currentDay, int expectedNextDay)
        {
            var bankHolidays = new[] { 25.December(2020), 28.December(2020) };

            var dateCalculator = CreateDateCalculator(currentDay.December(2020).At(11, 2, 0).Utc(), bankHolidays);

            var actual = new DailyNotification(
                dateCalculator,
                Mock.Of <IEmailRepository>(),
                Mock.Of <IRequestRepository>(),
                Mock.Of <IUserRepository>()).GetNextRunTime();

            var expected = expectedNextDay.December(2020).At(11, 2, 0).Utc();

            Assert.Equal(expected, actual);
        }
        public static void Body_contains_request_status_when_allocated()
        {
            var user      = CreateUser.With(userId: "user1", emailAddress: "*****@*****.**");
            var localDate = 1.April(2020);

            var requests = new[] { new Request(user.UserId, localDate, RequestStatus.Allocated) };

            var template = new DailyNotification(requests, user, localDate);

            const string ExpectedPlainTextBody =
                "You have been allocated a parking space for Wed 01 Apr.\r\n\r\n" +
                "If you no longer need this space, please cancel your request so that it can be given to someone else.";
            const string ExpectedHtmlBody =
                "<p>You have been allocated a parking space for Wed 01 Apr.</p>\r\n" +
                "<p>If you no longer need this space, please cancel your request so that it can be given to someone else.</p>";

            Assert.Equal(ExpectedPlainTextBody, template.PlainTextBody);
            Assert.Equal(ExpectedHtmlBody, template.HtmlBody);
        }