public void Build_walk_price_divided_on_dog_price_per_walk_should_equal_dogs_count_in_pack(List <DogPack> dogPacks, ScheduleTimeBounds scheduleBounds)
        {
            // Arrange
            var payload = new WeeklySchedulePayloadBuilder()
                          .With(p => p.DogPacks = dogPacks)
                          .With(p => p.DateFrom = scheduleBounds.DateFrom)
                          .With(p => p.DateTo   = scheduleBounds.DateTo)
                          .With(p => p.Now      = scheduleBounds.Now)
                          .SetupWeekDays()
                          .Build();

            // Act
            var walks = _weeklyScheduleBuilder.Build(payload).ToList();

            // Assert
            var walksWithWrongTotal = walks.Where(NotValidPrice).ToList();

            Assert.AreEqual(0, walksWithWrongTotal.Count);

            bool NotValidPrice(Walk walk) =>
            (walk.Price / PriceForDogPerWalk(walk)) != walk.DogPack.Dogs.Count;

            decimal PriceForDogPerWalk(Walk walk) =>
            PriceRate(GetDogPackType(walk.DogPack)).PricePerWalk;

            PriceRate PriceRate((DogSize size, bool isAggressive) data) =>
            payload.PriceRates.Find(pr => pr.DogSize == data.size &&
                                    pr.IsAggressive == data.isAggressive);
        }
        public void Build_given_payload_should_schedule_9_walks()
        {
            // Arrange
            var payload = new WeeklySchedulePayloadBuilder()
                          .With(p => p.DogPacks = new List <DogPack> {
                new DogPack {
                    Dogs = new List <Dog> {
                        new Dog()
                        {
                            Size = DogSize.Large
                        }
                    }
                }
            })
                          .With(p => p.DateFrom     = new DateTime(2017, 10, 14))
                          .With(p => p.DateTo       = new DateTime(2017, 10, 21))
                          .With(p => p.WalkDuration = TimeSpan.FromHours(1))
                          .With(p => p.Now          = new DateTime(2017, 10, 16) + TimeSpan.FromHours(12))
                          .SetupWeekDays()
                          .Build();

            // Act
            var walks = _weeklyScheduleBuilder.Build(payload).ToList();

            // Assert
            Assert.AreEqual(9, walks.Count);
        }
        public void Build_should_get_no_walks_when_wrong_input()
        {
            var walks = _weeklyScheduleBuilder.Build(null);

            Assert.AreEqual(0, walks.Count(), "should get no walks when input is NULL");

            walks = _weeklyScheduleBuilder.Build(new WeekDaysSchedulePayload {
            });
            Assert.AreEqual(0, walks.Count(), "should get no walks when input is empty");

            var payloadWithNoDogPacks = new WeeklySchedulePayloadBuilder()
                                        .With(p => p.DogPacks = null)
                                        .Build();

            walks = _weeklyScheduleBuilder.Build(payloadWithNoDogPacks);
            Assert.AreEqual(0, walks.Count(), "should get no walks when no dog packs");

            var payloadWithNoPriceRates = new WeeklySchedulePayloadBuilder()
                                          .With(p => p.PriceRates = null)
                                          .Build();

            walks = _weeklyScheduleBuilder.Build(payloadWithNoPriceRates);
            Assert.AreEqual(0, walks.Count(), "should get no walks when no price rates");

            var payloadWithNoWorkingDays = new WeeklySchedulePayloadBuilder()
                                           .With(p => p.WorkingDays = null)
                                           .Build();

            walks = _weeklyScheduleBuilder.Build(payloadWithNoWorkingDays);
            Assert.AreEqual(0, walks.Count(), "should get no walks when no working days");
        }
        public void Build_the_walks_with_empty_dog_packs_shouldnt_be_scheduled(List <DogPack> dogPacks, ScheduleTimeBounds scheduleBounds)
        {
            // Arrange
            var payload = new WeeklySchedulePayloadBuilder()
                          .With(p => p.DogPacks = dogPacks)
                          .With(p => p.DateFrom = scheduleBounds.DateFrom)
                          .With(p => p.DateTo   = scheduleBounds.DateTo)
                          .With(p => p.Now      = scheduleBounds.Now)
                          .SetupWeekDays()
                          .Build();

            // Act
            var walks = _weeklyScheduleBuilder.Build(payload);

            // Assert
            var allWithDogs = walks.All(w => w.DogPack?.Dogs.Any() ?? false);

            Assert.True(allWithDogs);
        }
        public void Build_walking_datetime_should_be_between_given_DateFrom_and_DateTo(List <DogPack> dogPacks, ScheduleTimeBounds scheduleBounds)
        {
            // Arrange
            var payload = new WeeklySchedulePayloadBuilder()
                          .With(p => p.DogPacks = dogPacks)
                          .With(p => p.DateFrom = scheduleBounds.DateFrom)
                          .With(p => p.DateTo   = scheduleBounds.DateTo)
                          .With(p => p.Now      = scheduleBounds.Now)
                          .SetupWeekDays()
                          .Build();

            // Act
            var walks = _weeklyScheduleBuilder.Build(payload).ToList();

            // Assert
            var outOfTimeBoundsWalks = walks.Where(w =>
                                                   w.StartDateTime <payload.DateFrom &&
                                                                    w.StartDateTime> payload.DateTo).ToList();

            Assert.AreEqual(0, outOfTimeBoundsWalks.Count);
        }
        public void Build_walks_should_be_scheduled_at_given_days_and_time_only(List <DogPack> dogPacks, ScheduleTimeBounds scheduleBounds)
        {
            // Arrange
            var payload = new WeeklySchedulePayloadBuilder()
                          .With(p => p.DogPacks = dogPacks)
                          .With(p => p.DateFrom = scheduleBounds.DateFrom)
                          .With(p => p.DateTo   = scheduleBounds.DateTo)
                          .With(p => p.Now      = scheduleBounds.Now)
                          .SetupWeekDays()
                          .Build();

            // Act
            var walks = _weeklyScheduleBuilder.Build(payload);

            // Assert
            var isMatchWorkingHours = walks.All(w => IsMatchWorkingHours(w.StartDateTime));

            Assert.True(isMatchWorkingHours);

            bool IsMatchWorkingHours(DateTime walkingTime) =>
            payload.WorkingDays
            .FirstOrDefault(x => x.DayOfWeek == walkingTime.DayOfWeek)
            ?.WorkingHours.Any(wh => wh == walkingTime.TimeOfDay) ?? false;
        }