aboutsummaryrefslogtreecommitdiff
path: root/BackEnd
diff options
context:
space:
mode:
Diffstat (limited to 'BackEnd')
-rw-r--r--BackEnd/Timeline.Tests/Helpers/CommonJsonSerializeOptions.cs (renamed from BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs)2
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests/HttpClientTestExtensions.cs3
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/HttpClientTestExtensions.cs52
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/IntegratedTestBase.cs133
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests2/TimelineTest.cs34
-rw-r--r--BackEnd/Timeline.Tests/Timeline.Tests.csproj6
-rw-r--r--BackEnd/Timeline/Controllers/TimelineV2Controller.cs18
7 files changed, 239 insertions, 9 deletions
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs b/BackEnd/Timeline.Tests/Helpers/CommonJsonSerializeOptions.cs
index a14c8eef..a7d6d01f 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests/CommonJsonSerializeOptions.cs
+++ b/BackEnd/Timeline.Tests/Helpers/CommonJsonSerializeOptions.cs
@@ -2,7 +2,7 @@
using System.Text.Json.Serialization;
using Timeline.Models.Converters;
-namespace Timeline.Tests.IntegratedTests
+namespace Timeline.Tests.Helpers
{
public static class CommonJsonSerializeOptions
{
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTestExtensions.cs b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTestExtensions.cs
index 9848564f..c66baafc 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTestExtensions.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests/HttpClientTestExtensions.cs
@@ -6,7 +6,8 @@ using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Threading.Tasks;
using Timeline.Models.Http;
-
+using Timeline.Tests.Helpers;
+
namespace Timeline.Tests.IntegratedTests
{
public delegate void HeaderSetup(HttpRequestHeaders requestHeaders, HttpContentHeaders? contentHeaders);
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<HttpResponseMessage> 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<T> AssertJsonBodyAsync<T>(HttpResponseMessage response)
+ {
+ var body = await response.Content.ReadFromJsonAsync<T>(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<T> TestJsonSendAsync<T>(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<T>(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<IUserService>();
+ var userPermissionService = scope.ServiceProvider.GetRequiredService<IUserPermissionService>();
+
+ var admin = await userService.CreateUserAsync(new CreateUserParams("admin", "adminpw"));
+ foreach (var permission in Enum.GetValues<UserPermission>())
+ {
+ 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<IUserService>();
+ 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<string> CreateTokenWithCredentialAsync(string username, string password)
+ {
+ var client = CreateDefaultClient();
+ var res = await client.TestJsonSendAsync<HttpCreateTokenResponse>(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<HttpTimeline>(HttpMethod.Post, "v2/timelines", new HttpTimelineCreateRequest
+ {
+ Name = "hello"
+ }, expectedStatusCode: HttpStatusCode.Created);
+
+ var b = await client.TestJsonSendAsync<HttpTimeline>(HttpMethod.Get, "v2/timelines/user/hello");
+
+ a.Name.Should().Be(b.Name);
+ a.UniqueId.Should().Be(b.UniqueId);
+ }
+ }
+}
+
diff --git a/BackEnd/Timeline.Tests/Timeline.Tests.csproj b/BackEnd/Timeline.Tests/Timeline.Tests.csproj
index 82dc4d6a..4d4d3da2 100644
--- a/BackEnd/Timeline.Tests/Timeline.Tests.csproj
+++ b/BackEnd/Timeline.Tests/Timeline.Tests.csproj
@@ -29,4 +29,10 @@
<ItemGroup>
<ProjectReference Include="..\Timeline\Timeline.csproj" />
</ItemGroup>
+ <ItemGroup>
+ <None Remove="V2\" />
+ </ItemGroup>
+ <ItemGroup>
+ <Folder Include="IntegratedTests2\" />
+ </ItemGroup>
</Project>
diff --git a/BackEnd/Timeline/Controllers/TimelineV2Controller.cs b/BackEnd/Timeline/Controllers/TimelineV2Controller.cs
index c82fde2b..63beb357 100644
--- a/BackEnd/Timeline/Controllers/TimelineV2Controller.cs
+++ b/BackEnd/Timeline/Controllers/TimelineV2Controller.cs
@@ -2,6 +2,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+using Timeline.Entities;
using Timeline.Models.Http;
using Timeline.Models.Validation;
using Timeline.Services.Mapper;
@@ -16,23 +17,26 @@ namespace Timeline.Controllers
{
private ITimelineService _timelineService;
private IGenericMapper _mapper;
- private TimelineMapper _timelineMapper;
private IUserService _userService;
- public TimelineV2Controller(ITimelineService timelineService, IGenericMapper mapper, TimelineMapper timelineMapper, IUserService userService)
+ public TimelineV2Controller(ITimelineService timelineService, IGenericMapper mapper, IUserService userService)
{
_timelineService = timelineService;
_mapper = mapper;
- _timelineMapper = timelineMapper;
_userService = userService;
}
+ private Task<HttpTimeline> MapAsync(TimelineEntity entity)
+ {
+ return _mapper.MapAsync<HttpTimeline>(entity, Url, User);
+ }
+
[HttpGet("{owner}/{timeline}")]
public async Task<ActionResult<HttpTimeline>> GetAsync([FromRoute][Username] string owner, [FromRoute][TimelineName] string timeline)
{
var timelineId = await _timelineService.GetTimelineIdAsync(owner, timeline);
var t = await _timelineService.GetTimelineAsync(timelineId);
- return await _timelineMapper.MapAsync(t, Url, User);
+ return await MapAsync(t);
}
[HttpPatch("{owner}/{timeline}")]
@@ -51,7 +55,7 @@ namespace Timeline.Controllers
}
await _timelineService.ChangePropertyAsync(timelineId, _mapper.AutoMapperMap<TimelineChangePropertyParams>(body));
var t = await _timelineService.GetTimelineAsync(timelineId);
- return await _timelineMapper.MapAsync(t, Url, User);
+ return await MapAsync(t);
}
[HttpDelete("{owner}/{timeline}")]
@@ -123,8 +127,8 @@ namespace Timeline.Controllers
var authUserId = GetAuthUserId();
var authUser = await _userService.GetUserAsync(authUserId);
var timeline = await _timelineService.CreateTimelineAsync(authUserId, body.Name);
- var result = await _timelineMapper.MapAsync(timeline, Url, User);
- return CreatedAtAction(nameof(GetAsync), new { owner = authUser.Username, timeline = body.Name }, result);
+ var result = await MapAsync(timeline);
+ return CreatedAtAction("Get", new { owner = authUser.Username, timeline = body.Name }, result);
}
}
}