コード例 #1
0
        public async void Should_combine_ajacent_deleted_ranges_into_a_single_entry()
        {
            // Set up
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime + TimeSpan.FromHours(1), ToTime = TestFromTime + TimeSpan.FromHours(2)
                    },
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime, ToTime = TestFromTime + TimeSpan.FromHours(1)
                    },
                }
            };

            // Act
            await _service.Update(Db, _poll.Id, req);

            // Assert
            Db.WasSaveChangesCalled.Should().BeTrue();

            var addedEntries = Db.Mock.TimeLogEntries.Added;

            addedEntries.Should().HaveCount(1);

            // First entry
            var entry0 = addedEntries[0];

            entry0.FromTime.Should().Be(TestFromTime);
            entry0.ToTime.Should().Be(TestFromTime + TimeSpan.FromHours(2));
        }
コード例 #2
0
        public void If_from_time_is_on_or_before_to_time_should_throw_and_not_save_any_deletions(int hoursLength)
        {
            // Set up
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange
                    {
                        FromTime = TestFromTime,
                        ToTime   = TestFromTime + TimeSpan.FromHours(1)
                    },
                    new TimeLogDeletedRange
                    {
                        FromTime = TestFromTime + TimeSpan.FromHours(3),
                        ToTime   = TestFromTime + TimeSpan.FromHours(3 + hoursLength)
                    },
                }
            };

            // Act
            Func <Task> action = async() => await _service.Update(Db, _poll.Id, req);

            // Assert
            action.Should().Throw <BadRequestException>()
            .WithMessage("*fromTime*")
            .WithMessage("*toTime*");

            Db.WasSaveChangesCalled.Should().BeFalse();
        }
コード例 #3
0
        public async void Truncate_from_and_to_times_to_preceding_minute()
        {
            // Set up
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange
                    {
                        FromTime = TestFromTime + TimeSpan.FromSeconds(5),
                        ToTime   = TestFromTime + TimeSpan.FromHours(1) + TimeSpan.FromSeconds(59)
                    },
                }
            };

            // Act
            await _service.Update(Db, _poll.Id, req);

            // Assert
            Db.WasSaveChangesCalled.Should().BeTrue();

            var addedEntries = Db.Mock.TimeLogEntries.Added;

            // First entry
            var entry0 = addedEntries[0];

            entry0.FromTime.Should().Be(TestFromTime);
            entry0.ToTime.Should().Be(TestFromTime + TimeSpan.FromHours(1));
        }
コード例 #4
0
        public void Should_not_save_deletions_if_there_are_errors_with_additions()
        {
            // Set up.
            // Valid deletion but an invalid addition.
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime, ToTime = TestFromTime + TimeSpan.FromHours(1)
                    },
                },
                Additions = new List <PollResponseAddRequest>
                {
                    new PollResponseAddRequest
                    {
                        TimeCollected   = TestFromTime,
                        TimeBlockLength = TimeSpan.FromHours(1),
                        ResponseText    = "", // This should fail
                        TimeZone        = "ABC",
                        TimeZoneOffset  = TimeSpan.FromHours(-2)
                    }
                }
            };

            // Act
            Func <Task> action = async() => await _service.Update(Db, _poll.Id, req);

            // Assert.
            action.Should().Throw <BadRequestException>(); // This is for a sanity check.
            Db.WasSaveChangesCalled.Should().BeFalse();
        }
コード例 #5
0
        public async Task <IActionResult> Update([FromBody] TimeLogUpdateRequest req)
        {
            var poll = await GetDefaultPollAsync();

            await _timeLogService.Update(Db, poll.Id, req);

            return(NoContent());
        }
コード例 #6
0
        public void Must_have_additions_or_deletions()
        {
            // Set up
            var req = new TimeLogUpdateRequest();

            // Act
            Func <Task> action = async() => await _service.Update(Db, _poll.Id, req);

            // Assert
            action.Should()
            .Throw <BadRequestException>()
            .WithMessage("*deletion*")
            .WithMessage("*addition*");
        }
コード例 #7
0
        public async void Should_insert_deletion_entry_for_every_range()
        {
            // Set up
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime, ToTime = TestFromTime + TimeSpan.FromHours(1)
                    },
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime + TimeSpan.FromHours(2), ToTime = TestFromTime + TimeSpan.FromHours(3)
                    },
                }
            };

            // Act
            await _service.Update(Db, _poll.Id, req);

            // Assert
            Db.WasSaveChangesCalled.Should().BeTrue();

            var addedEntries = Db.Mock.TimeLogEntries.Added;

            addedEntries.Should().HaveCount(2);

            var entry0 = addedEntries[0];

            entry0.IsDeletion.Should().Be(true);
            entry0.FromTime.Should().Be(TestFromTime + TimeSpan.FromHours(2));
            entry0.ToTime.Should().Be(TestFromTime + TimeSpan.FromHours(3));
            entry0.EntryText.Should().Be("[deletion]");

            // Second entry
            var entry1 = addedEntries[1];

            entry1.IsDeletion.Should().Be(true);
            entry1.FromTime.Should().Be(TestFromTime);
            entry1.ToTime.Should().Be(TestFromTime + TimeSpan.FromHours(1));
            entry1.EntryText.Should().Be("[deletion]");
        }
