From 3e471ac783d91fcc61a90b759fecefe3b80014ba Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 18 Jun 2020 16:21:39 +0800 Subject: Add last modified info to timeline. --- Timeline.Tests/Services/TimelineServiceTest.cs | 87 ++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 Timeline.Tests/Services/TimelineServiceTest.cs (limited to 'Timeline.Tests/Services/TimelineServiceTest.cs') diff --git a/Timeline.Tests/Services/TimelineServiceTest.cs b/Timeline.Tests/Services/TimelineServiceTest.cs new file mode 100644 index 00000000..f7a94dfc --- /dev/null +++ b/Timeline.Tests/Services/TimelineServiceTest.cs @@ -0,0 +1,87 @@ +using Castle.Core.Logging; +using FluentAssertions; +using Microsoft.Extensions.Logging.Abstractions; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Timeline.Entities; +using Timeline.Services; +using Timeline.Tests.Helpers; +using Xunit; + +namespace Timeline.Tests.Services +{ + public class TimelineServiceTest : IAsyncLifetime + { + private TestDatabase _testDatabase = new TestDatabase(); + + private DatabaseContext _databaseContext; + + private readonly PasswordService _passwordService = new PasswordService(); + + private readonly ETagGenerator _eTagGenerator = new ETagGenerator(); + + private readonly ImageValidator _imageValidator = new ImageValidator(); + + private readonly TestClock _clock = new TestClock(); + + private DataManager _dataManager; + + private UserService _userService; + + private TimelineService _timelineService; + + public TimelineServiceTest() + { + } + + public async Task InitializeAsync() + { + await _testDatabase.InitializeAsync(); + _databaseContext = _testDatabase.CreateContext(); + _dataManager = new DataManager(_databaseContext, _eTagGenerator); + _userService = new UserService(NullLogger.Instance, _databaseContext, _passwordService); + _timelineService = new TimelineService(NullLogger.Instance, _databaseContext, _dataManager, _userService, _imageValidator, _clock); + } + + public async Task DisposeAsync() + { + await _testDatabase.DisposeAsync(); + } + + [Fact] + public async Task PersonalTimeline_LastModified() + { + var mockTime = new DateTime(2000, 1, 1, 1, 1, 1); + + _clock.SetCurrentTime(mockTime); + + var timeline = await _timelineService.GetTimeline("@user"); + + timeline.NameLastModified.Should().Be(mockTime); + timeline.LastModified.Should().Be(mockTime); + } + + [Fact] + public async Task OrdinaryTimeline_LastModified() + { + var mockTime = new DateTime(2000, 1, 1, 1, 1, 1); + + _clock.SetCurrentTime(mockTime); + + { + var timeline = await _timelineService.CreateTimeline("tl", await _userService.GetUserIdByUsername("user")); + + timeline.NameLastModified.Should().Be(mockTime); + timeline.LastModified.Should().Be(mockTime); + } + + { + var timeline = await _timelineService.GetTimeline("tl"); + timeline.NameLastModified.Should().Be(mockTime); + timeline.LastModified.Should().Be(mockTime); + } + } + } +} -- cgit v1.2.3 From 1eb71943ad8d4769cb6166a6f33c0eecea80fffe Mon Sep 17 00:00:00 2001 From: crupest Date: Thu, 18 Jun 2020 17:13:08 +0800 Subject: feat(back): Timeline service add last modified. --- Timeline.Tests/Helpers/TestClock.cs | 20 ++++++++++ Timeline.Tests/Services/TimelineServiceTest.cs | 53 ++++++++++++++----------- Timeline/Services/TimelineService.cs | 55 +++++++++++++++++++------- 3 files changed, 91 insertions(+), 37 deletions(-) (limited to 'Timeline.Tests/Services/TimelineServiceTest.cs') diff --git a/Timeline.Tests/Helpers/TestClock.cs b/Timeline.Tests/Helpers/TestClock.cs index 7febc0fe..de7d0eb7 100644 --- a/Timeline.Tests/Helpers/TestClock.cs +++ b/Timeline.Tests/Helpers/TestClock.cs @@ -19,5 +19,25 @@ namespace Timeline.Tests.Helpers { _currentTime = mockTime; } + + public DateTime SetMockCurrentTime() + { + var time = new DateTime(2000, 1, 1, 1, 1, 1); + _currentTime = time; + return time; + } + + public DateTime ForwardCurrentTime() + { + return ForwardCurrentTime(TimeSpan.FromDays(1)); + } + + public DateTime ForwardCurrentTime(TimeSpan timeSpan) + { + if (_currentTime == null) + return SetMockCurrentTime(); + _currentTime.Value.Add(timeSpan); + return _currentTime.Value; + } } } diff --git a/Timeline.Tests/Services/TimelineServiceTest.cs b/Timeline.Tests/Services/TimelineServiceTest.cs index f7a94dfc..cb2ade61 100644 --- a/Timeline.Tests/Services/TimelineServiceTest.cs +++ b/Timeline.Tests/Services/TimelineServiceTest.cs @@ -1,18 +1,20 @@ using Castle.Core.Logging; using FluentAssertions; +using FluentAssertions.Xml; using Microsoft.Extensions.Logging.Abstractions; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Timeline.Entities; +using Timeline.Models; using Timeline.Services; using Timeline.Tests.Helpers; using Xunit; namespace Timeline.Tests.Services { - public class TimelineServiceTest : IAsyncLifetime + public class TimelineServiceTest : IAsyncLifetime, IDisposable { private TestDatabase _testDatabase = new TestDatabase(); @@ -48,40 +50,45 @@ namespace Timeline.Tests.Services public async Task DisposeAsync() { await _testDatabase.DisposeAsync(); + await _databaseContext.DisposeAsync(); } - [Fact] - public async Task PersonalTimeline_LastModified() + public void Dispose() { - var mockTime = new DateTime(2000, 1, 1, 1, 1, 1); - - _clock.SetCurrentTime(mockTime); - - var timeline = await _timelineService.GetTimeline("@user"); - - timeline.NameLastModified.Should().Be(mockTime); - timeline.LastModified.Should().Be(mockTime); + _eTagGenerator.Dispose(); } - [Fact] - public async Task OrdinaryTimeline_LastModified() + [Theory] + [InlineData("@user")] + [InlineData("tl")] + public async Task Timeline_LastModified(string timelineName) { - var mockTime = new DateTime(2000, 1, 1, 1, 1, 1); - - _clock.SetCurrentTime(mockTime); + _clock.ForwardCurrentTime(); + void Check(Models.Timeline timeline) { - var timeline = await _timelineService.CreateTimeline("tl", await _userService.GetUserIdByUsername("user")); - - timeline.NameLastModified.Should().Be(mockTime); - timeline.LastModified.Should().Be(mockTime); + timeline.NameLastModified.Should().Be(_clock.GetCurrentTime()); + timeline.LastModified.Should().Be(_clock.GetCurrentTime()); } + async Task GetAndCheck() { - var timeline = await _timelineService.GetTimeline("tl"); - timeline.NameLastModified.Should().Be(mockTime); - timeline.LastModified.Should().Be(mockTime); + Check(await _timelineService.GetTimeline(timelineName)); } + + var _ = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); + if (!isPersonal) + Check(await _timelineService.CreateTimeline(timelineName, await _userService.GetUserIdByUsername("user"))); + + await GetAndCheck(); + + _clock.ForwardCurrentTime(); + await _timelineService.ChangeProperty(timelineName, new TimelineChangePropertyRequest { Visibility = TimelineVisibility.Public }); + await GetAndCheck(); + + _clock.ForwardCurrentTime(); + await _timelineService.ChangeMember(timelineName, new List { "admin" }, null); + await GetAndCheck(); } } } diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index ba5576d1..6c1e91c6 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -15,6 +15,23 @@ using static Timeline.Resources.Services.TimelineService; namespace Timeline.Services { + public static class TimelineHelper + { + public static string ExtractTimelineName(string name, out bool isPersonal) + { + if (name.StartsWith("@", StringComparison.OrdinalIgnoreCase)) + { + isPersonal = true; + return name.Substring(1); + } + else + { + isPersonal = false; + return name; + } + } + } + public enum TimelineUserRelationshipType { Own = 0b1, @@ -383,19 +400,7 @@ namespace Timeline.Services }; } - private static string ExtractTimelineName(string name, out bool isPersonal) - { - if (name.StartsWith("@", StringComparison.OrdinalIgnoreCase)) - { - isPersonal = true; - return name.Substring(1); - } - else - { - isPersonal = false; - return name; - } - } + // Get timeline id by name. If it is a personal timeline and it does not exist, it will be created. // @@ -407,7 +412,7 @@ namespace Timeline.Services // It follows all timeline-related function common interface contracts. private async Task FindTimelineId(string timelineName) { - timelineName = ExtractTimelineName(timelineName, out var isPersonal); + timelineName = TimelineHelper.ExtractTimelineName(timelineName, out var isPersonal); if (isPersonal) { @@ -713,16 +718,26 @@ namespace Timeline.Services var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); + var changed = false; + if (newProperties.Description != null) { + changed = true; timelineEntity.Description = newProperties.Description; } if (newProperties.Visibility.HasValue) { + changed = true; timelineEntity.Visibility = newProperties.Visibility.Value; } + if (changed) + { + var currentTime = _clock.GetCurrentTime(); + timelineEntity.LastModified = currentTime; + } + await _database.SaveChangesAsync(); } @@ -768,8 +783,17 @@ namespace Timeline.Services simplifiedAdd.Remove(u); simplifiedRemove.Remove(u); } + + if (simplifiedAdd.Count == 0) + simplifiedAdd = null; + + if (simplifiedRemove.Count == 0) + simplifiedRemove = null; } + if (simplifiedAdd == null && simplifiedRemove == null) + return; + var timelineId = await FindTimelineId(timelineName); async Task?> CheckExistenceAndGetId(List? list) @@ -799,6 +823,9 @@ namespace Timeline.Services _database.TimelineMembers.RemoveRange(membersToRemove); } + var timelineEntity = await _database.Timelines.Where(t => t.Id == timelineId).SingleAsync(); + timelineEntity.LastModified = _clock.GetCurrentTime(); + await _database.SaveChangesAsync(); } -- cgit v1.2.3