Skip to content

Commit 2946eb6

Browse files
authored
bugfix: Fix integration tests (#170)
* Intercept cloudflare turnstile requests * Less invasive http request intercepting, fix DI
1 parent 8f143dc commit 2946eb6

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

API.IntegrationTests/AccountTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public async Task CreateAccount_ShouldAdd_NewUserToDatabase()
1616
username = "Bob",
1717
password = "SecurePassword123#",
1818
email = "bob@example.com",
19-
turnstileresponse = "lmao"
19+
turnstileresponse = "valid-token"
2020
});
2121

2222

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
using System.Net;
2+
using System.Text.Json;
3+
using System.Web;
4+
5+
namespace OpenShock.API.IntegrationTests.HttpMessageHandlers;
6+
7+
sealed class InterceptedHttpMessageHandler : DelegatingHandler
8+
{
9+
private async Task<HttpResponseMessage> HandleCloudflareTurnstileRequest(HttpRequestMessage request, CancellationToken cancellationToken)
10+
{
11+
var formData = request.Content != null ? await request.Content.ReadAsStringAsync(cancellationToken) : string.Empty;
12+
var parsedForm = HttpUtility.ParseQueryString(formData);
13+
var responseToken = parsedForm["response"];
14+
15+
var responseDto = responseToken switch
16+
{
17+
"valid-token" => new CloudflareTurnstileVerifyResponseDto
18+
{
19+
Success = true,
20+
ErrorCodes = [],
21+
ChallengeTs = DateTime.UtcNow,
22+
Hostname = "validhost",
23+
Action = "validaction",
24+
Cdata = ""
25+
},
26+
"invalid-token" => new CloudflareTurnstileVerifyResponseDto
27+
{
28+
Success = false,
29+
ErrorCodes = ["invalid-input-response"],
30+
ChallengeTs = DateTime.UtcNow,
31+
Hostname = "invalidhost",
32+
Action = "invalidaction",
33+
Cdata = ""
34+
},
35+
_ => new CloudflareTurnstileVerifyResponseDto
36+
{
37+
Success = false,
38+
ErrorCodes = ["bad-request"],
39+
ChallengeTs = DateTime.UtcNow,
40+
Hostname = "unknownhost",
41+
Action = "unknownaction",
42+
Cdata = ""
43+
}
44+
};
45+
46+
var responseJson = JsonSerializer.Serialize(responseDto);
47+
48+
var responseMessage = new HttpResponseMessage(HttpStatusCode.OK)
49+
{
50+
Content = new StringContent(responseJson, System.Text.Encoding.UTF8, "application/json")
51+
};
52+
53+
return responseMessage;
54+
}
55+
56+
private async Task<HttpResponseMessage> HandleMailJetApiHost(HttpRequestMessage request, CancellationToken cancellationToken)
57+
{
58+
return new HttpResponseMessage(HttpStatusCode.NotFound);
59+
}
60+
61+
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
62+
{
63+
return request.RequestUri switch
64+
{
65+
{ Host: "challenges.cloudflare.com", AbsolutePath: "/turnstile/v0/siteverify" } => await HandleCloudflareTurnstileRequest(request, cancellationToken),
66+
{ Host: "api.mailjet.com" } => await HandleMailJetApiHost(request, cancellationToken),
67+
_ => new HttpResponseMessage(HttpStatusCode.NotFound)
68+
};
69+
}
70+
71+
private class CloudflareTurnstileVerifyResponseDto
72+
{
73+
public bool Success { get; set; }
74+
public string[] ErrorCodes { get; set; }
75+
public DateTime ChallengeTs { get; set; }
76+
public string Hostname { get; set; }
77+
public string Action { get; set; }
78+
public string Cdata { get; set; }
79+
}
80+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using Microsoft.Extensions.Http;
2+
3+
namespace OpenShock.API.IntegrationTests.HttpMessageHandlers;
4+
5+
sealed class InterceptedHttpMessageHandlerBuilder : HttpMessageHandlerBuilder
6+
{
7+
public override string? Name { get; set; }
8+
public override HttpMessageHandler PrimaryHandler { get; set; }
9+
public override IList<DelegatingHandler> AdditionalHandlers => [];
10+
11+
12+
public override HttpMessageHandler Build()
13+
{
14+
return new InterceptedHttpMessageHandler();
15+
}
16+
}

API.IntegrationTests/IntegrationTestWebAppFactory.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
using Microsoft.AspNetCore.Hosting;
22
using Microsoft.AspNetCore.Mvc.Testing;
33
using Microsoft.AspNetCore.TestHost;
4+
using Microsoft.Extensions.DependencyInjection;
5+
using Microsoft.Extensions.DependencyInjection.Extensions;
6+
using Microsoft.Extensions.Http;
7+
using OpenShock.API.IntegrationTests.HttpMessageHandlers;
8+
using OpenShock.Common.Services.Turnstile;
49
using Testcontainers.PostgreSql;
510
using Testcontainers.Redis;
611
using TUnit.Core.Interfaces;
@@ -78,7 +83,7 @@ protected override void ConfigureWebHost(IWebHostBuilder builder)
7883

7984
builder.ConfigureTestServices(services =>
8085
{
81-
// We can replace services here
86+
services.AddTransient<HttpMessageHandlerBuilder, InterceptedHttpMessageHandlerBuilder>();
8287
});
8388
}
8489

0 commit comments

Comments
 (0)