コード例 #8
0
        public async void Should_set_CreatedTimeUtc_to_one_msec_ago()
        {
            // Set up
            var req = new TimeLogUpdateRequest
            {
                Deletions = new List <TimeLogDeletedRange>
                {
                    new TimeLogDeletedRange {
                        FromTime = TestFromTime, ToTime = TestFromTime + TimeSpan.FromHours(1)
                    },
                }
            };

            // Act
            await _service.Update(Db, _poll.Id, req);

            // Assert
            var expectedCreatedTimeUtc = TestUtcNow - TimeSpan.FromMilliseconds(1);

            var addedEntries = Db.Mock.TimeLogEntries.Added;
            var entry0       = addedEntries[0];

            entry0.CreatedTimeUtc.Should().Be(expectedCreatedTimeUtc);
        }
コード例 #9
0
        public async Task Update(MainDbContext db, Guid pollId, TimeLogUpdateRequest req)
        {
            if ((req.Deletions == null || req.Deletions.Count == 0) &&
                (req.Additions == null || req.Additions.Count == 0))
            {
                throw new BadRequestException("Must provide additions or deletions.");
            }

            var createdTimeUtc = _timeService.UtcNow;

            // Process deletions.
            if (req.Deletions != null)
            {
                var sortedDeletions        = req.Deletions.OrderByDescending(d => d.ToTime).ToList();
                var deletionEntries        = new List <TimeLogEntry>(sortedDeletions.Count);
                var deletionCreatedTimeUtc = createdTimeUtc - TimeSpan.FromMilliseconds(1);

                TimeLogEntry currentEntry = null;

                for (var i = 0; i < sortedDeletions.Count; i++)
                {
                    var deletion = sortedDeletions[i];

                    // Adjust and validate time ranges.
                    var fromTime = ToStartOfMinute(deletion.FromTime);
                    var toTime   = ToStartOfMinute(deletion.ToTime);

                    if (fromTime >= toTime)
                    {
                        throw new BadRequestException(
                                  $"'fromTime' must be before 'toTime' after truncating to the start of minute. " +
                                  $"In deletion at position {i + 1} found 'fromTime': '{fromTime}', " +
                                  $"'toTime': {toTime}.");
                    }

                    // See if we need to extend the range or start a new one.
                    // We don't need to compare fromTime or currentEntry.ToTime because
                    // the entries are sorted by toTime desc.
                    if (currentEntry != null && toTime >= currentEntry.FromTime)
                    {
                        // The entries overlap. Combine them into a single entry.
                        currentEntry.FromTime = fromTime;
                    }
                    else
                    {
                        // Need to start a new entry.
                        if (currentEntry != null)
                        {
                            db.TimeLogEntries.Add(currentEntry);
                        }

                        currentEntry = new TimeLogEntry
                        {
                            Id             = Guid.NewGuid(),
                            FromTime       = fromTime,
                            ToTime         = toTime,
                            EntryText      = "[deletion]",
                            TimeZone       = deletion.TimeZone,
                            TimeZoneOffset = deletion.TimeZoneOffset,
                            CreatedTimeUtc = deletionCreatedTimeUtc,
                            IsDeletion     = true,
                            PollId         = pollId,
                        };
                    }
                }

                // Save the last deletion.
                if (currentEntry != null)
                {
                    db.TimeLogEntries.Add(currentEntry);
                }
            }

            // Process additions.
            if (req.Additions != null)
            {
                for (int i = 0; i < req.Additions.Count; i++)
                {
                    var additionReq = req.Additions[i];
                    ValidatePollResponseAddRequest(additionReq, i);

                    // Round down to the nearest minute.
                    var savedFromTime = ToStartOfMinute(additionReq.TimeCollected);

                    var newEntry = new TimeLogEntry
                    {
                        Id             = Guid.NewGuid(),
                        PollId         = pollId,
                        FromTime       = savedFromTime,
                        ToTime         = savedFromTime + additionReq.TimeBlockLength,
                        EntryText      = additionReq.ResponseText,
                        CreatedTimeUtc = createdTimeUtc,
                        TimeZone       = additionReq.TimeZone,
                        TimeZoneOffset = additionReq.TimeZoneOffset,
                        SubmissionType = additionReq.SubmissionType,
                    };

                    db.TimeLogEntries.Add(newEntry);
                }
            }

            await db.SaveChangesAsync();
        }
コード例 #10
0
 public Task Update(MainDbContext db, Guid pollId, TimeLogUpdateRequest req)
 {
     throw new NotImplementedException();
 }