aboutsummaryrefslogtreecommitdiff
path: root/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
diff options
context:
space:
mode:
author杨宇千 <crupest@outlook.com>2019-11-20 18:21:17 +0800
committerGitHub <noreply@github.com>2019-11-20 18:21:17 +0800
commit751467deb8ae18909ebd2b241bbb64f1f9da8295 (patch)
tree788b8acdf1141c757cb3226d3cd5f64594386b8f /Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
parent2de7fa95bb5ad0a10f74fb390bac464a250dee42 (diff)
parent33318b9244a82fee6d711aa15f853e1590ff13f7 (diff)
downloadtimeline-751467deb8ae18909ebd2b241bbb64f1f9da8295.tar.gz
timeline-751467deb8ae18909ebd2b241bbb64f1f9da8295.tar.bz2
timeline-751467deb8ae18909ebd2b241bbb64f1f9da8295.zip
Merge pull request #54 from crupest/timeline
Add core feature Timeline (currently only personal timeline)
Diffstat (limited to 'Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs')
-rw-r--r--Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs495
1 files changed, 495 insertions, 0 deletions
diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
new file mode 100644
index 00000000..483499fb
--- /dev/null
+++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs
@@ -0,0 +1,495 @@
+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)
+ {
+
+ }
+
+ [Fact]
+ public async Task TimelineGet_Should_Work()
+ {
+ using var client = await CreateClientWithNoAuth();
+ var res = await client.GetAsync("users/user/timeline");
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<BaseTimelineInfo>().Which;
+ body.Owner.Should().Be("user");
+ body.Visibility.Should().Be(TimelineVisibility.Register);
+ body.Description.Should().Be("");
+ body.Members.Should().NotBeNull().And.BeEmpty();
+ }
+
+ [Fact]
+ public async Task Description_Should_Work()
+ {
+ using var client = await CreateClientAsUser();
+
+ async Task AssertDescription(string description)
+ {
+ var res = await client.GetAsync("users/user/timeline");
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<BaseTimelineInfo>()
+ .Which.Description.Should().Be(description);
+ }
+
+ const string mockDescription = "haha";
+
+ await AssertDescription("");
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Description = mockDescription });
+ res.Should().HaveStatusCode(200);
+ await AssertDescription(mockDescription);
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Description = null });
+ res.Should().HaveStatusCode(200);
+ await AssertDescription(mockDescription);
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Description = "" });
+ res.Should().HaveStatusCode(200);
+ await AssertDescription("");
+ }
+ }
+
+ [Fact]
+ public async Task Member_Should_Work()
+ {
+ const string getUrl = "users/user/timeline";
+ const string changeUrl = "users/user/timeline/op/member";
+ using var client = await CreateClientAsUser();
+
+ async Task AssertMembers(IList<string> members)
+ {
+ var res = await client.GetAsync(getUrl);
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<BaseTimelineInfo>()
+ .Which.Members.Should().NotBeNull().And.BeEquivalentTo(members);
+ }
+
+ async Task AssertEmptyMembers()
+ {
+ var res = await client.GetAsync(getUrl);
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<BaseTimelineInfo>()
+ .Which.Members.Should().NotBeNull().And.BeEmpty();
+ }
+
+ await AssertEmptyMembers();
+ {
+ var res = await client.PostAsJsonAsync(changeUrl,
+ new TimelineMemberChangeRequest { Add = new List<string> { "admin", "usernotexist" } });
+ res.Should().HaveStatusCode(400)
+ .And.HaveCommonBody()
+ .Which.Code.Should().Be(ErrorCodes.Http.Timeline.ChangeMemberUserNotExist);
+ }
+ {
+ var res = await client.PostAsJsonAsync(changeUrl,
+ new TimelineMemberChangeRequest { Remove = new List<string> { "admin", "usernotexist" } });
+ res.Should().HaveStatusCode(400)
+ .And.HaveCommonBody()
+ .Which.Code.Should().Be(ErrorCodes.Http.Timeline.ChangeMemberUserNotExist);
+ }
+ {
+ var res = await client.PostAsJsonAsync(changeUrl,
+ new TimelineMemberChangeRequest { Add = new List<string> { "admin" }, Remove = new List<string> { "admin" } });
+ res.Should().HaveStatusCode(200);
+ await AssertEmptyMembers();
+ }
+ {
+ var res = await client.PostAsJsonAsync(changeUrl,
+ new TimelineMemberChangeRequest { Add = new List<string> { "admin" } });
+ res.Should().HaveStatusCode(200);
+ await AssertMembers(new List<string> { "admin" });
+ }
+ {
+ var res = await client.PostAsJsonAsync(changeUrl,
+ new TimelineMemberChangeRequest { Remove = new List<string> { "admin" } });
+ res.Should().HaveStatusCode(200);
+ await AssertEmptyMembers();
+ }
+ }
+
+ [Theory]
+ [InlineData(AuthType.None, 200, 401, 401, 401, 401)]
+ [InlineData(AuthType.User, 200, 200, 403, 200, 403)]
+ [InlineData(AuthType.Admin, 200, 200, 200, 200, 200)]
+ public async Task Permission_Timeline(AuthType authType, int get, int opPropertyUser, int opPropertyAdmin, int opMemberUser, int opMemberAdmin)
+ {
+ using var client = await CreateClientAs(authType);
+ {
+ var res = await client.GetAsync("users/user/timeline");
+ res.Should().HaveStatusCode(get);
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Description = "hahaha" });
+ res.Should().HaveStatusCode(opPropertyUser);
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("users/admin/timeline/op/property",
+ new TimelinePropertyChangeRequest { Description = "hahaha" });
+ res.Should().HaveStatusCode(opPropertyAdmin);
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/member",
+ new TimelineMemberChangeRequest { Add = new List<string> { "admin" } });
+ res.Should().HaveStatusCode(opMemberUser);
+ }
+
+ {
+ var res = await client.PostAsJsonAsync("users/admin/timeline/op/member",
+ new TimelineMemberChangeRequest { Add = new List<string> { "user" } });
+ res.Should().HaveStatusCode(opMemberAdmin);
+ }
+ }
+
+ [Fact]
+ public async Task Permission_GetPost()
+ {
+ const string userUrl = "users/user/timeline/posts";
+ const string adminUrl = "users/admin/timeline/posts";
+ { // default visibility is registered
+ {
+ using var client = await CreateClientWithNoAuth();
+ 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.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Public });
+ res.Should().HaveStatusCode(200);
+ }
+ {
+ using var client = await CreateClientWithNoAuth();
+ var res = await client.GetAsync(userUrl);
+ res.Should().HaveStatusCode(200);
+ }
+ }
+
+ { // change visibility to private
+ {
+ using var client = await CreateClientAsAdmin();
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/property",
+ new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Private });
+ res.Should().HaveStatusCode(200);
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/admin/timeline/op/property",
+ new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Private });
+ res.Should().HaveStatusCode(200);
+ }
+ }
+ {
+ using var client = await CreateClientWithNoAuth();
+ 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 CreateClientAsAdmin();
+ var res = await client.GetAsync(userUrl);
+ res.Should().HaveStatusCode(200);
+ }
+ { // add member
+ using var client = await CreateClientAsAdmin();
+ var res = await client.PostAsJsonAsync("users/admin/timeline/op/member",
+ new TimelineMemberChangeRequest { Add = new List<string> { "user" } });
+ 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()
+ {
+ CreateExtraMockUsers(1);
+
+ using (var client = await CreateClientAsUser())
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/member",
+ new TimelineMemberChangeRequest { Add = new List<string> { "user0" } });
+ res.Should().HaveStatusCode(200);
+ }
+
+ using (var client = await CreateClientWithNoAuth())
+ {
+ { // no auth should get 401
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ res.Should().HaveStatusCode(401);
+ }
+ }
+
+ using (var client = await CreateClientAsUser())
+ {
+ { // post self's
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ res.Should().HaveStatusCode(200);
+ }
+ { // post other not as a member should get 403
+ var res = await client.PostAsJsonAsync("users/admin/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ res.Should().HaveStatusCode(403);
+ }
+ }
+
+ using (var client = await CreateClientAsAdmin())
+ {
+ { // post as admin
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ res.Should().HaveStatusCode(200);
+ }
+ }
+
+ using (var client = await CreateClientAs(ExtraMockUsers[0]))
+ {
+ { // post as member
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ res.Should().HaveStatusCode(200);
+ }
+ }
+ }
+
+ [Fact]
+ public async Task Permission_Post_Delete()
+ {
+ CreateExtraMockUsers(2);
+
+ async Task<long> CreatePost(MockUser auth, string timeline)
+ {
+ using var client = await CreateClientAs(auth);
+ var res = await client.PostAsJsonAsync($"users/{timeline}/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa" });
+ return res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostCreateResponse>()
+ .Which.Id;
+ }
+
+ using (var client = await CreateClientAsUser())
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/op/member",
+ new TimelineMemberChangeRequest { Add = new List<string> { "user0", "user1" } });
+ res.Should().HaveStatusCode(200);
+ }
+
+ { // no auth should get 401
+ using var client = await CreateClientWithNoAuth();
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = 12 });
+ res.Should().HaveStatusCode(401);
+ }
+
+ { // self can delete self
+ var postId = await CreatePost(MockUser.User, "user");
+ using var client = await CreateClientAsUser();
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = postId });
+ res.Should().HaveStatusCode(200);
+ }
+
+ { // admin can delete any
+ var postId = await CreatePost(MockUser.User, "user");
+ using var client = await CreateClientAsAdmin();
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = postId });
+ res.Should().HaveStatusCode(200);
+ }
+
+ { // owner can delete other
+ var postId = await CreatePost(ExtraMockUsers[0], "user");
+ using var client = await CreateClientAsUser();
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = postId });
+ res.Should().HaveStatusCode(200);
+ }
+
+ { // author can delete self
+ var postId = await CreatePost(ExtraMockUsers[0], "user");
+ using var client = await CreateClientAs(ExtraMockUsers[0]);
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = postId });
+ res.Should().HaveStatusCode(200);
+ }
+
+ { // otherwise is forbidden
+ var postId = await CreatePost(ExtraMockUsers[0], "user");
+ using var client = await CreateClientAs(ExtraMockUsers[1]);
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = postId });
+ res.Should().HaveStatusCode(403);
+ }
+ }
+
+ [Fact]
+ public async Task Post_Op_Should_Work()
+ {
+ {
+ using var client = await CreateClientAsUser();
+ {
+ var res = await client.GetAsync("users/user/timeline/posts");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostInfo[]>()
+ .Which.Should().NotBeNull().And.BeEmpty();
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = null });
+ res.Should().BeInvalidModel();
+ }
+ const string mockContent = "aaa";
+ TimelinePostCreateResponse createRes;
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = mockContent });
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostCreateResponse>()
+ .Which;
+ body.Should().NotBeNull();
+ createRes = body;
+ }
+ {
+ var res = await client.GetAsync("users/user/timeline/posts");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostInfo[]>()
+ .Which.Should().NotBeNull().And.BeEquivalentTo(
+ new TimelinePostInfo
+ {
+ Id = createRes.Id,
+ Author = "user",
+ Content = mockContent,
+ Time = createRes.Time
+ });
+ }
+ const string mockContent2 = "bbb";
+ var mockTime2 = DateTime.Now.AddDays(-1);
+ TimelinePostCreateResponse createRes2;
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = mockContent2, Time = mockTime2 });
+ var body = res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostCreateResponse>()
+ .Which;
+ body.Should().NotBeNull();
+ createRes2 = body;
+ }
+ {
+ var res = await client.GetAsync("users/user/timeline/posts");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostInfo[]>()
+ .Which.Should().NotBeNull().And.BeEquivalentTo(
+ new TimelinePostInfo
+ {
+ Id = createRes.Id,
+ Author = "user",
+ Content = mockContent,
+ Time = createRes.Time
+ },
+ new TimelinePostInfo
+ {
+ Id = createRes2.Id,
+ Author = "user",
+ Content = mockContent2,
+ Time = createRes2.Time
+ });
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = createRes.Id });
+ res.Should().HaveStatusCode(200);
+ }
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/delete",
+ new TimelinePostDeleteRequest { Id = 30000 });
+ res.Should().HaveStatusCode(400)
+ .And.HaveCommonBody()
+ .Which.Code.Should().Be(ErrorCodes.Http.Timeline.PostOperationDeleteNotExist);
+ }
+ {
+ var res = await client.GetAsync("users/user/timeline/posts");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostInfo[]>()
+ .Which.Should().NotBeNull().And.BeEquivalentTo(
+ new TimelinePostInfo
+ {
+ Id = createRes2.Id,
+ Author = "user",
+ Content = mockContent2,
+ Time = createRes2.Time
+ });
+ }
+ }
+ }
+
+ [Fact]
+ public async Task GetPost_Should_Ordered()
+ {
+ using var client = await CreateClientAsUser();
+
+ async Task<long> CreatePost(DateTime time)
+ {
+ var res = await client.PostAsJsonAsync("users/user/timeline/postop/create",
+ new TimelinePostCreateRequest { Content = "aaa", Time = time });
+ return res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostCreateResponse>()
+ .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("users/user/timeline/posts");
+ res.Should().HaveStatusCode(200)
+ .And.HaveJsonBody<TimelinePostInfo[]>()
+ .Which.Select(p => p.Id).Should().Equal(id1, id2, id0);
+ }
+ }
+ }
+}