From 27e1360ffe4b2f5aa7d240e1de88c5459587b489 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 8 Apr 2022 17:39:07 +0800 Subject: ... --- .../IntegratedTests2/HttpClientTestExtensions.cs | 52 ++++++++ .../IntegratedTests2/IntegratedTestBase.cs | 133 +++++++++++++++++++++ .../IntegratedTests2/TimelineTest.cs | 34 ++++++ 3 files changed, 219 insertions(+) create mode 100644 BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests2/IntegratedTestBase.cs create mode 100644 BackEnd/Timeline.Tests/IntegratedTests2/TimelineTest.cs (limited to 'BackEnd/Timeline.Tests/IntegratedTests2') diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs new file mode 100644 index 00000000..0124b72a --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs @@ -0,0 +1,52 @@ +using FluentAssertions; +using System; +using System.Net; +using System.Net.Http; +using System.Net.Http.Json; +using System.Threading.Tasks; +using Timeline.Models.Http; +using Timeline.Tests.Helpers; + +namespace Timeline.Tests.IntegratedTests2 +{ + public delegate Task RequestSetupAsync(HttpRequestMessage httpRequest); + + public static class HttpClientTestExtensions + { + public static async Task TestSendAsync(this HttpClient client, HttpMethod method, string url, HttpContent? body = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null) + { + using var req = new HttpRequestMessage + { + Method = method, + RequestUri = new Uri(url, UriKind.Relative), + Content = body + }; + var task = requestSetup?.Invoke(req); + if (task is not null) await task; + var res = await client.SendAsync(req); + res.StatusCode.Should().Be(expectedStatusCode); + return res; + } + + public static async Task AssertJsonBodyAsync(HttpResponseMessage response) + { + var body = await response.Content.ReadFromJsonAsync(CommonJsonSerializeOptions.Options); + body.Should().NotBeNull($"Body is not json format of type {typeof(T).FullName}"); + return body!; + } + + public static async Task TestJsonSendAsync(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null) + { + using JsonContent? reqContent = jsonBody is null ? null : JsonContent.Create(jsonBody, options: CommonJsonSerializeOptions.Options); + await client.TestSendAsync(method, url, reqContent, expectedStatusCode, requestSetup); + } + + public static async Task TestJsonSendAsync(this HttpClient client, HttpMethod method, string url, object? jsonBody = null, HttpStatusCode expectedStatusCode = HttpStatusCode.OK, RequestSetupAsync? requestSetup = null) + { + using JsonContent? reqContent = jsonBody == null ? null : JsonContent.Create(jsonBody, options: CommonJsonSerializeOptions.Options); + var res = await client.TestSendAsync(method, url, reqContent, expectedStatusCode, requestSetup); + var resBody = await AssertJsonBodyAsync(res); + return resBody; + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/IntegratedTestBase.cs b/BackEnd/Timeline.Tests/IntegratedTests2/IntegratedTestBase.cs new file mode 100644 index 00000000..1d01fd0e --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests2/IntegratedTestBase.cs @@ -0,0 +1,133 @@ +using Microsoft.AspNetCore.TestHost; +using Microsoft.Extensions.DependencyInjection; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading.Tasks; +using Timeline.Models.Http; +using Timeline.Services.User; +using Timeline.Tests.Helpers; +using Xunit; +using Xunit.Abstractions; + +namespace Timeline.Tests.IntegratedTests2 +{ + public abstract class IntegratedTestBase : IAsyncLifetime + { + protected TestApplication TestApp { get; } + + protected int TestUserCount { get; } + + protected string NormalUserToken { get; set; } = default!; + protected string AdminUserToken { get; set; } = default!; + + public IntegratedTestBase(ITestOutputHelper testOutputHelper) : this(1, testOutputHelper) + { + + } + + public IntegratedTestBase(int userCount, ITestOutputHelper testOutputHelper) + { + if (userCount < 0) + throw new ArgumentOutOfRangeException(nameof(userCount), userCount, "User count can't be negative."); + + TestUserCount = userCount; + + TestApp = new TestApplication(testOutputHelper); + } + + protected virtual Task OnInitializeAsync() + { + return Task.CompletedTask; + } + + protected virtual Task OnDisposeAsync() + { + return Task.CompletedTask; + } + + protected virtual void OnInitialize() + { + + } + + protected virtual void OnDispose() + { + + } + + private async Task CreateInitUsersAsync() + { + using var scope = TestApp.Host.Services.CreateScope(); + + var userService = scope.ServiceProvider.GetRequiredService(); + var userPermissionService = scope.ServiceProvider.GetRequiredService(); + + var admin = await userService.CreateUserAsync(new CreateUserParams("admin", "adminpw")); + foreach (var permission in Enum.GetValues()) + { + await userPermissionService.AddPermissionToUserAsync(admin.Id, permission); + } + await userService.CreateUserAsync(new CreateUserParams("user", "userpw")); + } + + public async Task CreateUserAsync(string username, string password) + { + using var scope = TestApp.Host.Services.CreateScope(); + var userService = scope.ServiceProvider.GetRequiredService(); + await userService.CreateUserAsync(new CreateUserParams(username, password)); + } + + public async Task InitializeAsync() + { + await TestApp.InitializeAsync(); + await CreateInitUsersAsync(); + NormalUserToken = await CreateTokenWithCredentialAsync("user", "userpw"); + AdminUserToken = await CreateTokenWithCredentialAsync("admin", "adminpw"); + await OnInitializeAsync(); + OnInitialize(); + } + + public async Task DisposeAsync() + { + await OnDisposeAsync(); + OnDispose(); + await TestApp.DisposeAsync(); + } + + public HttpClient CreateDefaultClient(bool setApiBase = true) + { + var client = TestApp.Host.GetTestServer().CreateClient(); + if (setApiBase) + { + client.BaseAddress = new Uri(client.BaseAddress!, "api/"); + } + return client; + } + + public async Task CreateTokenWithCredentialAsync(string username, string password) + { + var client = CreateDefaultClient(); + var res = await client.TestJsonSendAsync(HttpMethod.Post, "token/create", + new HttpCreateTokenRequest { Username = username, Password = password }); + return res.Token; + } + + public HttpClient CreateClientWithToken(string token, bool setApiBase = true) + { + var client = CreateDefaultClient(setApiBase); + client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token); + return client; + } + + public HttpClient CreateClientAsAdmin() + { + return CreateClientWithToken(AdminUserToken); + } + + public HttpClient CreateClientAsUser() + { + return CreateClientWithToken(NormalUserToken); + } + } +} diff --git a/BackEnd/Timeline.Tests/IntegratedTests2/TimelineTest.cs b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineTest.cs new file mode 100644 index 00000000..19ad315e --- /dev/null +++ b/BackEnd/Timeline.Tests/IntegratedTests2/TimelineTest.cs @@ -0,0 +1,34 @@ +using System; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; +using FluentAssertions; +using Timeline.Models.Http; +using Xunit; +using Xunit.Abstractions; + +namespace Timeline.Tests.IntegratedTests2 +{ + public class TimelineTest : IntegratedTestBase + { + public TimelineTest(ITestOutputHelper testOutput) : base(testOutput) + { + } + + [Fact] + public async Task CreateAndGet() + { + using var client = CreateClientAsUser(); + var a = await client.TestJsonSendAsync(HttpMethod.Post, "v2/timelines", new HttpTimelineCreateRequest + { + Name = "hello" + }, expectedStatusCode: HttpStatusCode.Created); + + var b = await client.TestJsonSendAsync(HttpMethod.Get, "v2/timelines/user/hello"); + + a.Name.Should().Be(b.Name); + a.UniqueId.Should().Be(b.UniqueId); + } + } +} + -- cgit v1.2.3