From 48d53341db4953b3d583dd825b48d854c0a166e9 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 13 Nov 2020 17:08:20 +0800 Subject: ... --- BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs') diff --git a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs b/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs index b3709a28..ef230cb0 100644 --- a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs +++ b/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs @@ -17,31 +17,33 @@ namespace Timeline.Tests.Helpers var res = await client.GetAsync(getUrl); res.Should().HaveStatusCode(200); var cacheControlHeader = res.Headers.CacheControl; - cacheControlHeader.NoCache.Should().BeTrue(); + cacheControlHeader.Should().NotBeNull(); + cacheControlHeader!.NoCache.Should().BeTrue(); cacheControlHeader.NoStore.Should().BeFalse(); cacheControlHeader.Private.Should().BeTrue(); cacheControlHeader.Public.Should().BeFalse(); cacheControlHeader.MustRevalidate.Should().BeTrue(); cacheControlHeader.MaxAge.Should().NotBeNull().And.Be(TimeSpan.FromDays(14)); - eTag = res.Headers.ETag; + res.Headers.ETag.Should().NotBeNull(); + eTag = res.Headers.ETag!; } { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.TryAddWithoutValidation("If-None-Match", "\"dsdfd"); var res = await client.SendAsync(request); - res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBody(ErrorCodes.Common.Header.IfNonMatch_BadFormat); + await res.Should().HaveStatusCode(HttpStatusCode.BadRequest) + .And.HaveCommonBodyWithCodeAsync(ErrorCodes.Common.Header.IfNonMatch_BadFormat); } { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.TryAddWithoutValidation("If-None-Match", "\"aaa\""); @@ -52,7 +54,7 @@ namespace Timeline.Tests.Helpers { using var request = new HttpRequestMessage() { - RequestUri = new Uri(client.BaseAddress, getUrl), + RequestUri = new Uri(client.BaseAddress!, getUrl), Method = HttpMethod.Get, }; request.Headers.Add("If-None-Match", eTag.ToString()); -- cgit v1.2.3 From 301780410580647b994e13bc2367153569d04634 Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 14 Nov 2020 01:58:38 +0800 Subject: ... --- BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs | 66 --- .../Timeline.Tests/Helpers/HttpClientExtensions.cs | 36 -- .../Helpers/HttpResponseExtensions.cs | 30 -- .../Timeline.Tests/Helpers/ResponseAssertions.cs | 128 ------ .../IntegratedTests/CacheTestHelper.cs | 66 +++ .../IntegratedTests/CommonJsonSerializeOptions.cs | 21 + .../IntegratedTests/HttpClientExtensions.cs | 48 +++ .../HttpClientTimelineExtensions.cs | 30 ++ .../IntegratedTests/HttpClientUserExtensions.cs | 17 + .../IntegratedTests/HttpResponseExtensions.cs | 14 + .../IntegratedTests/IntegratedTestBase.cs | 9 +- .../IntegratedTests/ResponseAssertions.cs | 136 +++++++ .../Timeline.Tests/IntegratedTests/TimelineTest.cs | 452 +++++---------------- .../IntegratedTests/UserPermissionTest.cs | 64 +-- 14 files changed, 478 insertions(+), 639 deletions(-) delete mode 100644 BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs delete mode 100644 BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs delete mode 100644 BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs delete mode 100644 BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/CacheTestHelper.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/HttpClientExtensions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/HttpResponseExtensions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests/ResponseAssertions.cs (limited to 'BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs') diff --git a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs b/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs deleted file mode 100644 index ef230cb0..00000000 --- a/BackEnd/Timeline.Tests/Helpers/CacheTestHelper.cs +++ /dev/null @@ -1,66 +0,0 @@ -using FluentAssertions; -using System; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Threading.Tasks; -using Timeline.Models.Http; - -namespace Timeline.Tests.Helpers -{ - public static class CacheTestHelper - { - public static async Task TestCache(HttpClient client, string getUrl) - { - EntityTagHeaderValue eTag; - { - var res = await client.GetAsync(getUrl); - res.Should().HaveStatusCode(200); - var cacheControlHeader = res.Headers.CacheControl; - cacheControlHeader.Should().NotBeNull(); - cacheControlHeader!.NoCache.Should().BeTrue(); - cacheControlHeader.NoStore.Should().BeFalse(); - cacheControlHeader.Private.Should().BeTrue(); - cacheControlHeader.Public.Should().BeFalse(); - cacheControlHeader.MustRevalidate.Should().BeTrue(); - cacheControlHeader.MaxAge.Should().NotBeNull().And.Be(TimeSpan.FromDays(14)); - res.Headers.ETag.Should().NotBeNull(); - eTag = res.Headers.ETag!; - } - - { - using var request = new HttpRequestMessage() - { - RequestUri = new Uri(client.BaseAddress!, getUrl), - Method = HttpMethod.Get, - }; - request.Headers.TryAddWithoutValidation("If-None-Match", "\"dsdfd"); - var res = await client.SendAsync(request); - await res.Should().HaveStatusCode(HttpStatusCode.BadRequest) - .And.HaveCommonBodyWithCodeAsync(ErrorCodes.Common.Header.IfNonMatch_BadFormat); - } - - { - using var request = new HttpRequestMessage() - { - RequestUri = new Uri(client.BaseAddress!, getUrl), - Method = HttpMethod.Get, - }; - request.Headers.TryAddWithoutValidation("If-None-Match", "\"aaa\""); - var res = await client.SendAsync(request); - res.Should().HaveStatusCode(HttpStatusCode.OK); - } - - { - using var request = new HttpRequestMessage() - { - RequestUri = new Uri(client.BaseAddress!, getUrl), - Method = HttpMethod.Get, - }; - request.Headers.Add("If-None-Match", eTag.ToString()); - var res = await client.SendAsync(request); - res.Should().HaveStatusCode(HttpStatusCode.NotModified); - } - } - } -} diff --git a/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs b/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs deleted file mode 100644 index 47335a22..00000000 --- a/BackEnd/Timeline.Tests/Helpers/HttpClientExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Net.Mime; -using System.Text; -using System.Threading.Tasks; - -namespace Timeline.Tests.Helpers -{ - public static class HttpClientExtensions - { - public static Task PutByteArrayAsync(this HttpClient client, string url, byte[] body, string mimeType) - { - return client.PutByteArrayAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); - } - - public static Task PutByteArrayAsync(this HttpClient client, Uri url, byte[] body, string mimeType) - { - using var content = new ByteArrayContent(body); - content.Headers.ContentLength = body.Length; - content.Headers.ContentType = new MediaTypeHeaderValue(mimeType); - return client.PutAsync(url, content); - } - - public static Task PutStringAsync(this HttpClient client, string url, string body, string? mimeType = null) - { - return client.PutStringAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); - } - - public static Task PutStringAsync(this HttpClient client, Uri url, string body, string? mimeType = null) - { - using var content = new StringContent(body, Encoding.UTF8, mimeType ?? MediaTypeNames.Text.Plain); - return client.PutAsync(url, content); - } - } -} diff --git a/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs b/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs deleted file mode 100644 index 01497434..00000000 --- a/BackEnd/Timeline.Tests/Helpers/HttpResponseExtensions.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Net.Http; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; -using Timeline.Models.Converters; -using Timeline.Models.Http; - -namespace Timeline.Tests.Helpers -{ - public static class HttpResponseExtensions - { - public static JsonSerializerOptions JsonSerializerOptions { get; } - - static HttpResponseExtensions() - { - JsonSerializerOptions = new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); - JsonSerializerOptions.Converters.Add(new JsonDateTimeConverter()); - } - - public static async Task ReadBodyAsJsonAsync(this HttpResponseMessage response) - { - var stream = await response.Content.ReadAsStreamAsync(); - return await JsonSerializer.DeserializeAsync(stream, JsonSerializerOptions); - } - } -} diff --git a/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs b/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs deleted file mode 100644 index 95df3eda..00000000 --- a/BackEnd/Timeline.Tests/Helpers/ResponseAssertions.cs +++ /dev/null @@ -1,128 +0,0 @@ -using FluentAssertions; -using FluentAssertions.Execution; -using FluentAssertions.Formatting; -using FluentAssertions.Primitives; -using System; -using System.Globalization; -using System.Net; -using System.Net.Http; -using System.Net.Http.Json; -using System.Text; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading.Tasks; -using Timeline.Models.Converters; -using Timeline.Models.Http; - -namespace Timeline.Tests.Helpers -{ - public class HttpResponseMessageValueFormatter : IValueFormatter - { - public bool CanHandle(object value) - { - return value is HttpResponseMessage; - } - - public string Format(object value, FormattingContext context, FormatChild formatChild) - { - string newline = context.UseLineBreaks ? Environment.NewLine : ""; - string padding = new string('\t', context.Depth); - - var res = (HttpResponseMessage)value; - return $"{newline}{padding} Status Code: {res.StatusCode}"; - } - } - - public class HttpResponseMessageAssertions - : ReferenceTypeAssertions - { - static HttpResponseMessageAssertions() - { - Formatter.AddFormatter(new HttpResponseMessageValueFormatter()); - } - - public HttpResponseMessageAssertions(HttpResponseMessage instance) - { - Subject = instance; - } - - protected override string Identifier => "HttpResponseMessage"; - - public AndConstraint HaveStatusCode(int expected, string because = "", params object[] becauseArgs) - { - return HaveStatusCode((HttpStatusCode)expected, because, becauseArgs); - } - - public AndConstraint HaveStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) - { - Execute.Assertion.BecauseOf(because, becauseArgs) - .ForCondition(Subject.StatusCode == expected) - .FailWith("Expected status code of {context:HttpResponseMessage} to be {0}{reason}, but found {1}.", expected, Subject.StatusCode); - return new AndConstraint(this); - } - - public async Task HaveAndGetJsonBodyAsync(string because = "", params object[] becauseArgs) - { - var a = Execute.Assertion.BecauseOf(because, becauseArgs); - - var body = await Subject.ReadBodyAsJsonAsync(); - if (body == null) - { - a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string of type {0}{reason}, but failed to read it or it was not a valid json string.", typeof(T).FullName); - return default!; - } - return body; - } - } - - public static class AssertionResponseExtensions - { - public static HttpResponseMessageAssertions Should(this HttpResponseMessage instance) - { - return new HttpResponseMessageAssertions(instance); - } - - public static Task HaveAndGetCommonBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) - { - return assertions.HaveAndGetJsonBodyAsync(because, becauseArgs); - } - - public static async Task HaveCommonBodyWithCodeAsync(this HttpResponseMessageAssertions assertions, int code, string? message = null, params object[] messageArgs) - { - message = string.IsNullOrEmpty(message) ? "" : ", " + string.Format(CultureInfo.CurrentCulture, message, messageArgs); - var body = await assertions.HaveAndGetCommonBodyAsync("Response body should be CommonResponse{0}", message); - body.Code.Should().Be(code, "Response body code is not the specified one{0}", message); - } - - public static Task> HaveAndGetCommonDataBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) - { - return assertions.HaveAndGetJsonBodyAsync>(because, becauseArgs); - } - - public static async Task BePutAsync(this HttpResponseMessageAssertions assertions, bool create, string because = "", params object[] becauseArgs) - { - var body = await assertions.HaveStatusCode(create ? 201 : 200, because, becauseArgs) - .And.HaveAndGetJsonBodyAsync(because, becauseArgs); - body.Code.Should().Be(0); - body.Data.Create.Should().Be(create); - } - - public static async Task BeDeleteAsync(this HttpResponseMessageAssertions assertions, bool delete, string because = "", params object[] becauseArgs) - { - var body = await assertions.HaveStatusCode(200, because, becauseArgs) - .And.HaveAndGetJsonBodyAsync(because, becauseArgs); - body.Code.Should().Be(0); - body.Data.Delete.Should().Be(delete); - } - - public static async Task BeInvalidModelAsync(this HttpResponseMessageAssertions assertions, string message = null) - { - message = string.IsNullOrEmpty(message) ? "" : ", " + message; - var body = await assertions.HaveStatusCode(400, "Invalid Model Error must have 400 status code{0}", message) - .And.HaveAndGetCommonBodyAsync("Invalid Model Error must have CommonResponse body{0}", message); - body.Code.Should().Be(ErrorCodes.Common.InvalidModel, - "Invalid Model Error must have code {0} in body{1}", - ErrorCodes.Common.InvalidModel, message); - } - } -} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/CacheTestHelper.cs b/BackEnd/Timeline.Tests/IntegratedTests/CacheTestHelper.cs new file mode 100644 index 00000000..bafb2fcf --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/CacheTestHelper.cs @@ -0,0 +1,66 @@ +using FluentAssertions; +using System; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Threading.Tasks; +using Timeline.Models.Http; + +namespace Timeline.Tests.IntegratedTests +{ + public static class CacheTestHelper + { + public static async Task TestCache(HttpClient client, string getUrl) + { + EntityTagHeaderValue eTag; + { + var res = await client.GetAsync(getUrl); + res.Should().HaveStatusCode(200); + var cacheControlHeader = res.Headers.CacheControl; + cacheControlHeader.Should().NotBeNull(); + cacheControlHeader!.NoCache.Should().BeTrue(); + cacheControlHeader.NoStore.Should().BeFalse(); + cacheControlHeader.Private.Should().BeTrue(); + cacheControlHeader.Public.Should().BeFalse(); + cacheControlHeader.MustRevalidate.Should().BeTrue(); + cacheControlHeader.MaxAge.Should().NotBeNull().And.Be(TimeSpan.FromDays(14)); + res.Headers.ETag.Should().NotBeNull(); + eTag = res.Headers.ETag!; + } + + { + using var request = new HttpRequestMessage() + { + RequestUri = new Uri(client.BaseAddress!, getUrl), + Method = HttpMethod.Get, + }; + request.Headers.TryAddWithoutValidation("If-None-Match", "\"dsdfd"); + var res = await client.SendAsync(request); + await res.Should().HaveStatusCode(HttpStatusCode.BadRequest) + .And.HaveCommonBodyWithCodeAsync(ErrorCodes.Common.Header.IfNonMatch_BadFormat); + } + + { + using var request = new HttpRequestMessage() + { + RequestUri = new Uri(client.BaseAddress!, getUrl), + Method = HttpMethod.Get, + }; + request.Headers.TryAddWithoutValidation("If-None-Match", "\"aaa\""); + var res = await client.SendAsync(request); + res.Should().HaveStatusCode(HttpStatusCode.OK); + } + + { + using var request = new HttpRequestMessage() + { + RequestUri = new Uri(client.BaseAddress!, getUrl), + Method = HttpMethod.Get, + }; + request.Headers.Add("If-None-Match", eTag.ToString()); + var res = await client.SendAsync(request); + res.Should().HaveStatusCode(HttpStatusCode.NotModified); + } + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs b/BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs new file mode 100644 index 00000000..a14c8eef --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs @@ -0,0 +1,21 @@ +using System.Text.Json; +using System.Text.Json.Serialization; +using Timeline.Models.Converters; + +namespace Timeline.Tests.IntegratedTests +{ + public static class CommonJsonSerializeOptions + { + public static JsonSerializerOptions Options { get; } + + static CommonJsonSerializeOptions() + { + Options = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + Options.Converters.Add(new JsonStringEnumConverter()); + Options.Converters.Add(new JsonDateTimeConverter()); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientExtensions.cs new file mode 100644 index 00000000..9258e644 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientExtensions.cs @@ -0,0 +1,48 @@ +using System; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Net.Http.Json; +using System.Net.Mime; +using System.Text; +using System.Threading.Tasks; + +namespace Timeline.Tests.IntegratedTests +{ + public static class HttpClientExtensions + { + public static async Task PatchAsJsonAsync(this HttpClient client, string url, T body) + { + using var reqContent = JsonContent.Create(body, options: CommonJsonSerializeOptions.Options); + return await client.PatchAsync(url, reqContent); + } + + public static Task PutAsync(this HttpClient client, string url) + { + return client.PutAsync(url, null!); + } + + public static Task PutByteArrayAsync(this HttpClient client, string url, byte[] body, string mimeType) + { + return client.PutByteArrayAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); + } + + public static async Task PutByteArrayAsync(this HttpClient client, Uri url, byte[] body, string mimeType) + { + using var content = new ByteArrayContent(body); + content.Headers.ContentLength = body.Length; + content.Headers.ContentType = new MediaTypeHeaderValue(mimeType); + return await client.PutAsync(url, content); + } + + public static Task PutStringAsync(this HttpClient client, string url, string body, string? mimeType = null) + { + return client.PutStringAsync(new Uri(url, UriKind.RelativeOrAbsolute), body, mimeType); + } + + public static async Task PutStringAsync(this HttpClient client, Uri url, string body, string? mimeType = null) + { + using var content = new StringContent(body, Encoding.UTF8, mimeType ?? MediaTypeNames.Text.Plain); + return await client.PutAsync(url, content); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs new file mode 100644 index 00000000..125435f9 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTimelineExtensions.cs @@ -0,0 +1,30 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Timeline.Models.Http; + +namespace Timeline.Tests.IntegratedTests +{ + public static class HttpClientTimelineExtensions + { + public static async Task GetTimelineAsync(this HttpClient client, string timelineName) + { + var res = await client.GetAsync($"timelines/{timelineName}"); + res.Should().HaveStatusCode(HttpStatusCode.OK); + return await res.Should().HaveAndGetJsonBodyAsync(); + } + + public static async Task PatchTimelineAsync(this HttpClient client, string timelineName, TimelinePatchRequest body) + { + var res = await client.PatchAsJsonAsync($"timelines/{timelineName}", body); + res.Should().HaveStatusCode(HttpStatusCode.OK); + return await res.Should().HaveAndGetJsonBodyAsync(); + } + + public static async Task PutTimelineMemberAsync(this HttpClient client, string timelineName, string memberUsername) + { + var res = await client.PutAsync($"timelines/{timelineName}/members/{memberUsername}"); + res.Should().HaveStatusCode(HttpStatusCode.OK); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs new file mode 100644 index 00000000..0ce2325f --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientUserExtensions.cs @@ -0,0 +1,17 @@ +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Timeline.Models.Http; + +namespace Timeline.Tests.IntegratedTests +{ + public static class HttpClientUserExtensions + { + public static async Task GetUserAsync(this HttpClient client, string username) + { + var res = await client.GetAsync($"users/{username}"); + res.Should().HaveStatusCode(HttpStatusCode.OK); + return await res.Should().HaveAndGetJsonBodyAsync(); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseExtensions.cs new file mode 100644 index 00000000..097fefd1 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpResponseExtensions.cs @@ -0,0 +1,14 @@ +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading.Tasks; + +namespace Timeline.Tests.IntegratedTests +{ + public static class HttpResponseExtensions + { + public static async Task ReadBodyAsJsonAsync(this HttpResponseMessage response) + { + return await response.Content.ReadFromJsonAsync(CommonJsonSerializeOptions.Options); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs index 79d2d5bf..070b456f 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs @@ -4,10 +4,7 @@ using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Generic; using System.Net.Http; -using System.Text.Json; -using System.Text.Json.Serialization; using System.Threading.Tasks; -using Timeline.Models.Converters; using Timeline.Models.Http; using Timeline.Services; using Timeline.Tests.Helpers; @@ -19,7 +16,7 @@ namespace Timeline.Tests.IntegratedTests { protected TestApplication TestApp { get; } - private readonly int _userCount; + protected int TestUserCount { get; } public IntegratedTestBase() : this(1) { @@ -31,7 +28,7 @@ namespace Timeline.Tests.IntegratedTests if (userCount < 0) throw new ArgumentOutOfRangeException(nameof(userCount), userCount, "User count can't be negative."); - _userCount = userCount; + TestUserCount = userCount; TestApp = new TestApplication(); } @@ -65,7 +62,7 @@ namespace Timeline.Tests.IntegratedTests ("admin", "adminpw", "administrator") }; - for (int i = 1; i <= _userCount; i++) + for (int i = 1; i <= TestUserCount; i++) { users.Add(($"user{i}", $"user{i}pw", $"imuser{i}")); } diff --git a/BackEnd/Timeline.Tests/IntegratedTests/ResponseAssertions.cs b/BackEnd/Timeline.Tests/IntegratedTests/ResponseAssertions.cs new file mode 100644 index 00000000..166cde09 --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests/ResponseAssertions.cs @@ -0,0 +1,136 @@ +using FluentAssertions; +using FluentAssertions.Execution; +using FluentAssertions.Formatting; +using FluentAssertions.Primitives; +using System; +using System.Globalization; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using Timeline.Models.Http; + +namespace Timeline.Tests.IntegratedTests +{ + public class HttpResponseMessageValueFormatter : IValueFormatter + { + public bool CanHandle(object value) + { + return value is HttpResponseMessage; + } + + public string Format(object value, FormattingContext context, FormatChild formatChild) + { + string newline = context.UseLineBreaks ? Environment.NewLine : ""; + string padding = new string('\t', context.Depth); + + var res = (HttpResponseMessage)value; + return $"{newline}{padding} Status Code: {res.StatusCode}"; + } + } + + public class HttpResponseMessageAssertions + : ReferenceTypeAssertions + { + static HttpResponseMessageAssertions() + { + Formatter.AddFormatter(new HttpResponseMessageValueFormatter()); + } + + public HttpResponseMessageAssertions(HttpResponseMessage instance) + { + Subject = instance; + } + + protected override string Identifier => "HttpResponseMessage"; + + public AndConstraint HaveStatusCode(int expected, string because = "", params object[] becauseArgs) + { + return HaveStatusCode((HttpStatusCode)expected, because, becauseArgs); + } + + public AndConstraint HaveStatusCode(HttpStatusCode expected, string because = "", params object[] becauseArgs) + { + Execute.Assertion.BecauseOf(because, becauseArgs) + .ForCondition(Subject.StatusCode == expected) + .FailWith("Expected status code of {context:HttpResponseMessage} to be {0}{reason}, but found {1}.", expected, Subject.StatusCode); + return new AndConstraint(this); + } + + public async Task HaveAndGetJsonBodyAsync(string because = "", params object[] becauseArgs) + { + var a = Execute.Assertion.BecauseOf(because, becauseArgs); + + var body = await Subject.ReadBodyAsJsonAsync(); + if (body == null) + { + a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string of type {0}{reason}, but failed to read it or it was not a valid json string.", typeof(T).FullName); + return default!; + } + return body; + } + + public async Task> HaveJsonBodyAsync(string because = "", params object[] becauseArgs) + { + var a = Execute.Assertion.BecauseOf(because, becauseArgs); + + var body = await Subject.ReadBodyAsJsonAsync(); + if (body == null) + { + a.FailWith("Expected response body of {context:HttpResponseMessage} to be json string of type {0}{reason}, but failed to read it or it was not a valid json string.", typeof(T).FullName); + return new(Subject, null); + } + return new(Subject, body); + } + } + + public static class AssertionResponseExtensions + { + public static HttpResponseMessageAssertions Should(this HttpResponseMessage instance) + { + return new HttpResponseMessageAssertions(instance); + } + + public static Task HaveAndGetCommonBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + { + return assertions.HaveAndGetJsonBodyAsync(because, becauseArgs); + } + + public static async Task HaveCommonBodyWithCodeAsync(this HttpResponseMessageAssertions assertions, int code, string? message = null, params object[] messageArgs) + { + message = string.IsNullOrEmpty(message) ? "" : ", " + string.Format(CultureInfo.CurrentCulture, message, messageArgs); + var body = await assertions.HaveAndGetCommonBodyAsync("Response body should be CommonResponse{0}", message); + body.Code.Should().Be(code, "Response body code is not the specified one{0}", message); + } + + public static Task> HaveAndGetCommonDataBodyAsync(this HttpResponseMessageAssertions assertions, string because = "", params object[] becauseArgs) + { + return assertions.HaveAndGetJsonBodyAsync>(because, becauseArgs); + } + + public static async Task BePutAsync(this HttpResponseMessageAssertions assertions, bool create, string because = "", params object[] becauseArgs) + { + var body = await assertions.HaveStatusCode(create ? 201 : 200, because, becauseArgs) + .And.HaveAndGetJsonBodyAsync(because, becauseArgs); + body.Code.Should().Be(0); + body.Data.Create.Should().Be(create); + } + + public static async Task BeDeleteAsync(this HttpResponseMessageAssertions assertions, bool delete, string because = "", params object[] becauseArgs) + { + var body = await assertions.HaveStatusCode(200, because, becauseArgs) + .And.HaveAndGetJsonBodyAsync(because, becauseArgs); + body.Code.Should().Be(0); + body.Data.Delete.Should().Be(delete); + } + + public static async Task BeInvalidModelAsync(this HttpResponseMessageAssertions assertions, string? message = null) + { + message = string.IsNullOrEmpty(message) ? "" : ", " + message; + var body = await assertions.HaveStatusCode(400, "Invalid Model Error must have 400 status code{0}", message) + .And.HaveAndGetCommonBodyAsync("Invalid Model Error must have CommonResponse body{0}", message); + body.Code.Should().Be(ErrorCodes.Common.InvalidModel, + "Invalid Model Error must have code {0} in body{1}", + ErrorCodes.Common.InvalidModel, message); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs index fd574a82..e996be45 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineTest.cs @@ -9,12 +9,13 @@ using System.Globalization; using System.Linq; using System.Net; using System.Net.Http; -using System.Text; +using System.Net.Http.Json; using System.Threading.Tasks; using Timeline.Entities; using Timeline.Models; using Timeline.Models.Http; using Timeline.Tests.Helpers; +using Timeline.Tests.IntegratedTests; using Xunit; namespace Timeline.Tests.IntegratedTests @@ -59,81 +60,32 @@ namespace Timeline.Tests.IntegratedTests { for (int i = 0; i <= 3; i++) { - var client = await CreateClientAs(i); + using var client = await CreateClientAs(i); var res = await client.PostAsJsonAsync("timelines", new TimelineCreateRequest { Name = $"t{i}" }); res.Should().HaveStatusCode(200); } } - private static string CalculateUrlTail(string? subpath, ICollection>? query) + [Fact] + public async Task TimelineGet_Should_Work() { - StringBuilder result = new StringBuilder(); - if (subpath != null) + using var client = await CreateDefaultClient(); + { - if (!subpath.StartsWith("/", StringComparison.OrdinalIgnoreCase)) - result.Append('/'); - result.Append(subpath); + var res = await client.GetAsync("timelines/@!!!"); + await res.Should().BeInvalidModelAsync(); } - if (query != null && query.Count != 0) { - result.Append('?'); - foreach (var (key, value, index) in query.Select((pair, index) => (pair.Key, pair.Value, index))) - { - result.Append(WebUtility.UrlEncode(key)); - result.Append('='); - result.Append(WebUtility.UrlEncode(value)); - if (index != query.Count - 1) - result.Append('&'); - } + var res = await client.GetAsync("timelines/!!!"); + await res.Should().BeInvalidModelAsync(); } - return result.ToString(); - } - - private static string GeneratePersonalTimelineUrl(int id, string? subpath = null, ICollection>? query = null) - { - return $"timelines/@{(id == 0 ? "admin" : ("user" + id))}{CalculateUrlTail(subpath, query)}"; - } - - private static string GenerateOrdinaryTimelineUrl(int id, string? subpath = null, ICollection>? query = null) - { - return $"timelines/t{id}{CalculateUrlTail(subpath, query)}"; - } - - public delegate string TimelineUrlGenerator(int userId, string subpath = null, ICollection> query = null); - - public static IEnumerable TimelineUrlGeneratorData() - { - yield return new[] { new TimelineUrlGenerator(GeneratePersonalTimelineUrl) }; - yield return new[] { new TimelineUrlGenerator(GenerateOrdinaryTimelineUrl) }; - } - - private static string GeneratePersonalTimelineUrlByName(string name, string? subpath = null) - { - return $"timelines/@{name}{(subpath == null ? "" : "/" + subpath)}"; - } - - private static string GenerateOrdinaryTimelineUrlByName(string name, string? subpath = null) - { - return $"timelines/{name}{(subpath == null ? "" : "/" + subpath)}"; - } - - public static IEnumerable TimelineUrlByNameGeneratorData() - { - yield return new[] { new Func(GeneratePersonalTimelineUrlByName) }; - yield return new[] { new Func(GenerateOrdinaryTimelineUrlByName) }; - } - - [Fact] - public async Task TimelineGet_Should_Work() - { - using var client = await CreateDefaultClient(); { var res = await client.GetAsync("timelines/@user1"); var body = await res.Should().HaveStatusCode(200) .And.HaveAndGetJsonBodyAsync(); - body.Owner.Should().; + body.Owner.Should().BeEquivalentTo(await client.GetUserAsync("user1")); body.Visibility.Should().Be(TimelineVisibility.Register); body.Description.Should().Be(""); body.Members.Should().NotBeNull().And.BeEmpty(); @@ -145,9 +97,9 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("timelines/t1"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; - body.Owner.Should().BeEquivalentTo(UserInfos[1]); + var body = await res.Should().HaveStatusCode(200) + .And.HaveAndGetJsonBodyAsync(); + body.Owner.Should().BeEquivalentTo(await client.GetUserAsync("user1")); body.Visibility.Should().Be(TimelineVisibility.Register); body.Description.Should().Be(""); body.Members.Should().NotBeNull().And.BeEmpty(); @@ -159,33 +111,45 @@ namespace Timeline.Tests.IntegratedTests } [Fact] - public async Task TimelineList() + public async Task TimelineList_Should_Work() { - TimelineInfo user1Timeline; + using var client = await CreateDefaultClient(); - var client = await CreateDefaultClient(); + var result = new List + { + await client.GetTimelineAsync("@user1") + }; + for (int i = 0; i <= TestUserCount; i++) { - var res = await client.GetAsync("timelines/@user1"); - user1Timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + result.Add(await client.GetTimelineAsync($"t{i}")); } - { - var testResult = new List(); - testResult.Add(user1Timeline); - testResult.AddRange(_testTimelines); - var res = await client.GetAsync("timelines"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which.Should().BeEquivalentTo(testResult); - } + var res = await client.GetAsync("timelines"); + var body = res.Should().HaveStatusCode(200) + .And.HaveAndGetJsonBodyAsync>(); + + body.Should().BeEquivalentTo(result); } [Fact] - public async Task TimelineList_WithQuery() + public async Task TimelineListWithQuery_Should_Work() { + { + using var client = await CreateDefaultClient(); + + async Task TestAgainst(string url) + { + var res = await client.GetAsync(url); + await res.Should().BeInvalidModelAsync(); + } + + await TestAgainst("timelines?relate=us!!"); + await TestAgainst("timelines?relateType=aaa"); + await TestAgainst("timelines?visibility=aaa"); + } + var testResultRelate = new List(); var testResultOwn = new List(); var testResultJoin = new List(); @@ -196,32 +160,15 @@ namespace Timeline.Tests.IntegratedTests var testResultPublic = new List(); { - var client = await CreateClientAsUser(); - - { - var res = await client.PutAsync("timelines/@user1/members/user3", null); - res.Should().HaveStatusCode(200); - } - - { - var res = await client.PutAsync("timelines/t1/members/user3", null); - res.Should().HaveStatusCode(200); - } + using var client = await CreateClientAsUser(); - { - var res = await client.PatchAsJsonAsync("timelines/@user1", new TimelinePatchRequest { Visibility = TimelineVisibility.Public }); - res.Should().HaveStatusCode(200); - } + await client.PutTimelineMemberAsync("@user1", "user3"); + await client.PutTimelineMemberAsync("t1", "user3"); + await client.PatchTimelineAsync("@user1", new() { Visibility = TimelineVisibility.Public }); + await client.PatchTimelineAsync("t1", new() { Visibility = TimelineVisibility.Register }); { - var res = await client.PatchAsJsonAsync("timelines/t1", new TimelinePatchRequest { Visibility = TimelineVisibility.Register }); - res.Should().HaveStatusCode(200); - } - - { - var res = await client.GetAsync("timelines/@user1"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("@user1"); testResultRelate.Add(timeline); testResultJoin.Add(timeline); testResultRelatePublic.Add(timeline); @@ -229,9 +176,7 @@ namespace Timeline.Tests.IntegratedTests } { - var res = await client.GetAsync("timelines/t1"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("t1"); testResultRelate.Add(timeline); testResultJoin.Add(timeline); testResultRelateRegister.Add(timeline); @@ -239,41 +184,22 @@ namespace Timeline.Tests.IntegratedTests } { - var client = await CreateClientAs(2); - - { - var res = await client.PutAsync("timelines/@user2/members/user3", null); - res.Should().HaveStatusCode(200); - } - - { - var res = await client.PutAsync("timelines/t2/members/user3", null); - res.Should().HaveStatusCode(200); - } - - { - var res = await client.PatchAsJsonAsync("timelines/@user2", new TimelinePatchRequest { Visibility = TimelineVisibility.Register }); - res.Should().HaveStatusCode(200); - } + using var client = await CreateClientAs(2); - { - var res = await client.PatchAsJsonAsync("timelines/t2", new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); - res.Should().HaveStatusCode(200); - } + await client.PutTimelineMemberAsync("@user2", "user3"); + await client.PutTimelineMemberAsync("t2", "user3"); + await client.PatchTimelineAsync("@user2", new() { Visibility = TimelineVisibility.Register }); + await client.PatchTimelineAsync("t2", new() { Visibility = TimelineVisibility.Private }); { - var res = await client.GetAsync("timelines/@user2"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("@user2"); testResultRelate.Add(timeline); testResultJoin.Add(timeline); testResultRelateRegister.Add(timeline); } { - var res = await client.GetAsync("timelines/t2"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("t2"); testResultRelate.Add(timeline); testResultJoin.Add(timeline); testResultJoinPrivate.Add(timeline); @@ -281,31 +207,19 @@ namespace Timeline.Tests.IntegratedTests } { - var client = await CreateClientAs(3); - - { - var res = await client.PatchAsJsonAsync("timelines/@user3", new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); - res.Should().HaveStatusCode(200); - } - - { - var res = await client.PatchAsJsonAsync("timelines/t3", new TimelinePatchRequest { Visibility = TimelineVisibility.Register }); - res.Should().HaveStatusCode(200); - } + using var client = await CreateClientAs(3); + await client.PatchTimelineAsync("@user3", new TimelinePatchRequest { Visibility = TimelineVisibility.Private }); + await client.PatchTimelineAsync("t3", new TimelinePatchRequest { Visibility = TimelineVisibility.Register }); { - var res = await client.GetAsync("timelines/@user3"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("@user3"); testResultRelate.Add(timeline); testResultOwn.Add(timeline); testResultOwnPrivate.Add(timeline); } { - var res = await client.GetAsync("timelines/t3"); - var timeline = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; + var timeline = await client.GetTimelineAsync("t3"); testResultRelate.Add(timeline); testResultOwn.Add(timeline); testResultRelateRegister.Add(timeline); @@ -313,86 +227,23 @@ namespace Timeline.Tests.IntegratedTests } { - var client = await CreateClientAs(3); - { - var res = await client.GetAsync("timelines?relate=user3"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultRelate); - } - - { - var res = await client.GetAsync("timelines?relate=user3&relateType=own"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultOwn); - } - - { - var res = await client.GetAsync("timelines?relate=user3&visibility=public"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultRelatePublic); - } - - { - var res = await client.GetAsync("timelines?relate=user3&visibility=register"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultRelateRegister); - } + using var client = await CreateDefaultClient(); + async Task TestAgainst(string url, List against) { - var res = await client.GetAsync("timelines?relate=user3&relateType=join&visibility=private"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultJoinPrivate); + var res = await client.GetAsync(url); + var body = await res.Should().HaveStatusCode(200) + .And.HaveAndGetJsonBodyAsync>(); + body.Should().BeEquivalentTo(against); } - { - var res = await client.GetAsync("timelines?relate=user3&relateType=own&visibility=private"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultOwnPrivate); - } - } - - { - var client = await CreateDefaultClient(); - { - var res = await client.GetAsync("timelines?visibility=public"); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody>() - .Which; - body.Should().BeEquivalentTo(testResultPublic); - } - } - } - - [Fact] - public async Task TimelineList_InvalidModel() - { - var client = await CreateClientAsUser(); - - { - var res = await client.GetAsync("timelines?relate=us!!"); - res.Should().BeInvalidModel(); - } - - { - var res = await client.GetAsync("timelines?relateType=aaa"); - res.Should().BeInvalidModel(); - } - - { - var res = await client.GetAsync("timelines?visibility=aaa"); - res.Should().BeInvalidModel(); + await TestAgainst("timelines?relate=user3", testResultRelate); + await TestAgainst("timelines?relate=user3&relateType=own", testResultOwn); + await TestAgainst("timelines?relate=user3&visibility=public", testResultRelatePublic); + await TestAgainst("timelines?relate=user3&visibility=register", testResultRelateRegister); + await TestAgainst("timelines?relate=user3&relateType=join&visibility=private", testResultJoinPrivate); + await TestAgainst("timelines?relate=user3&relateType=own&visibility=private", testResultOwnPrivate); + await TestAgainst("timelines?visibility=public", testResultPublic); } } @@ -405,31 +256,25 @@ namespace Timeline.Tests.IntegratedTests res.Should().HaveStatusCode(HttpStatusCode.Unauthorized); } - using (var client = await CreateClientAsUser()) { + using var client = await CreateClientAsUser(); + { var res = await client.PostAsJsonAsync("timelines", new TimelineCreateRequest { Name = "!!!" }); - res.Should().BeInvalidModel(); + await res.Should().BeInvalidModelAsync(); } - TimelineInfo timelineInfo; { var res = await client.PostAsJsonAsync("timelines", new TimelineCreateRequest { Name = "aaa" }); - timelineInfo = res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which; - } - - { - var res = await client.GetAsync("timelines/aaa"); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody() - .Which.Should().BeEquivalentTo(timelineInfo); + var body = await res.Should().HaveStatusCode(200) + .And.HaveAndGetJsonBodyAsync(); + body.Should().BeEquivalentTo(await client.GetTimelineAsync("aaa")); } { var res = await client.PostAsJsonAsync("timelines", new TimelineCreateRequest { Name = "aaa" }); - res.Should().HaveStatusCode(400) - .And.HaveCommonBody(ErrorCodes.TimelineController.NameConflict); + await res.Should().HaveStatusCode(400) + .And.HaveCommonBodyWithCodeAsync(ErrorCodes.TimelineController.NameConflict); } } } @@ -454,17 +299,17 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.DeleteAsync("timelines/!!!"); - res.Should().BeInvalidModel(); + await res.Should().BeInvalidModelAsync(); } { var res = await client.DeleteAsync("timelines/t2"); - res.Should().BeDelete(true); + await res.Should().BeDeleteAsync(true); } { var res = await client.DeleteAsync("timelines/t2"); - res.Should().BeDelete(false); + await res.Should().BeDeleteAsync(false); } } @@ -473,12 +318,12 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.DeleteAsync("timelines/!!!"); - res.Should().BeInvalidModel(); + await res.Should().BeInvalidModelAsync(); } { var res = await client.DeleteAsync("timelines/t1"); - res.Should().BeDelete(true); + await res.Should().BeDeleteAsync(true); } { @@ -489,122 +334,47 @@ namespace Timeline.Tests.IntegratedTests } [Theory] - [MemberData(nameof(TimelineUrlByNameGeneratorData))] - public async Task InvalidModel_BadName(Func generator) + [InlineData("@user1")] + [InlineData("t1")] + public async Task TimelineDescription_Should_Work(string timelineName) { - using var client = await CreateClientAsAdministrator(); - { - var res = await client.GetAsync(generator("aaa!!!", null)); - res.Should().BeInvalidModel(); - } - { - var res = await client.PatchAsJsonAsync(generator("aaa!!!", null), new TimelinePatchRequest { }); - res.Should().BeInvalidModel(); - } - { - var res = await client.PutAsync(generator("aaa!!!", "members/user1"), null); - res.Should().BeInvalidModel(); - } - { - var res = await client.DeleteAsync(generator("aaa!!!", "members/user1")); - res.Should().BeInvalidModel(); - } - { - var res = await client.GetAsync(generator("aaa!!!", "posts")); - res.Should().BeInvalidModel(); - } - { - var res = await client.PostAsJsonAsync(generator("aaa!!!", "posts"), TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().BeInvalidModel(); - } - { - var res = await client.DeleteAsync(generator("aaa!!!", "posts/123")); - res.Should().BeInvalidModel(); - } + using var client = await CreateClientAsUser(); + { - var res = await client.GetAsync(generator("aaa!!!", "posts/123/data")); - res.Should().BeInvalidModel(); + var timeline = await client.GetTimelineAsync(timelineName); + timeline.Description.Should().BeEmpty(); } - } - [Theory] - [MemberData(nameof(TimelineUrlByNameGeneratorData))] - public async Task Ordinary_NotFound(Func generator) - { - var errorCode = generator == GenerateOrdinaryTimelineUrlByName ? ErrorCodes.TimelineController.NotExist : ErrorCodes.UserCommon.NotExist; + const string mockDescription = "haha"; - using var client = await CreateClientAsAdministrator(); - { - var res = await client.GetAsync(generator("notexist", null)); - res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode); - } { - var res = await client.PatchAsJsonAsync(generator("notexist", null), new TimelinePatchRequest { }); - res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode); - } - { - var res = await client.PutAsync(generator("notexist", "members/user1"), null); - res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode); - } - { - var res = await client.DeleteAsync(generator("notexist", "members/user1")); - res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode); - } - { - var res = await client.GetAsync(generator("notexist", "posts")); - res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode); - } - { - var res = await client.PostAsJsonAsync(generator("notexist", "posts"), TimelineHelper.TextPostCreateRequest("aaa")); - res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode); - } - { - var res = await client.DeleteAsync(generator("notexist", "posts/123")); - res.Should().HaveStatusCode(400).And.HaveCommonBody(errorCode); + var timeline = await client.PatchTimelineAsync(timelineName, new() { Description = mockDescription }); + timeline.Description.Should().Be(mockDescription); } + { - var res = await client.GetAsync(generator("notexist", "posts/123/data")); - res.Should().HaveStatusCode(404).And.HaveCommonBody(errorCode); + var timeline = await client.GetTimelineAsync(timelineName); + timeline.Description.Should().Be(mockDescription); } - } - - [Theory] - [MemberData(nameof(TimelineUrlGeneratorData))] - public async Task Description_Should_Work(TimelineUrlGenerator generator) - { - using var client = await CreateClientAsUser(); - async Task AssertDescription(string description) { - var res = await client.GetAsync(generator(1, null)); - var body = res.Should().HaveStatusCode(200) - .And.HaveJsonBody() - .Which.Description.Should().Be(description); + var timeline = await client.PatchTimelineAsync(timelineName, new() { Description = null }); + timeline.Description.Should().Be(mockDescription); } - const string mockDescription = "haha"; - - await AssertDescription(""); { - var res = await client.PatchAsJsonAsync(generator(1, null), - new TimelinePatchRequest { Description = mockDescription }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which.Description.Should().Be(mockDescription); - await AssertDescription(mockDescription); + var timeline = await client.GetTimelineAsync(timelineName); + timeline.Description.Should().Be(mockDescription); } + { - var res = await client.PatchAsJsonAsync(generator(1, null), - new TimelinePatchRequest { Description = null }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which.Description.Should().Be(mockDescription); - await AssertDescription(mockDescription); + var timeline = await client.PatchTimelineAsync(timelineName, new() { Description = "" }); + timeline.Description.Should().BeEmpty(); } + { - var res = await client.PatchAsJsonAsync(generator(1, null), - new TimelinePatchRequest { Description = "" }); - res.Should().HaveStatusCode(200) - .And.HaveJsonBody().Which.Description.Should().Be(""); - await AssertDescription(""); + var timeline = await client.GetTimelineAsync(timelineName); + timeline.Description.Should().BeEmpty(); } } diff --git a/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs index cf27a6c6..80f31be9 100644 --- a/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs +++ b/BackEnd/Timeline.Tests/IntegratedTests/UserPermissionTest.cs @@ -3,10 +3,10 @@ using System; using System.Collections.Generic; using System.Linq; using System.Net; -using System.Net.Http.Json; using System.Threading.Tasks; using Timeline.Models.Http; using Timeline.Services; +using Timeline.Tests.Helpers; using Xunit; namespace Timeline.Tests.IntegratedTests @@ -21,7 +21,7 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateDefaultClient(); var res = await client.GetAsync("users/admin"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); } @@ -31,7 +31,7 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateDefaultClient(); var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEmpty(); } @@ -54,19 +54,19 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/admin"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); } { - var res = await client.PutAsync($"users/admin/permissions/{permission}", null); + var res = await client.PutAsync($"users/admin/permissions/{permission}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/admin"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(Enum.GetNames()); } } @@ -78,14 +78,14 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsAdministrator(); { - var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + var res = await client.PutAsync($"users/user1/permissions/{permission}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(permission.ToString()); } @@ -97,7 +97,7 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEmpty(); } } @@ -109,26 +109,26 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsAdministrator(); { - var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + var res = await client.PutAsync($"users/user1/permissions/{permission}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(permission.ToString()); } { - var res = await client.PutAsync($"users/user1/permissions/{permission}", null); + var res = await client.PutAsync($"users/user1/permissions/{permission}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(permission.ToString()); } } @@ -147,7 +147,7 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEmpty(); } } @@ -158,39 +158,39 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsAdministrator(); { - var res = await client.PutAsync($"users/user1/permissions/{UserPermission.AllTimelineManagement}", null); + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.AllTimelineManagement}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(UserPermission.AllTimelineManagement.ToString()); } { - var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}", null); + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(UserPermission.AllTimelineManagement.ToString(), UserPermission.HighlightTimelineManangement.ToString()); } { - var res = await client.PutAsync($"users/user1/permissions/{UserPermission.UserManagement}", null); + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.UserManagement}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo( UserPermission.AllTimelineManagement.ToString(), UserPermission.HighlightTimelineManangement.ToString(), @@ -205,7 +205,7 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo( UserPermission.AllTimelineManagement.ToString(), UserPermission.UserManagement.ToString()); @@ -219,19 +219,19 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(UserPermission.UserManagement.ToString()); } { - var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}", null); + var res = await client.PutAsync($"users/user1/permissions/{UserPermission.HighlightTimelineManangement}"); res.StatusCode.Should().Be(HttpStatusCode.OK); } { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo( UserPermission.HighlightTimelineManangement.ToString(), UserPermission.UserManagement.ToString()); } @@ -244,7 +244,7 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEquivalentTo(UserPermission.UserManagement.ToString()); } @@ -256,7 +256,7 @@ namespace Timeline.Tests.IntegratedTests { var res = await client.GetAsync("users/user1"); res.StatusCode.Should().Be(HttpStatusCode.OK); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetJsonBodyAsync(); body.Permissions.Should().BeEmpty(); } } @@ -269,16 +269,16 @@ namespace Timeline.Tests.IntegratedTests using var client = await CreateClientAsAdministrator(); { - var res = await client.PutAsync(url, null); + var res = await client.PutAsync(url); res.StatusCode.Should().Be(HttpStatusCode.BadRequest); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetCommonBodyAsync(); body.Code.Should().Be(ErrorCodes.Common.InvalidModel); } { var res = await client.DeleteAsync(url); res.StatusCode.Should().Be(HttpStatusCode.BadRequest); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetCommonBodyAsync(); body.Code.Should().Be(ErrorCodes.Common.InvalidModel); } } @@ -291,16 +291,16 @@ namespace Timeline.Tests.IntegratedTests const string url = "users/user123/permissions/UserManagement"; { - var res = await client.PutAsync(url, null); + var res = await client.PutAsync(url); res.StatusCode.Should().Be(HttpStatusCode.NotFound); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetCommonBodyAsync(); body.Code.Should().Be(ErrorCodes.UserCommon.NotExist); } { var res = await client.DeleteAsync(url); res.StatusCode.Should().Be(HttpStatusCode.NotFound); - var body = await res.Content.ReadFromJsonAsync(); + var body = await res.Should().HaveAndGetCommonBodyAsync(); body.Code.Should().Be(ErrorCodes.UserCommon.NotExist); } } -- cgit v1.2.3