diff options
-rw-r--r-- | Timeline.ErrorCodes/ErrorCodes.cs | 9 | ||||
-rw-r--r-- | Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs | 533 | ||||
-rw-r--r-- | Timeline.Tests/IntegratedTests/TimelineTest.cs | 308 | ||||
-rw-r--r-- | Timeline/Controllers/TimelineController.cs | 4 | ||||
-rw-r--r-- | Timeline/Filters/Timeline.cs | 2 | ||||
-rw-r--r-- | Timeline/Models/Http/ErrorResponse.cs | 29 | ||||
-rw-r--r-- | Timeline/Resources/Messages.Designer.cs | 51 | ||||
-rw-r--r-- | Timeline/Resources/Messages.resx | 21 | ||||
-rw-r--r-- | Timeline/Services/TimelineService.cs | 14 |
9 files changed, 270 insertions, 701 deletions
diff --git a/Timeline.ErrorCodes/ErrorCodes.cs b/Timeline.ErrorCodes/ErrorCodes.cs index eca0e18b..ef150921 100644 --- a/Timeline.ErrorCodes/ErrorCodes.cs +++ b/Timeline.ErrorCodes/ErrorCodes.cs @@ -56,16 +56,13 @@ public const int BadFormat_BadSize = 1_103_00_03;
}
- public static class TimelineCommon
+ public static class TimelineController
{
public const int NameConflict = 1_104_01_01;
public const int NotExist = 1_104_02_01;
public const int MemberPut_NotExist = 1_104_03_01;
- }
-
- public static class TimelineController
- {
- public const int QueryRelateNotExist = 1_105_01_01;
+ public const int QueryRelateNotExist = 1_104_04_01;
+ public const int PostNoData = 1_104_05_01;
}
}
}
diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs deleted file mode 100644 index aa37e898..00000000 --- a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs +++ /dev/null @@ -1,533 +0,0 @@ -using FluentAssertions; -using Microsoft.AspNetCore.Mvc.Testing; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net.Http; -using System.Threading.Tasks; -using Timeline.Models;
-using Timeline.Models.Http; -using Timeline.Tests.Helpers; -using Xunit; - -namespace Timeline.Tests.IntegratedTests -{ - public class PersonalTimelineTest : IntegratedTestBase - { - public PersonalTimelineTest(WebApplicationFactory<Startup> factory) - : base(factory, 3) - { - - } - - [Fact] - public async Task TimelineGet_Should_Work() - { - using var client = await CreateDefaultClient(); - var res = await client.GetAsync("timelines/@user1"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>().Which; - body.Owner.Should().BeEquivalentTo(UserInfos[1]); - body.Visibility.Should().Be(TimelineVisibility.Register); - body.Description.Should().Be(""); - body.Members.Should().NotBeNull().And.BeEmpty(); - }
-
- [Fact] - public async Task InvalidModel_BadUsername() - { - using var client = await CreateClientAsAdministrator(); - {
- var res = await client.GetAsync("timelines/@user!!!"); - res.Should().BeInvalidModel();
- }
- {
- var res = await client.PatchAsJsonAsync("timelines/@user!!!", new TimelinePatchRequest { }); - res.Should().BeInvalidModel();
- }
- {
- var res = await client.PutAsync("timelines/@user!!!/members/user1", null); - res.Should().BeInvalidModel();
- }
- {
- var res = await client.DeleteAsync("timelines/@user!!!/members/user1"); - res.Should().BeInvalidModel();
- }
- {
- var res = await client.GetAsync("timelines/@user!!!/posts"); - res.Should().BeInvalidModel();
- }
- {
- var res = await client.PostAsJsonAsync("timelines/@user!!!/posts", TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().BeInvalidModel();
- } - {
- var res = await client.DeleteAsync("timelines/@user!!!/posts/123");
- res.Should().BeInvalidModel();
- } - }
-
- [Fact] - public async Task NotFound() - { - using var client = await CreateClientAsAdministrator(); - {
- var res = await client.GetAsync("timelines/@usernotexist"); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- }
- {
- var res = await client.PatchAsJsonAsync("timelines/@usernotexist", new TimelinePatchRequest { }); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- }
- {
- var res = await client.PutAsync("timelines/@usernotexist/members/user1", null); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- }
- {
- var res = await client.DeleteAsync("timelines/@usernotexist/members/user1"); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- }
- {
- var res = await client.GetAsync("timelines/@usernotexist/posts"); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- }
- {
- var res = await client.PostAsJsonAsync("timelines/@usernotexist/posts", TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- } - {
- var res = await client.DeleteAsync("timelines/@usernotexist/posts/123");
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
- } - } - - [Fact] - public async Task Description_Should_Work() - { - using var client = await CreateClientAsUser(); - - async Task AssertDescription(string description) - { - var res = await client.GetAsync("timelines/@user1"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>() - .Which.Description.Should().Be(description); - } - - const string mockDescription = "haha"; - - await AssertDescription(""); - { - var res = await client.PatchAsJsonAsync("timelines/@user1", - new TimelinePatchRequest { Description = mockDescription }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be(mockDescription); - await AssertDescription(mockDescription); - } - { - var res = await client.PatchAsJsonAsync("timelines/@user1", - new TimelinePatchRequest { Description = null }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be(mockDescription); - await AssertDescription(mockDescription); - } - { - var res = await client.PatchAsJsonAsync("timelines/@user1", - new TimelinePatchRequest { Description = "" }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be(""); - await AssertDescription(""); - } - } - - [Fact] - public async Task Member_Should_Work() - { - const string getUrl = "timelines/@user1"; - using var client = await CreateClientAsUser(); - - async Task AssertMembers(IList<UserInfo> members) - { - var res = await client.GetAsync(getUrl); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>() - .Which.Members.Should().NotBeNull().And.BeEquivalentTo(members); - } - - async Task AssertEmptyMembers() - { - var res = await client.GetAsync(getUrl); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelineInfo>() - .Which.Members.Should().NotBeNull().And.BeEmpty(); - } - - await AssertEmptyMembers(); - { - var res = await client.PutAsync("/timelines/@user1/members/usernotexist", null); - res.Should().HaveStatusCode(400) - .And.HaveCommonBody(ErrorCodes.TimelineCommon.MemberPut_NotExist); - } - await AssertEmptyMembers(); - { - var res = await client.PutAsync("/timelines/@user1/members/user2", null); - res.Should().HaveStatusCode(200); - } - await AssertMembers(new List<UserInfo> { UserInfos[2] }); - { - var res = await client.DeleteAsync("/timelines/@user1/members/user2"); - res.Should().BeDelete(true); - }
- await AssertEmptyMembers(); - { - var res = await client.DeleteAsync("/timelines/@user1/members/users2"); - res.Should().BeDelete(false); - } - await AssertEmptyMembers(); - } - - [Theory] - [InlineData(-1, 200, 401, 401, 401, 401)] - [InlineData(1, 200, 200, 403, 200, 403)] - [InlineData(0, 200, 200, 200, 200, 200)] - public async Task Permission_Timeline(int userNumber, int get, int opPatchUser, int opPatchAdmin, int opMemberUser, int opMemberAdmin) - { - using var client = await CreateClientAs(userNumber); - { - var res = await client.GetAsync("timelines/@user1"); - res.Should().HaveStatusCode(get); - } - - { - var res = await client.PatchAsJsonAsync("timelines/@user1", new TimelinePatchRequest { Description = "hahaha" }); - res.Should().HaveStatusCode(opPatchUser); - } - - { - var res = await client.PatchAsJsonAsync("timelines/@admin", new TimelinePatchRequest { Description = "hahaha" }); - res.Should().HaveStatusCode(opPatchAdmin); - } - - { - var res = await client.PutAsync("timelines/@user1/members/user2", null); - res.Should().HaveStatusCode(opMemberUser); - }
-
- { - var res = await client.DeleteAsync("timelines/@user1/members/user2"); - res.Should().HaveStatusCode(opMemberUser); - } - - { - var res = await client.PutAsync("timelines/@admin/members/user2", null); - res.Should().HaveStatusCode(opMemberAdmin); - }
-
- { - var res = await client.DeleteAsync("timelines/@admin/members/user2"); - res.Should().HaveStatusCode(opMemberAdmin); - } - } - - [Fact] - public async Task Visibility_Test() - { - const string userUrl = "timelines/@user1/posts"; - const string adminUrl = "timelines/@admin/posts"; - {
-
- using var client = await CreateClientAsUser(); - using var content = new StringContent(@"{""visibility"":""abcdefg""}", System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json); - var res = await client.PatchAsync("timelines/@user1", content); - res.Should().BeInvalidModel(); - } - { // default visibility is registered - { - using var client = await CreateDefaultClient(); - var res = await client.GetAsync(userUrl); - res.Should().HaveStatusCode(403); - } - - { - using var client = await CreateClientAsUser(); - var res = await client.GetAsync(adminUrl); - res.Should().HaveStatusCode(200); - } - } - - { // change visibility to public - { - using var client = await CreateClientAsUser(); - var res = await client.PatchAsJsonAsync("timelines/@user1", - new TimelinePatchRequest { Visibility = TimelineVisibility.Public }); - res.Should().HaveStatusCode(200); - } - { - using var client = await CreateDefaultClient(); - var res = await client.GetAsync(userUrl); - res.Should().HaveStatusCode(200); - } - } - - { // change visibility to private - { - using var client = await CreateClientAsAdministrator(); - { - var res = await client.PatchAsJsonAsync("timelines/@user1", - new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); - res.Should().HaveStatusCode(200); - } - { - var res = await client.PatchAsJsonAsync("timelines/@admin", - new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); - res.Should().HaveStatusCode(200); - } - } - { - using var client = await CreateDefaultClient(); - var res = await client.GetAsync(userUrl); - res.Should().HaveStatusCode(403); - } - { // user can't read admin's - using var client = await CreateClientAsUser(); - var res = await client.GetAsync(adminUrl); - res.Should().HaveStatusCode(403); - } - { // admin can read user's - using var client = await CreateClientAsAdministrator(); - var res = await client.GetAsync(userUrl); - res.Should().HaveStatusCode(200); - } - { // add member - using var client = await CreateClientAsAdministrator(); - var res = await client.PutAsync("/timelines/@admin/members/user1", null); - res.Should().HaveStatusCode(200); - } - { // now user can read admin's - using var client = await CreateClientAsUser(); - var res = await client.GetAsync(adminUrl); - res.Should().HaveStatusCode(200); - } - } - } - - - [Fact] - public async Task Permission_Post_Create() - { - using (var client = await CreateClientAsUser()) - { - var res = await client.PutAsync("timelines/@user1/members/user2", null); - res.Should().HaveStatusCode(200); - } - - using (var client = await CreateDefaultClient()) - { - { // no auth should get 401 - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(401); - } - } - - using (var client = await CreateClientAsUser()) - { - { // post self's - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(200); - } - { // post other not as a member should get 403 - var res = await client.PostAsJsonAsync("timelines/@admin/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(403); - } - } - - using (var client = await CreateClientAsAdministrator()) - { - { // post as admin - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(200); - } - } - - using (var client = await CreateClientAs(2)) - { - { // post as member - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(200); - } - } - } - - [Fact] - public async Task Permission_Post_Delete() - { - async Task<long> CreatePost(int userNumber) - { - using var client = await CreateClientAs(userNumber); - var res = await client.PostAsJsonAsync($"timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa")); - return res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo>() - .Which.Id; - } - - using (var client = await CreateClientAsUser()) - { - {
- var res = await client.PutAsync("timelines/@user1/members/user2", null);
- res.Should().HaveStatusCode(200); - }
- {
- var res = await client.PutAsync("timelines/@user1/members/user3", null);
- res.Should().HaveStatusCode(200); - } - } - - { // no auth should get 401 - using var client = await CreateDefaultClient(); - var res = await client.DeleteAsync("timelines/@user1/posts/12"); - res.Should().HaveStatusCode(401); - } - - { // self can delete self - var postId = await CreatePost(1); - using var client = await CreateClientAsUser(); - var res = await client.DeleteAsync($"timelines/@user1/posts/{postId}"); - res.Should().HaveStatusCode(200); - } - - { // admin can delete any - var postId = await CreatePost(1); - using var client = await CreateClientAsAdministrator(); - var res = await client.DeleteAsync($"timelines/@user1/posts/{postId}"); - res.Should().HaveStatusCode(200); - } - - { // owner can delete other - var postId = await CreatePost(2); - using var client = await CreateClientAsUser(); - var res = await client.DeleteAsync($"timelines/@user1/posts/{postId}"); - res.Should().HaveStatusCode(200); - } - - { // author can delete self - var postId = await CreatePost(2); - using var client = await CreateClientAs(2); - var res = await client.DeleteAsync($"timelines/@user1/posts/{postId}"); - res.Should().HaveStatusCode(200); - } - - { // otherwise is forbidden - var postId = await CreatePost(2); - using var client = await CreateClientAs(3); - var res = await client.DeleteAsync($"timelines/@user1/posts/{postId}"); - res.Should().HaveStatusCode(403); - } - } - - [Fact] - public async Task Post_Op_Should_Work() - { - { - using var client = await CreateClientAsUser(); - { - var res = await client.GetAsync("timelines/@user1/posts"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEmpty(); - } - { - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest(null)); - res.Should().BeInvalidModel(); - } - const string mockContent = "aaa"; - TimelinePostInfo createRes; - { - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest(mockContent)); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo>() - .Which; - body.Should().NotBeNull(); - body.Content.Should().BeEquivalentTo(TimelineHelper.TextPostContent(mockContent)); - body.Author.Should().BeEquivalentTo(UserInfos[1]); - createRes = body; - } - { - var res = await client.GetAsync("timelines/@user1/posts"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo(createRes); - } - const string mockContent2 = "bbb"; - var mockTime2 = DateTime.Now.AddDays(-1); - TimelinePostInfo createRes2; - { - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest(mockContent2, mockTime2)); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo>() - .Which; - body.Should().NotBeNull();
- body.Content.Should().BeEquivalentTo(TimelineHelper.TextPostContent(mockContent2)); - body.Author.Should().BeEquivalentTo(UserInfos[1]); - body.Time.Should().BeCloseTo(mockTime2, 1000); - createRes2 = body; - } - { - var res = await client.GetAsync("timelines/@user1/posts"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo(createRes, createRes2); - } - { - var res = await client.DeleteAsync($"timelines/@user1/posts/{createRes.Id}"); - res.Should().BeDelete(true); - } - { - var res = await client.DeleteAsync("timelines/@user1/posts/30000"); - res.Should().BeDelete(false); - } - { - var res = await client.GetAsync("timelines/@user1/posts"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Should().NotBeNull().And.BeEquivalentTo(createRes2); - } - } - } - - [Fact] - public async Task GetPost_Should_Ordered() - { - using var client = await CreateClientAsUser(); - - async Task<long> CreatePost(DateTime time) - { - var res = await client.PostAsJsonAsync("timelines/@user1/posts", - TimelineHelper.TextPostCreateRequest("aaa", time)); - return res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo>() - .Which.Id; - } - - var now = DateTime.Now; - var id0 = await CreatePost(now.AddDays(1)); - var id1 = await CreatePost(now.AddDays(-1)); - var id2 = await CreatePost(now); - - { - var res = await client.GetAsync("timelines/@user1/posts"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody<TimelinePostInfo[]>() - .Which.Select(p => p.Id).Should().Equal(id1, id2, id0); - } - } - } -} diff --git a/Timeline.Tests/IntegratedTests/TimelineTest.cs b/Timeline.Tests/IntegratedTests/TimelineTest.cs index 720140f1..7206c675 100644 --- a/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -43,7 +43,7 @@ namespace Timeline.Tests.IntegratedTests public TimelineTest(WebApplicationFactory<Startup> factory)
: base(factory, 3)
{
-
+ CreateTestTimelines().Wait();
}
private List<TimelineInfo> _testTimelines;
@@ -61,11 +61,38 @@ namespace Timeline.Tests.IntegratedTests }
}
+ private static string GeneratePersonalTimelineUrl(int id, string subpath = null)
+ {
+ return $"timelines/@{(id == 0 ? "admin" : ("user" + id))}{(subpath == null ? "" : ("/" + subpath))}";
+ }
+
+ private static string GenerateOrdinaryTimelineUrl(int id, string subpath = null)
+ {
+ return $"timelines/t{id}{(subpath == null ? "" : ("/" + subpath))}";
+ }
+
+ public static IEnumerable<object[]> TimelineUrlGeneratorData()
+ {
+ yield return new[] { new Func<int, string, string>(GeneratePersonalTimelineUrl) };
+ yield return new[] { new Func<int, string, string>(GenerateOrdinaryTimelineUrl) };
+ }
+
[Fact]
- public async Task TimelineList()
+ public async Task Personal_TimelineGet_Should_Work()
{
- await CreateTestTimelines();
+ using var client = await CreateDefaultClient();
+ var res = await client.GetAsync("timelines/@user1");
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelineInfo>().Which;
+ body.Owner.Should().BeEquivalentTo(UserInfos[1]);
+ body.Visibility.Should().Be(TimelineVisibility.Register);
+ body.Description.Should().Be("");
+ body.Members.Should().NotBeNull().And.BeEmpty();
+ }
+ [Fact]
+ public async Task TimelineList()
+ {
TimelineInfo user1Timeline;
var client = await CreateDefaultClient();
@@ -91,8 +118,6 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task TimelineList_WithQuery()
{
- await CreateTestTimelines();
-
var testResultRelate = new List<TimelineInfo>();
var testResultOwn = new List<TimelineInfo>();
var testResultJoin = new List<TimelineInfo>();
@@ -336,7 +361,7 @@ namespace Timeline.Tests.IntegratedTests {
var res = await client.PostAsJsonAsync("timelines", new TimelineCreateRequest { Name = "aaa" });
res.Should().HaveStatusCode(400)
- .And.HaveCommonBody(ErrorCodes.TimelineCommon.NameConflict);
+ .And.HaveCommonBody(ErrorCodes.TimelineController.NameConflict);
}
}
}
@@ -344,8 +369,6 @@ namespace Timeline.Tests.IntegratedTests [Fact]
public async Task TimelineDelete_Should_Work()
{
- await CreateTestTimelines();
-
{
using var client = await CreateDefaultClient();
var res = await client.DeleteAsync("timelines/t1");
@@ -398,7 +421,7 @@ namespace Timeline.Tests.IntegratedTests }
[Fact]
- public async Task InvalidModel_BadName()
+ public async Task Ordinary_InvalidModel_BadName()
{
using var client = await CreateClientAsAdministrator();
{
@@ -432,49 +455,117 @@ namespace Timeline.Tests.IntegratedTests }
[Fact]
- public async Task NotFound()
+ public async Task Personal_InvalidModel_BadUsername()
+ {
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.GetAsync("timelines/@user!!!");
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PatchAsJsonAsync("timelines/@user!!!", new TimelinePatchRequest { });
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PutAsync("timelines/@user!!!/members/user1", null);
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.DeleteAsync("timelines/@user!!!/members/user1");
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.GetAsync("timelines/@user!!!/posts");
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.PostAsJsonAsync("timelines/@user!!!/posts", TimelineHelper.TextPostCreateRequest("aaa"));
+ res.Should().BeInvalidModel();
+ }
+ {
+ var res = await client.DeleteAsync("timelines/@user!!!/posts/123");
+ res.Should().BeInvalidModel();
+ }
+ }
+
+ [Fact]
+ public async Task Ordinary_NotFound()
{
using var client = await CreateClientAsAdministrator();
{
var res = await client.GetAsync("timelines/notexist");
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.PatchAsJsonAsync("timelines/notexist", new TimelinePatchRequest { });
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.PutAsync("timelines/notexist/members/user1", null);
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.DeleteAsync("timelines/notexist/members/user1");
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.GetAsync("timelines/notexist/posts");
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.PostAsJsonAsync("timelines/notexist/posts", TimelineHelper.TextPostCreateRequest("aaa"));
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
{
var res = await client.DeleteAsync("timelines/notexist/posts/123");
- res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineCommon.NotExist);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.TimelineController.NotExist);
}
}
+
[Fact]
- public async Task Description_Should_Work()
+ public async Task PersonalNotFound()
{
- await CreateTestTimelines();
+ using var client = await CreateClientAsAdministrator();
+ {
+ var res = await client.GetAsync("timelines/@usernotexist");
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PatchAsJsonAsync("timelines/@usernotexist", new TimelinePatchRequest { });
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PutAsync("timelines/@usernotexist/members/user1", null);
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.DeleteAsync("timelines/@usernotexist/members/user1");
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.GetAsync("timelines/@usernotexist/posts");
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.PostAsJsonAsync("timelines/@usernotexist/posts", TimelineHelper.TextPostCreateRequest("aaa"));
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ {
+ var res = await client.DeleteAsync("timelines/@usernotexist/posts/123");
+ res.Should().HaveStatusCode(404).And.HaveCommonBody(ErrorCodes.UserCommon.NotExist);
+ }
+ }
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Description_Should_Work(Func<int, string, string> generator)
+ {
using var client = await CreateClientAsUser();
async Task AssertDescription(string description)
{
- var res = await client.GetAsync("timelines/t1");
+ var res = await client.GetAsync(generator(1, null));
var body = res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelineInfo>()
.Which.Description.Should().Be(description);
@@ -484,21 +575,21 @@ namespace Timeline.Tests.IntegratedTests await AssertDescription("");
{
- var res = await client.PatchAsJsonAsync("timelines/t1",
+ var res = await client.PatchAsJsonAsync(generator(1, null),
new TimelinePatchRequest { Description = mockDescription });
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be(mockDescription);
await AssertDescription(mockDescription);
}
{
- var res = await client.PatchAsJsonAsync("timelines/t1",
+ var res = await client.PatchAsJsonAsync(generator(1, null),
new TimelinePatchRequest { Description = null });
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be(mockDescription);
await AssertDescription(mockDescription);
}
{
- var res = await client.PatchAsJsonAsync("timelines/t1",
+ var res = await client.PatchAsJsonAsync(generator(1, null),
new TimelinePatchRequest { Description = "" });
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelineInfo>().Which.Description.Should().Be("");
@@ -506,12 +597,11 @@ namespace Timeline.Tests.IntegratedTests }
}
- [Fact]
- public async Task Member_Should_Work()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Member_Should_Work(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
- const string getUrl = "timelines/t1";
+ var getUrl = generator(1, null);
using var client = await CreateClientAsUser();
async Task AssertMembers(IList<UserInfo> members)
@@ -532,35 +622,40 @@ namespace Timeline.Tests.IntegratedTests await AssertEmptyMembers();
{
- var res = await client.PutAsync("/timelines/t1/members/usernotexist", null);
+ var res = await client.PutAsync(generator(1, "members/usernotexist"), null);
res.Should().HaveStatusCode(400)
- .And.HaveCommonBody(ErrorCodes.TimelineCommon.MemberPut_NotExist);
+ .And.HaveCommonBody(ErrorCodes.TimelineController.MemberPut_NotExist);
}
await AssertEmptyMembers();
{
- var res = await client.PutAsync("/timelines/t1/members/user2", null);
+ var res = await client.PutAsync(generator(1, "members/user2"), null);
res.Should().HaveStatusCode(200);
}
await AssertMembers(new List<UserInfo> { UserInfos[2] });
{
- var res = await client.DeleteAsync("/timelines/t1/members/user2");
+ var res = await client.DeleteAsync(generator(1, "members/user2"));
res.Should().BeDelete(true);
}
await AssertEmptyMembers();
{
- var res = await client.DeleteAsync("/timelines/t1/members/users2");
+ var res = await client.DeleteAsync(generator(1, "members/aaa"));
res.Should().BeDelete(false);
}
await AssertEmptyMembers();
}
[Theory]
- [InlineData(-1, 200, 401, 401, 401, 401)]
- [InlineData(1, 200, 200, 403, 200, 403)]
- [InlineData(0, 200, 200, 200, 200, 200)]
- public async Task Permission_Timeline(int userNumber, int get, int opPatchUser, int opPatchAdmin, int opMemberUser, int opMemberAdmin)
+ [InlineData(nameof(GenerateOrdinaryTimelineUrl), -1, 200, 401, 401, 401, 401)]
+ [InlineData(nameof(GenerateOrdinaryTimelineUrl), 1, 200, 200, 403, 200, 403)]
+ [InlineData(nameof(GenerateOrdinaryTimelineUrl), 0, 200, 200, 200, 200, 200)]
+ [InlineData(nameof(GeneratePersonalTimelineUrl), -1, 200, 401, 401, 401, 401)]
+ [InlineData(nameof(GeneratePersonalTimelineUrl), 1, 200, 200, 403, 200, 403)]
+ [InlineData(nameof(GeneratePersonalTimelineUrl), 0, 200, 200, 200, 200, 200)]
+
+ public async Task Permission_Timeline(string generatorName, int userNumber, int get, int opPatchUser, int opPatchAdmin, int opMemberUser, int opMemberAdmin)
{
- await CreateTestTimelines();
+ var method = GetType().GetMethod(generatorName, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+ Func<int, string, string> generator = (int id, string subpath) => (string)method.Invoke(null, new object[] { id, subpath });
using var client = await CreateClientAs(userNumber);
{
@@ -569,48 +664,47 @@ namespace Timeline.Tests.IntegratedTests }
{
- var res = await client.PatchAsJsonAsync("timelines/t1", new TimelinePatchRequest { Description = "hahaha" });
+ var res = await client.PatchAsJsonAsync(generator(1, null), new TimelinePatchRequest { Description = "hahaha" });
res.Should().HaveStatusCode(opPatchUser);
}
{
- var res = await client.PatchAsJsonAsync("timelines/t0", new TimelinePatchRequest { Description = "hahaha" });
+ var res = await client.PatchAsJsonAsync(generator(0, null), new TimelinePatchRequest { Description = "hahaha" });
res.Should().HaveStatusCode(opPatchAdmin);
}
{
- var res = await client.PutAsync("timelines/t1/members/user2", null);
+ var res = await client.PutAsync(generator(1, "members/user2"), null);
res.Should().HaveStatusCode(opMemberUser);
}
{
- var res = await client.DeleteAsync("timelines/t1/members/user2");
+ var res = await client.DeleteAsync(generator(1, "members/user2"));
res.Should().HaveStatusCode(opMemberUser);
}
{
- var res = await client.PutAsync("timelines/t0/members/user2", null);
+ var res = await client.PutAsync(generator(0, "members/user2"), null);
res.Should().HaveStatusCode(opMemberAdmin);
}
{
- var res = await client.DeleteAsync("timelines/t0/members/user2");
+ var res = await client.DeleteAsync(generator(0, "members/user2"));
res.Should().HaveStatusCode(opMemberAdmin);
}
}
- [Fact]
- public async Task Visibility_Test()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Visibility_Test(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
- const string userUrl = "timelines/t1/posts";
- const string adminUrl = "timelines/t0/posts";
+ var userUrl = generator(1, "posts");
+ var adminUrl = generator(0, "posts");
{
using var client = await CreateClientAsUser();
using var content = new StringContent(@"{""visibility"":""abcdefg""}", System.Text.Encoding.UTF8, System.Net.Mime.MediaTypeNames.Application.Json);
- var res = await client.PatchAsync("timelines/t1", content);
+ var res = await client.PatchAsync(generator(1, null), content);
res.Should().BeInvalidModel();
}
{ // default visibility is registered
@@ -630,7 +724,7 @@ namespace Timeline.Tests.IntegratedTests { // change visibility to public
{
using var client = await CreateClientAsUser();
- var res = await client.PatchAsJsonAsync("timelines/t1",
+ var res = await client.PatchAsJsonAsync(generator(1, null),
new TimelinePatchRequest { Visibility = TimelineVisibility.Public });
res.Should().HaveStatusCode(200);
}
@@ -645,12 +739,12 @@ namespace Timeline.Tests.IntegratedTests {
using var client = await CreateClientAsAdministrator();
{
- var res = await client.PatchAsJsonAsync("timelines/t1",
+ var res = await client.PatchAsJsonAsync(generator(1, null),
new TimelinePatchRequest { Visibility = TimelineVisibility.Private });
res.Should().HaveStatusCode(200);
}
{
- var res = await client.PatchAsJsonAsync("timelines/t0",
+ var res = await client.PatchAsJsonAsync(generator(0, null),
new TimelinePatchRequest { Visibility = TimelineVisibility.Private });
res.Should().HaveStatusCode(200);
}
@@ -672,7 +766,7 @@ namespace Timeline.Tests.IntegratedTests }
{ // add member
using var client = await CreateClientAsAdministrator();
- var res = await client.PutAsync("/timelines/t0/members/user1", null);
+ var res = await client.PutAsync(generator(0, "members/user1"), null);
res.Should().HaveStatusCode(200);
}
{ // now user can read admin's
@@ -683,22 +777,20 @@ namespace Timeline.Tests.IntegratedTests }
}
-
- [Fact]
- public async Task Permission_Post_Create()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Permission_Post_Create(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
using (var client = await CreateClientAsUser())
{
- var res = await client.PutAsync("timelines/t1/members/user2", null);
+ var res = await client.PutAsync(generator(1, "members/user2"), null);
res.Should().HaveStatusCode(200);
}
using (var client = await CreateDefaultClient())
{
{ // no auth should get 401
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
res.Should().HaveStatusCode(401);
}
@@ -707,12 +799,12 @@ namespace Timeline.Tests.IntegratedTests using (var client = await CreateClientAsUser())
{
{ // post self's
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
res.Should().HaveStatusCode(200);
}
{ // post other not as a member should get 403
- var res = await client.PostAsJsonAsync("timelines/t0/posts",
+ var res = await client.PostAsJsonAsync(generator(0, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
res.Should().HaveStatusCode(403);
}
@@ -721,7 +813,7 @@ namespace Timeline.Tests.IntegratedTests using (var client = await CreateClientAsAdministrator())
{
{ // post as admin
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
res.Should().HaveStatusCode(200);
}
@@ -730,22 +822,21 @@ namespace Timeline.Tests.IntegratedTests using (var client = await CreateClientAs(2))
{
{ // post as member
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
res.Should().HaveStatusCode(200);
}
}
}
- [Fact]
- public async Task Permission_Post_Delete()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Permission_Post_Delete(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
async Task<long> CreatePost(int userNumber)
{
using var client = await CreateClientAs(userNumber);
- var res = await client.PostAsJsonAsync($"timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa"));
return res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo>()
@@ -755,79 +846,78 @@ namespace Timeline.Tests.IntegratedTests using (var client = await CreateClientAsUser())
{
{
- var res = await client.PutAsync("timelines/t1/members/user2", null);
+ var res = await client.PutAsync(generator(1, "members/user2"), null);
res.Should().HaveStatusCode(200);
}
{
- var res = await client.PutAsync("timelines/t1/members/user3", null);
+ var res = await client.PutAsync(generator(1, "members/user3"), null);
res.Should().HaveStatusCode(200);
}
}
{ // no auth should get 401
using var client = await CreateDefaultClient();
- var res = await client.DeleteAsync("timelines/t1/posts/12");
+ var res = await client.DeleteAsync(generator(1, "posts/12"));
res.Should().HaveStatusCode(401);
}
{ // self can delete self
var postId = await CreatePost(1);
using var client = await CreateClientAsUser();
- var res = await client.DeleteAsync($"timelines/t1/posts/{postId}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{postId}"));
res.Should().HaveStatusCode(200);
}
{ // admin can delete any
var postId = await CreatePost(1);
using var client = await CreateClientAsAdministrator();
- var res = await client.DeleteAsync($"timelines/t1/posts/{postId}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{postId}"));
res.Should().HaveStatusCode(200);
}
{ // owner can delete other
var postId = await CreatePost(2);
using var client = await CreateClientAsUser();
- var res = await client.DeleteAsync($"timelines/t1/posts/{postId}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{postId}"));
res.Should().HaveStatusCode(200);
}
{ // author can delete self
var postId = await CreatePost(2);
using var client = await CreateClientAs(2);
- var res = await client.DeleteAsync($"timelines/t1/posts/{postId}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{postId}"));
res.Should().HaveStatusCode(200);
}
{ // otherwise is forbidden
var postId = await CreatePost(2);
using var client = await CreateClientAs(3);
- var res = await client.DeleteAsync($"timelines/t1/posts/{postId}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{postId}"));
res.Should().HaveStatusCode(403);
}
}
- [Fact]
- public async Task Post_Op_Should_Work()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task Post_Op_Should_Work(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
{
using var client = await CreateClientAsUser();
{
- var res = await client.GetAsync("timelines/t1/posts");
+ var res = await client.GetAsync(generator(1, "posts"));
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo[]>()
.Which.Should().NotBeNull().And.BeEmpty();
}
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest(null));
res.Should().BeInvalidModel();
}
const string mockContent = "aaa";
TimelinePostInfo createRes;
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest(mockContent));
var body = res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo>()
@@ -838,7 +928,7 @@ namespace Timeline.Tests.IntegratedTests createRes = body;
}
{
- var res = await client.GetAsync("timelines/t1/posts");
+ var res = await client.GetAsync(generator(1, "posts"));
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo[]>()
.Which.Should().NotBeNull().And.BeEquivalentTo(createRes);
@@ -847,7 +937,7 @@ namespace Timeline.Tests.IntegratedTests var mockTime2 = DateTime.Now.AddDays(-1);
TimelinePostInfo createRes2;
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest(mockContent2, mockTime2));
var body = res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo>()
@@ -859,25 +949,25 @@ namespace Timeline.Tests.IntegratedTests createRes2 = body;
}
{
- var res = await client.GetAsync("timelines/t1/posts");
+ var res = await client.GetAsync(generator(1, "posts"));
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo[]>()
.Which.Should().NotBeNull().And.BeEquivalentTo(createRes, createRes2);
}
{
- var res = await client.DeleteAsync($"timelines/t1/posts/{createRes.Id}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{createRes.Id}"));
res.Should().BeDelete(true);
}
{
- var res = await client.DeleteAsync($"timelines/t1/posts/{createRes.Id}");
+ var res = await client.DeleteAsync(generator(1, $"posts/{createRes.Id}"));
res.Should().BeDelete(false);
}
{
- var res = await client.DeleteAsync("timelines/t1/posts/30000");
+ var res = await client.DeleteAsync(generator(1, "posts/30000"));
res.Should().BeDelete(false);
}
{
- var res = await client.GetAsync("timelines/t1/posts");
+ var res = await client.GetAsync(generator(1, "posts"));
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo[]>()
.Which.Should().NotBeNull().And.BeEquivalentTo(createRes2);
@@ -885,16 +975,15 @@ namespace Timeline.Tests.IntegratedTests }
}
- [Fact]
- public async Task GetPost_Should_Ordered()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task GetPost_Should_Ordered(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
using var client = await CreateClientAsUser();
async Task<long> CreatePost(DateTime time)
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts",
+ var res = await client.PostAsJsonAsync(generator(1, "posts"),
TimelineHelper.TextPostCreateRequest("aaa", time));
return res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo>()
@@ -907,54 +996,53 @@ namespace Timeline.Tests.IntegratedTests var id2 = await CreatePost(now);
{
- var res = await client.GetAsync("timelines/t1/posts");
+ var res = await client.GetAsync(generator(1, "posts"));
res.Should().HaveStatusCode(200)
.And.HaveJsonBody<TimelinePostInfo[]>()
.Which.Select(p => p.Id).Should().Equal(id1, id2, id0);
}
}
- [Fact]
- public async Task CreatePost_InvalidModel()
+ [Theory]
+ [MemberData(nameof(TimelineUrlGeneratorData))]
+ public async Task CreatePost_InvalidModel(Func<int, string, string> generator)
{
- await CreateTestTimelines();
-
using var client = await CreateClientAsUser();
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = null });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = null });
res.Should().BeInvalidModel();
}
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = null } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = null } });
res.Should().BeInvalidModel();
}
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "hahaha" } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "hahaha" } });
res.Should().BeInvalidModel();
}
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "text", Text = null } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "text", Text = null } });
res.Should().BeInvalidModel();
}
{
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = null } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = null } });
res.Should().BeInvalidModel();
}
{
// image not base64
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = "!!!" } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = "!!!" } });
res.Should().BeInvalidModel();
}
{
// image base64 not image
- var res = await client.PostAsJsonAsync("timelines/t1/posts", new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = Convert.ToBase64String(new byte[] { 0x01, 0x02, 0x03 }) } });
+ var res = await client.PostAsJsonAsync(generator(1, "posts"), new TimelinePostCreateRequest { Content = new TimelinePostCreateRequestContent { Type = "image", Data = Convert.ToBase64String(new byte[] { 0x01, 0x02, 0x03 }) } });
res.Should().BeInvalidModel();
}
}
diff --git a/Timeline/Controllers/TimelineController.cs b/Timeline/Controllers/TimelineController.cs index d21603cd..0628937d 100644 --- a/Timeline/Controllers/TimelineController.cs +++ b/Timeline/Controllers/TimelineController.cs @@ -234,7 +234,7 @@ namespace Timeline.Controllers }
catch (UserNotExistException)
{
- return BadRequest(ErrorResponse.TimelineCommon.MemberPut_NotExist());
+ return BadRequest(ErrorResponse.TimelineController.MemberPut_NotExist());
}
}
@@ -272,7 +272,7 @@ namespace Timeline.Controllers }
catch (ConflictException)
{
- return BadRequest(ErrorResponse.TimelineCommon.NameConflict());
+ return BadRequest(ErrorResponse.TimelineController.NameConflict());
}
}
diff --git a/Timeline/Filters/Timeline.cs b/Timeline/Filters/Timeline.cs index e133c9d6..76e8d751 100644 --- a/Timeline/Filters/Timeline.cs +++ b/Timeline/Filters/Timeline.cs @@ -17,7 +17,7 @@ namespace Timeline.Filters }
else
{
- context.Result = new NotFoundObjectResult(ErrorResponse.TimelineCommon.NotExist());
+ context.Result = new NotFoundObjectResult(ErrorResponse.TimelineController.NotExist());
}
}
}
diff --git a/Timeline/Models/Http/ErrorResponse.cs b/Timeline/Models/Http/ErrorResponse.cs index 9f7e70e1..9c5a7cfe 100644 --- a/Timeline/Models/Http/ErrorResponse.cs +++ b/Timeline/Models/Http/ErrorResponse.cs @@ -242,44 +242,39 @@ namespace Timeline.Models.Http }
- public static class TimelineCommon
+ public static class TimelineController
{
public static CommonResponse NameConflict(params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.NameConflict, string.Format(TimelineCommon_NameConflict, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.NameConflict, string.Format(TimelineController_NameConflict, formatArgs));
}
public static CommonResponse CustomMessage_NameConflict(string message, params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.NameConflict, string.Format(message, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.NameConflict, string.Format(message, formatArgs));
}
public static CommonResponse NotExist(params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.NotExist, string.Format(TimelineCommon_NotExist, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.NotExist, string.Format(TimelineController_NotExist, formatArgs));
}
public static CommonResponse CustomMessage_NotExist(string message, params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.NotExist, string.Format(message, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.NotExist, string.Format(message, formatArgs));
}
public static CommonResponse MemberPut_NotExist(params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.MemberPut_NotExist, string.Format(TimelineCommon_MemberPut_NotExist, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.MemberPut_NotExist, string.Format(TimelineController_MemberPut_NotExist, formatArgs));
}
public static CommonResponse CustomMessage_MemberPut_NotExist(string message, params object?[] formatArgs)
{
- return new CommonResponse(ErrorCodes.TimelineCommon.MemberPut_NotExist, string.Format(message, formatArgs));
+ return new CommonResponse(ErrorCodes.TimelineController.MemberPut_NotExist, string.Format(message, formatArgs));
}
- }
-
- public static class TimelineController
- {
-
public static CommonResponse QueryRelateNotExist(params object?[] formatArgs)
{
return new CommonResponse(ErrorCodes.TimelineController.QueryRelateNotExist, string.Format(TimelineController_QueryRelateNotExist, formatArgs));
@@ -290,6 +285,16 @@ namespace Timeline.Models.Http return new CommonResponse(ErrorCodes.TimelineController.QueryRelateNotExist, string.Format(message, formatArgs));
}
+ public static CommonResponse PostNoData(params object?[] formatArgs)
+ {
+ return new CommonResponse(ErrorCodes.TimelineController.PostNoData, string.Format(TimelineController_PostNoData, formatArgs));
+ }
+
+ public static CommonResponse CustomMessage_PostNoData(string message, params object?[] formatArgs)
+ {
+ return new CommonResponse(ErrorCodes.TimelineController.PostNoData, string.Format(message, formatArgs));
+ }
+
}
}
diff --git a/Timeline/Resources/Messages.Designer.cs b/Timeline/Resources/Messages.Designer.cs index fb093f07..cae91093 100644 --- a/Timeline/Resources/Messages.Designer.cs +++ b/Timeline/Resources/Messages.Designer.cs @@ -151,65 +151,74 @@ namespace Timeline.Resources { }
/// <summary>
- /// Looks up a localized string similar to The user to set as member does not exist..
+ /// Looks up a localized string similar to Unknown type of post content..
/// </summary>
- internal static string TimelineCommon_MemberPut_NotExist {
+ internal static string TimelineController_ContentUnknownType {
get {
- return ResourceManager.GetString("TimelineCommon_MemberPut_NotExist", resourceCulture);
+ return ResourceManager.GetString("TimelineController_ContentUnknownType", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to A timeline with given name already exists..
+ /// Looks up a localized string similar to Data field is not a valid base64 string in image content..
/// </summary>
- internal static string TimelineCommon_NameConflict {
+ internal static string TimelineController_ImageContentDataNotBase64 {
get {
- return ResourceManager.GetString("TimelineCommon_NameConflict", resourceCulture);
+ return ResourceManager.GetString("TimelineController_ImageContentDataNotBase64", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to The timeline with given name does not exist..
+ /// Looks up a localized string similar to Data field is not a valid image after base64 decoding in image content..
/// </summary>
- internal static string TimelineCommon_NotExist {
+ internal static string TimelineController_ImageContentDataNotImage {
get {
- return ResourceManager.GetString("TimelineCommon_NotExist", resourceCulture);
+ return ResourceManager.GetString("TimelineController_ImageContentDataNotImage", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Unknown type of post content..
+ /// Looks up a localized string similar to Data field is required for image content..
/// </summary>
- internal static string TimelineController_ContentUnknownType {
+ internal static string TimelineController_ImageContentDataRequired {
get {
- return ResourceManager.GetString("TimelineController_ContentUnknownType", resourceCulture);
+ return ResourceManager.GetString("TimelineController_ImageContentDataRequired", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Data field is not a valid base64 string in image content..
+ /// Looks up a localized string similar to The user to set as member does not exist..
/// </summary>
- internal static string TimelineController_ImageContentDataNotBase64 {
+ internal static string TimelineController_MemberPut_NotExist {
get {
- return ResourceManager.GetString("TimelineController_ImageContentDataNotBase64", resourceCulture);
+ return ResourceManager.GetString("TimelineController_MemberPut_NotExist", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Data field is not a valid image after base64 decoding in image content..
+ /// Looks up a localized string similar to A timeline with given name already exists..
/// </summary>
- internal static string TimelineController_ImageContentDataNotImage {
+ internal static string TimelineController_NameConflict {
get {
- return ResourceManager.GetString("TimelineController_ImageContentDataNotImage", resourceCulture);
+ return ResourceManager.GetString("TimelineController_NameConflict", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Data field is required for image content..
+ /// Looks up a localized string similar to The timeline with given name does not exist..
/// </summary>
- internal static string TimelineController_ImageContentDataRequired {
+ internal static string TimelineController_NotExist {
get {
- return ResourceManager.GetString("TimelineController_ImageContentDataRequired", resourceCulture);
+ return ResourceManager.GetString("TimelineController_NotExist", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The post of that type has no data..
+ /// </summary>
+ internal static string TimelineController_PostNoData {
+ get {
+ return ResourceManager.GetString("TimelineController_PostNoData", resourceCulture);
}
}
diff --git a/Timeline/Resources/Messages.resx b/Timeline/Resources/Messages.resx index 6a4cb1b6..631bd749 100644 --- a/Timeline/Resources/Messages.resx +++ b/Timeline/Resources/Messages.resx @@ -147,15 +147,6 @@ <data name="Common_InvalidModel" xml:space="preserve">
<value>Model is of bad format.</value>
</data>
- <data name="TimelineCommon_MemberPut_NotExist" xml:space="preserve">
- <value>The user to set as member does not exist.</value>
- </data>
- <data name="TimelineCommon_NameConflict" xml:space="preserve">
- <value>A timeline with given name already exists.</value>
- </data>
- <data name="TimelineCommon_NotExist" xml:space="preserve">
- <value>The timeline with given name does not exist.</value>
- </data>
<data name="TimelineController_ContentUnknownType" xml:space="preserve">
<value>Unknown type of post content.</value>
</data>
@@ -168,6 +159,18 @@ <data name="TimelineController_ImageContentDataRequired" xml:space="preserve">
<value>Data field is required for image content.</value>
</data>
+ <data name="TimelineController_MemberPut_NotExist" xml:space="preserve">
+ <value>The user to set as member does not exist.</value>
+ </data>
+ <data name="TimelineController_NameConflict" xml:space="preserve">
+ <value>A timeline with given name already exists.</value>
+ </data>
+ <data name="TimelineController_NotExist" xml:space="preserve">
+ <value>The timeline with given name does not exist.</value>
+ </data>
+ <data name="TimelineController_PostNoData" xml:space="preserve">
+ <value>The post of that type has no data.</value>
+ </data>
<data name="TimelineController_QueryRelateNotExist" xml:space="preserve">
<value>The user specified by query param "relate" does not exist.</value>
</data>
diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index 97280728..301a1d97 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -287,11 +287,11 @@ namespace Timeline.Services }
- public abstract class BaseTimelineManager : IBaseTimelineService
+ public abstract class BaseTimelineService : IBaseTimelineService
{
- protected BaseTimelineManager(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock)
+ protected BaseTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock)
{
- _logger = loggerFactory.CreateLogger<BaseTimelineManager>();
+ _logger = loggerFactory.CreateLogger<BaseTimelineService>();
Clock = clock;
Database = database;
ImageValidator = imageValidator;
@@ -299,7 +299,7 @@ namespace Timeline.Services UserService = userService;
}
- private ILogger<BaseTimelineManager> _logger;
+ private ILogger<BaseTimelineService> _logger;
protected IClock Clock { get; }
@@ -546,7 +546,7 @@ namespace Timeline.Services var post = await Database.TimelinePosts.Where(p => p.TimelineId == timelineId && p.LocalId == id).SingleOrDefaultAsync();
- if (post == null)
+ if (post == null || post.Content == null)
throw new TimelinePostNotExistException(name, id);
string? dataTag = null;
@@ -739,7 +739,7 @@ namespace Timeline.Services }
}
- public class OrdinaryTimelineService : BaseTimelineManager, IOrdinaryTimelineService
+ public class OrdinaryTimelineService : BaseTimelineService, IOrdinaryTimelineService
{
private readonly TimelineNameValidator _timelineNameValidator = new TimelineNameValidator();
@@ -782,7 +782,7 @@ namespace Timeline.Services }
}
- public class PersonalTimelineService : BaseTimelineManager, IPersonalTimelineService
+ public class PersonalTimelineService : BaseTimelineService, IPersonalTimelineService
{
public PersonalTimelineService(ILoggerFactory loggerFactory, DatabaseContext database, IImageValidator imageValidator, IDataManager dataManager, IUserService userService, IClock clock)
: base(loggerFactory, database, imageValidator, dataManager, userService, clock)
|