aboutsummaryrefslogtreecommitdiff
path: root/BackEnd/Timeline.Tests
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2021-05-15 16:01:21 +0800
committercrupest <crupest@outlook.com>2021-05-15 16:01:21 +0800
commit49b0cb7b465561447b8d4693ba988b13e0e1b57a (patch)
tree4c533d940af0b2691619a960f439f5f33129a9ff /BackEnd/Timeline.Tests
parent741230818e8c8093f7ead04c7df1c21a17cceae4 (diff)
downloadtimeline-49b0cb7b465561447b8d4693ba988b13e0e1b57a.tar.gz
timeline-49b0cb7b465561447b8d4693ba988b13e0e1b57a.tar.bz2
timeline-49b0cb7b465561447b8d4693ba988b13e0e1b57a.zip
feat: Timeline post change notification with signalr.
Diffstat (limited to 'BackEnd/Timeline.Tests')
-rw-r--r--BackEnd/Timeline.Tests/Helpers/TestApplication.cs7
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs16
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests/TimelineHubTest.cs82
-rw-r--r--BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs2
-rw-r--r--BackEnd/Timeline.Tests/Timeline.Tests.csproj1
-rw-r--r--BackEnd/Timeline.Tests/packages.lock.json83
6 files changed, 188 insertions, 3 deletions
diff --git a/BackEnd/Timeline.Tests/Helpers/TestApplication.cs b/BackEnd/Timeline.Tests/Helpers/TestApplication.cs
index e0db966c..723ef500 100644
--- a/BackEnd/Timeline.Tests/Helpers/TestApplication.cs
+++ b/BackEnd/Timeline.Tests/Helpers/TestApplication.cs
@@ -1,6 +1,8 @@
using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Collections.Generic;
using System.IO;
@@ -46,5 +48,10 @@ namespace Timeline.Tests.Helpers
Directory.Delete(WorkDirectory, true);
}
+
+ public TestServer Server
+ {
+ get => (TestServer)Host.Services.GetRequiredService<IServer>();
+ }
}
}
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs
index 588f2f93..259ebfa1 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests/IntegratedTestBase.cs
@@ -105,6 +105,14 @@ namespace Timeline.Tests.IntegratedTests
return Task.FromResult(client);
}
+ public async Task<string> CreateTokenWithCredentialAsync(string username, string password)
+ {
+ var client = await CreateDefaultClient();
+ var res = await client.TestPostAsync<HttpCreateTokenResponse>("token/create",
+ new HttpCreateTokenRequest { Username = username, Password = password });
+ return res.Token;
+ }
+
public async Task<HttpClient> CreateClientWithCredential(string username, string password, bool setApiBase = true)
{
var client = await CreateDefaultClient(setApiBase);
@@ -115,6 +123,14 @@ namespace Timeline.Tests.IntegratedTests
return client;
}
+ public Task<string> CreateTokenAsync(int userNumber)
+ {
+ if (userNumber == 0)
+ return CreateTokenWithCredentialAsync("admin", "adminpw");
+ else
+ return CreateTokenWithCredentialAsync($"user{userNumber}", $"user{userNumber}pw");
+ }
+
public Task<HttpClient> CreateClientAs(int userNumber, bool setApiBase = true)
{
if (userNumber < 0)
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelineHubTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelineHubTest.cs
new file mode 100644
index 00000000..66df74d7
--- /dev/null
+++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelineHubTest.cs
@@ -0,0 +1,82 @@
+using FluentAssertions;
+using Microsoft.AspNetCore.SignalR.Client;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Timeline.SignalRHub;
+using Xunit;
+
+namespace Timeline.Tests.IntegratedTests
+{
+ public class TimelineHubTest : BaseTimelineTest
+ {
+ private HubConnection CreateConnection(string? token)
+ {
+ return new HubConnectionBuilder().WithUrl($"http://localhost/api/hub/timeline{(token is null ? "" : "?token=" + token)}",
+ options => options.HttpMessageHandlerFactory = _ => TestApp.Server.CreateHandler()).Build();
+ }
+
+ [Theory]
+ [MemberData(nameof(TimelineNameGeneratorTestData))]
+ public async Task TimelinePostUpdate_Should_Work(TimelineNameGenerator generator)
+ {
+ var token = await CreateTokenAsync(1);
+
+ await using var connection = CreateConnection(token);
+
+ var changed = false;
+
+ connection.On<string>(nameof(ITimelineClient.OnTimelinePostChanged), (timelineName) =>
+ {
+ timelineName.Should().Be(generator(1));
+ changed = true;
+ });
+
+ await connection.StartAsync();
+ connection.State.Should().Be(HubConnectionState.Connected);
+
+ using var client = await CreateClientAsUser();
+
+ await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelinePostTest.CreateTextPostRequest("aaa"));
+ changed.Should().BeFalse();
+
+ await connection.InvokeAsync(nameof(TimelineHub.SubscribeTimelinePostChange), generator(1));
+
+ await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelinePostTest.CreateTextPostRequest("bbb"));
+ changed.Should().BeTrue();
+
+ changed = false;
+
+ await connection.InvokeAsync(nameof(TimelineHub.UnsubscribeTimelinePostChange), generator(1));
+
+ await client.TestPostAsync($"timelines/{generator(1)}/posts", TimelinePostTest.CreateTextPostRequest("ccc"));
+ changed.Should().BeFalse();
+ }
+
+ [Fact]
+ public async Task TimelinePostUpdate_InvalidName()
+ {
+ await using var connection = CreateConnection(null);
+ await connection.StartAsync();
+ await connection.Awaiting(c => c.InvokeAsync(nameof(TimelineHub.SubscribeTimelinePostChange), "!!!")).Should().ThrowAsync<Exception>();
+ }
+
+ [Fact]
+ public async Task TimelinePostUpdate_NotExist()
+ {
+ await using var connection = CreateConnection(null);
+ await connection.StartAsync();
+ await connection.Awaiting(c => c.InvokeAsync(nameof(TimelineHub.SubscribeTimelinePostChange), "timelinenotexist")).Should().ThrowAsync<Exception>();
+ }
+
+ [Fact]
+ public async Task TimelinePostUpdate_Forbid()
+ {
+ await using var connection = CreateConnection(null);
+ await connection.StartAsync();
+ await connection.Awaiting(c => c.InvokeAsync(nameof(TimelineHub.SubscribeTimelinePostChange), "t1")).Should().ThrowAsync<Exception>();
+ }
+ }
+}
+
diff --git a/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs b/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
index 097275b0..ab8f6f66 100644
--- a/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
+++ b/BackEnd/Timeline.Tests/IntegratedTests/TimelinePostTest.cs
@@ -19,7 +19,7 @@ namespace Timeline.Tests.IntegratedTests
{
public class TimelinePostTest : BaseTimelineTest
{
- private static HttpTimelinePostCreateRequest CreateTextPostRequest(string text, DateTime? time = null, string? color = null)
+ public static HttpTimelinePostCreateRequest CreateTextPostRequest(string text, DateTime? time = null, string? color = null)
{
return new HttpTimelinePostCreateRequest()
{
diff --git a/BackEnd/Timeline.Tests/Timeline.Tests.csproj b/BackEnd/Timeline.Tests/Timeline.Tests.csproj
index 4a07024c..127a6b9a 100644
--- a/BackEnd/Timeline.Tests/Timeline.Tests.csproj
+++ b/BackEnd/Timeline.Tests/Timeline.Tests.csproj
@@ -14,6 +14,7 @@
</PackageReference>
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
+ <PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.6" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="5.0.5" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
<PackageReference Include="Moq" Version="4.16.1" />
diff --git a/BackEnd/Timeline.Tests/packages.lock.json b/BackEnd/Timeline.Tests/packages.lock.json
index 6a445ddc..be424c80 100644
--- a/BackEnd/Timeline.Tests/packages.lock.json
+++ b/BackEnd/Timeline.Tests/packages.lock.json
@@ -27,6 +27,16 @@
"Newtonsoft.Json.Bson": "1.0.1"
}
},
+ "Microsoft.AspNetCore.SignalR.Client": {
+ "type": "Direct",
+ "requested": "[5.0.6, )",
+ "resolved": "5.0.6",
+ "contentHash": "MgY6tg5iVaFwMRcwAQiUAp+BC+h1iGWb72SFBaIvryOc6tmCz/JrXzcS7P993W0mznhs+vHh+p2Nf+jo+dNLpw==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Http.Connections.Client": "5.0.6",
+ "Microsoft.AspNetCore.SignalR.Client.Core": "5.0.6"
+ }
+ },
"Microsoft.AspNetCore.TestHost": {
"type": "Direct",
"requested": "[5.0.5, )",
@@ -114,6 +124,41 @@
"resolved": "0.24.0",
"contentHash": "xvoxO3Ck4mNflc+62d5LCI8xCVmj+SEdpGPptUZmPtbqK88iZkSxtprJWUadHNt8tXY6rFx8oHGpEw1Qcu3lAw=="
},
+ "Microsoft.AspNetCore.Connections.Abstractions": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "dqtwdQL7cUdWHiyCkVB/0LIpBtdhwnhh9AMCOf+0eBb3wCF5/YvKMU0oVtMJViy+PFSxwjM8RyaVyC9G0Gl4Rg==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Http.Features": "5.0.6"
+ }
+ },
+ "Microsoft.AspNetCore.Http.Connections.Client": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "PchO5EMTZmOd/z13NrQXDQjifCIj5+wewe+/UENRakVPIPl+oKcnyFF0xTeJRBWc8DbIm4OdAr/ET/fqpUgKOg==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Http.Connections.Common": "5.0.6",
+ "Microsoft.Extensions.Logging.Abstractions": "5.0.0",
+ "Microsoft.Extensions.Options": "5.0.0"
+ }
+ },
+ "Microsoft.AspNetCore.Http.Connections.Common": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "9V35MkPVkKhFfhtc/tEROmyQ0k94qjZz97sia0rRDy5zxZuu2OTzQst+9oW+iujoQotpWAjZD+gRu3S04uetjQ==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Connections.Abstractions": "5.0.6"
+ }
+ },
+ "Microsoft.AspNetCore.Http.Features": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "MfpLQRQK/iBZLiaRgPd4dNq4REVbycYH9apU0i18UWQsqZt2Oa0+gZRnz8j4eDCzzCwQSoVXtuCtuCdEnIk9vg==",
+ "dependencies": {
+ "Microsoft.Extensions.Primitives": "5.0.1",
+ "System.IO.Pipelines": "5.0.1"
+ }
+ },
"Microsoft.AspNetCore.JsonPatch": {
"type": "Transitive",
"resolved": "5.0.0",
@@ -133,6 +178,35 @@
"Newtonsoft.Json.Bson": "1.0.2"
}
},
+ "Microsoft.AspNetCore.SignalR.Client.Core": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "J2kWDD1xnHDYMNLVxZ5MarqAg/lygYYKwYoqPobAWDlCF1wpXbmO/dAgby0NScTrvzSd6+NdyHp7dgxz/whLnw==",
+ "dependencies": {
+ "Microsoft.AspNetCore.SignalR.Common": "5.0.6",
+ "Microsoft.AspNetCore.SignalR.Protocols.Json": "5.0.6",
+ "Microsoft.Extensions.DependencyInjection": "5.0.1",
+ "Microsoft.Extensions.Logging": "5.0.0",
+ "System.Threading.Channels": "5.0.0"
+ }
+ },
+ "Microsoft.AspNetCore.SignalR.Common": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "x10OXN4vP8dB7SaqEU+Te2tbKy5HAFMRfhbpHSijY16S3JDfp6HqzdWjAKjinmzEoawtCegedTJ4b3/eslQbOQ==",
+ "dependencies": {
+ "Microsoft.AspNetCore.Connections.Abstractions": "5.0.6",
+ "Microsoft.Extensions.Options": "5.0.0"
+ }
+ },
+ "Microsoft.AspNetCore.SignalR.Protocols.Json": {
+ "type": "Transitive",
+ "resolved": "5.0.6",
+ "contentHash": "fFwax6INapN++2DGfxriYJm4lFDTXNyeoBa1qi2ppJqosQATLI2JpErDHIjZwSWqHLL3umxGNWGpQPDzSkIkVg==",
+ "dependencies": {
+ "Microsoft.AspNetCore.SignalR.Common": "5.0.6"
+ }
+ },
"Microsoft.AspNetCore.SpaServices.Extensions": {
"type": "Transitive",
"resolved": "5.0.5",
@@ -322,8 +396,8 @@
},
"Microsoft.Extensions.Primitives": {
"type": "Transitive",
- "resolved": "5.0.0",
- "contentHash": "cI/VWn9G1fghXrNDagX9nYaaB/nokkZn0HYAawGaELQrl8InSezfe9OnfPZLcJq3esXxygh3hkq2c3qoV3SDyQ=="
+ "resolved": "5.0.1",
+ "contentHash": "5WPSmL4YeP7eW+Vc8XZ4DwjYWBAiSwDV9Hm63JJWcz1Ie3Xjv4KuJXzgCstj48LkLfVCYa7mLcx7y+q6yqVvtw=="
},
"Microsoft.IdentityModel.JsonWebTokens": {
"type": "Transitive",
@@ -1457,6 +1531,11 @@
"System.Threading.Tasks": "4.3.0"
}
},
+ "System.Threading.Channels": {
+ "type": "Transitive",
+ "resolved": "5.0.0",
+ "contentHash": "RLBIxntLaG9pRmmuVDwY1kc8Bvp/FQzSxPU+19VekkScKkWtVP9r8bLhm28ama3usc816UBrmkg3vv3jUea/hw=="
+ },
"System.Threading.Tasks": {
"type": "Transitive",
"resolved": "4.3.0",