diff options
author | crupest <crupest@outlook.com> | 2019-11-18 19:29:37 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-11-18 19:29:37 +0800 |
commit | 468d7f4c416d4469375b7170beb5e388737c0970 (patch) | |
tree | 047960f05911f7c841223f7b6528fe30b8e52088 | |
parent | 5b5bb69c3ba2150816f120860be46d49c5bc37aa (diff) | |
download | timeline-468d7f4c416d4469375b7170beb5e388737c0970.tar.gz timeline-468d7f4c416d4469375b7170beb5e388737c0970.tar.bz2 timeline-468d7f4c416d4469375b7170beb5e388737c0970.zip |
Write tests and fix bugs found via tests.
-rw-r--r-- | Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs | 2 | ||||
-rw-r--r-- | Timeline.Tests/Helpers/ResponseAssertions.cs | 2 | ||||
-rw-r--r-- | Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs | 135 | ||||
-rw-r--r-- | Timeline/Entities/TimelineEntity.cs | 17 | ||||
-rw-r--r-- | Timeline/Models/Timeline.cs | 18 | ||||
-rw-r--r-- | Timeline/Resources/Services/Exception.Designer.cs | 2 | ||||
-rw-r--r-- | Timeline/Resources/Services/Exception.resx | 2 | ||||
-rw-r--r-- | Timeline/Services/TimelineService.cs | 2 |
8 files changed, 157 insertions, 23 deletions
diff --git a/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs b/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs index a7cbb37e..819017c2 100644 --- a/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs +++ b/Timeline.Tests/Controllers/PersonalTimelineControllerTest.cs @@ -309,7 +309,7 @@ namespace Timeline.Tests.Controllers var req = new TimelinePropertyChangeRequest
{
Description = "",
- Visibility = Entities.TimelineVisibility.Private
+ Visibility = TimelineVisibility.Private
};
_service.Setup(s => s.ChangeProperty(username, req)).Returns(Task.CompletedTask);
var result = await _controller.TimelineChangeProperty(username, req);
diff --git a/Timeline.Tests/Helpers/ResponseAssertions.cs b/Timeline.Tests/Helpers/ResponseAssertions.cs index 0e6f215b..6d764c68 100644 --- a/Timeline.Tests/Helpers/ResponseAssertions.cs +++ b/Timeline.Tests/Helpers/ResponseAssertions.cs @@ -88,7 +88,7 @@ namespace Timeline.Tests.Helpers return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, null);
}
- var result = JsonConvert.DeserializeObject<T>(body);
+ var result = JsonConvert.DeserializeObject<T>(body); // TODO! catch and throw on bad format
return new AndWhichConstraint<HttpResponseMessageAssertions, T>(this, result);
}
}
diff --git a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs index 9629fc0a..aaa6215c 100644 --- a/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs +++ b/Timeline.Tests/IntegratedTests/PersonalTimelineTest.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Net.Http; using System.Text.Json; using System.Threading.Tasks; +using Timeline.Models; using Timeline.Models.Http; using Timeline.Tests.Helpers; using Timeline.Tests.Helpers.Authentication; @@ -22,6 +23,64 @@ namespace Timeline.Tests.IntegratedTests } + [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 Factory.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)] @@ -58,5 +117,81 @@ namespace Timeline.Tests.IntegratedTests 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 = Factory.CreateDefaultClient(); + var res = await client.GetAsync(userUrl); + res.Should().HaveStatusCode(403); + } + + { + using var client = await Factory.CreateClientAsUser(); + var res = await client.GetAsync(adminUrl); + res.Should().HaveStatusCode(200); + } + } + + { // change visibility to public + { + using var client = await Factory.CreateClientAsUser(); + var res = await client.PostAsJsonAsync("users/user/timeline/op/property", + new TimelinePropertyChangeRequest { Visibility = TimelineVisibility.Public }); + res.Should().HaveStatusCode(200); + } + { + using var client = Factory.CreateDefaultClient(); + var res = await client.GetAsync(userUrl); + res.Should().HaveStatusCode(200); + } + } + + { // change visibility to private + { + using var client = await Factory.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 = Factory.CreateDefaultClient(); + var res = await client.GetAsync(userUrl); + res.Should().HaveStatusCode(403); + } + { // user can't read admin's + using var client = await Factory.CreateClientAsUser(); + var res = await client.GetAsync(adminUrl); + res.Should().HaveStatusCode(403); + } + { // admin can read user's + using var client = await Factory.CreateClientAsAdmin(); + var res = await client.GetAsync(userUrl); + res.Should().HaveStatusCode(200); + } + { // add member + using var client = await Factory.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 Factory.CreateClientAsUser(); + var res = await client.GetAsync(adminUrl); + res.Should().HaveStatusCode(200); + } + } + } } } diff --git a/Timeline/Entities/TimelineEntity.cs b/Timeline/Entities/TimelineEntity.cs index f5e22a54..9cacfcae 100644 --- a/Timeline/Entities/TimelineEntity.cs +++ b/Timeline/Entities/TimelineEntity.cs @@ -2,25 +2,10 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
+using Timeline.Models;
namespace Timeline.Entities
{
- public enum TimelineVisibility
- {
- /// <summary>
- /// All people including those without accounts.
- /// </summary>
- Public,
- /// <summary>
- /// Only people signed in.
- /// </summary>
- Register,
- /// <summary>
- /// Only member.
- /// </summary>
- Private
- }
-
[System.Diagnostics.CodeAnalysis.SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "This is entity object.")]
[Table("timelines")]
public class TimelineEntity
diff --git a/Timeline/Models/Timeline.cs b/Timeline/Models/Timeline.cs index 26012878..85fefff5 100644 --- a/Timeline/Models/Timeline.cs +++ b/Timeline/Models/Timeline.cs @@ -1,11 +1,25 @@ using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
using Timeline.Entities;
namespace Timeline.Models
{
+ public enum TimelineVisibility
+ {
+ /// <summary>
+ /// All people including those without accounts.
+ /// </summary>
+ Public,
+ /// <summary>
+ /// Only people signed in.
+ /// </summary>
+ Register,
+ /// <summary>
+ /// Only member.
+ /// </summary>
+ Private
+ }
+
public class TimelinePostInfo
{
public long Id { get; set; }
diff --git a/Timeline/Resources/Services/Exception.Designer.cs b/Timeline/Resources/Services/Exception.Designer.cs index 970c306d..1b46f9e9 100644 --- a/Timeline/Resources/Services/Exception.Designer.cs +++ b/Timeline/Resources/Services/Exception.Designer.cs @@ -286,7 +286,7 @@ namespace Timeline.Resources.Services { }
/// <summary>
- /// Looks up a localized string similar to An exception happened when do operation {} on the {} member on timeline..
+ /// Looks up a localized string similar to An exception happened when do operation {0} on the {1} member on timeline..
/// </summary>
internal static string TimelineMemberOperationExceptionDetail {
get {
diff --git a/Timeline/Resources/Services/Exception.resx b/Timeline/Resources/Services/Exception.resx index c8f6676a..1d9c0037 100644 --- a/Timeline/Resources/Services/Exception.resx +++ b/Timeline/Resources/Services/Exception.resx @@ -193,7 +193,7 @@ <value>An exception happened when add or remove member on timeline.</value>
</data>
<data name="TimelineMemberOperationExceptionDetail" xml:space="preserve">
- <value>An exception happened when do operation {} on the {} member on timeline.</value>
+ <value>An exception happened when do operation {0} on the {1} member on timeline.</value>
</data>
<data name="TimelineNameBadFormatException" xml:space="preserve">
<value>Timeline name is of bad format. If this is a personal timeline, it means the username is of bad format and inner exception should be a UsernameBadFormatException.</value>
diff --git a/Timeline/Services/TimelineService.cs b/Timeline/Services/TimelineService.cs index 494beb11..1d199aae 100644 --- a/Timeline/Services/TimelineService.cs +++ b/Timeline/Services/TimelineService.cs @@ -458,7 +458,7 @@ namespace Timeline.Services if (list != null)
{
Dictionary<string, int> result = new Dictionary<string, int>();
- var count = 0;
+ var count = list.Count;
for (var index = 0; index < count; index++)
{
var username = list[index];
|