Skip to content

Commit 1d12e04

Browse files
committed
Add HealthCheckResource_GetNotExisting_ReturnsOk test
Replace FluentAssertions with AwesomeAssertions Move files to libraries when not specific to project
1 parent 144c0e2 commit 1d12e04

File tree

14 files changed

+118
-73
lines changed

14 files changed

+118
-73
lines changed

Devpro.TerraformBackend.sln

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "0 - Solution Items", "0 - S
1313
README.md = README.md
1414
EndProjectSection
1515
EndProject
16-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2 - Applications", "2 - Applications", "{6D13F54F-4547-49C7-8136-01BFB4BBEE1E}"
16+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "3 - Applications", "3 - Applications", "{6D13F54F-4547-49C7-8136-01BFB4BBEE1E}"
1717
EndProject
18-
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1 - Libraries", "1 - Libraries", "{E9839BEC-B050-43E9-8EFD-34659CC92D93}"
18+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "2 - Business", "2 - Business", "{E9839BEC-B050-43E9-8EFD-34659CC92D93}"
1919
EndProject
2020
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApi", "src\WebApi\WebApi.csproj", "{5CD7A689-5ADB-4207-972E-6FA881AF1B1C}"
2121
EndProject
@@ -54,6 +54,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "pipelines", "pipelines", "{
5454
.github\workflows\pkg.yaml = .github\workflows\pkg.yaml
5555
EndProjectSection
5656
EndProject
57+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "1 - Framework", "1 - Framework", "{0C1E6968-B289-4378-84CF-B64E05E643A5}"
58+
EndProject
5759
Global
5860
GlobalSection(SolutionConfigurationPlatforms) = preSolution
5961
Debug|Any CPU = Debug|Any CPU
@@ -96,13 +98,13 @@ Global
9698
{5CD7A689-5ADB-4207-972E-6FA881AF1B1C} = {6D13F54F-4547-49C7-8136-01BFB4BBEE1E}
9799
{A5CAD112-C1E6-442B-BE0E-37C697030636} = {E9839BEC-B050-43E9-8EFD-34659CC92D93}
98100
{0429A41A-2D3A-42D4-8736-5FC0F6F0FF0C} = {E9839BEC-B050-43E9-8EFD-34659CC92D93}
99-
{49BF313A-4ED3-4BD2-9AEE-E44A5ED19C0C} = {E9839BEC-B050-43E9-8EFD-34659CC92D93}
101+
{49BF313A-4ED3-4BD2-9AEE-E44A5ED19C0C} = {0C1E6968-B289-4378-84CF-B64E05E643A5}
100102
{3C2E7F7E-1F8E-49D1-AD56-EC60BEB5299D} = {7B3738E0-6F86-4358-B55C-5AAD42B24F81}
101-
{F23098F5-355B-46F0-BABE-3D6E23D8EED7} = {E9839BEC-B050-43E9-8EFD-34659CC92D93}
103+
{F23098F5-355B-46F0-BABE-3D6E23D8EED7} = {0C1E6968-B289-4378-84CF-B64E05E643A5}
102104
{001CB9EB-2F7E-4288-BA9B-1E01ED43B8FF} = {3C2E7F7E-1F8E-49D1-AD56-EC60BEB5299D}
103105
{7F01D180-1A34-4377-B4E5-C852D8302CE7} = {7B3738E0-6F86-4358-B55C-5AAD42B24F81}
104106
{B055FFAF-8261-43B1-866A-12E289D5D7DC} = {6D13F54F-4547-49C7-8136-01BFB4BBEE1E}
105-
{19336002-C959-4E76-B112-861F93CF6423} = {E9839BEC-B050-43E9-8EFD-34659CC92D93}
107+
{19336002-C959-4E76-B112-861F93CF6423} = {0C1E6968-B289-4378-84CF-B64E05E643A5}
106108
{02EA681E-C7D8-13C7-8484-4AC65E1B71E8} = {7B3738E0-6F86-4358-B55C-5AAD42B24F81}
107109
EndGlobalSection
108110
GlobalSection(ExtensibilityGlobals) = postSolution

src/WebApi/DependencyInjection/SwaggerServiceCollectionExtensions.cs renamed to src/Common.AspNetCore.WebApi/DependencyInjection/SwaggerServiceCollectionExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
using Microsoft.OpenApi.Models;
1+
using Devpro.Common.AspNetCore.WebApi.Configuration;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.OpenApi.Models;
24

3-
namespace Devpro.TerraformBackend.WebApi.DependencyInjection;
5+
namespace Devpro.Common.AspNetCore.WebApi.DependencyInjection;
46

57
public static class SwaggerServiceCollectionExtensions
68
{

src/WebApi/DependencyInjection/BehaviorServiceCollectionExtensions.cs renamed to src/Common.AspNetCore/DependencyInjection/BehaviorServiceCollectionExtensions.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
using Microsoft.AspNetCore.Mvc;
1+
using System.Linq;
2+
using Microsoft.AspNetCore.Mvc;
3+
using Microsoft.Extensions.DependencyInjection;
4+
using Microsoft.Extensions.Logging;
25

3-
namespace Devpro.TerraformBackend.WebApi.DependencyInjection;
6+
namespace Devpro.Common.AspNetCore.DependencyInjection;
47

5-
internal static class BehaviorServiceCollectionExtensions
8+
public static class BehaviorServiceCollectionExtensions
69
{
710
/// <summary>
811
/// Ensures that every time an invalid model state occurs in the API, a warning log is generated with the request path.
912
/// </summary>
1013
/// <param name="services"></param>
1114
/// <returns></returns>
12-
internal static IServiceCollection AddInvalidModelStateLog(this IServiceCollection services)
15+
public static IServiceCollection AddInvalidModelStateLog(this IServiceCollection services)
1316
{
1417
services.PostConfigure<ApiBehaviorOptions>(options =>
1518
{

src/Common.AspNetCore/RawRequestBodyFormatter.cs renamed to src/Common.AspNetCore/Formatters/RawRequestBodyFormatter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
using Microsoft.AspNetCore.Mvc.Formatters;
55
using Microsoft.Net.Http.Headers;
66

7-
namespace Devpro.Common.AspNetCore;
7+
namespace Devpro.Common.AspNetCore.Formatters;
88

99
/// <summary>
1010
/// ASP.NET Core input formatter to manage raw request bodies.

src/Infrastructure.MongoDb/Repositories/StateRepository.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@
88

99
namespace Devpro.TerraformBackend.Infrastructure.MongoDb.Repositories
1010
{
11-
public class StateRepository : RepositoryBase, IStateRepository
11+
public class StateRepository(IMongoClientFactory mongoClientFactory, ILogger<StateRepository> logger, MongoDbConfiguration configuration)
12+
: RepositoryBase(mongoClientFactory, logger, configuration), IStateRepository
1213
{
13-
public StateRepository(IMongoClientFactory mongoClientFactory, ILogger<StateRepository> logger, MongoDbConfiguration configuration)
14-
: base(mongoClientFactory, logger, configuration)
15-
{
16-
}
17-
1814
protected override string CollectionName => "tf_state";
1915

2016
public async Task CreateAsync(string name, string jsonInput)

src/WebApi/Authentication/BasicAuthenticationHandler.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,28 @@ public class BasicAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOpti
1212
{
1313
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
1414
{
15-
// raises an error if no authorization header
15+
// checks authorization header
1616
if (!Request.Headers.ContainsKey("Authorization"))
1717
{
1818
return Task.FromResult(AuthenticateResult.Fail("Missing Authorization header"));
1919
}
2020

2121
var authorizationHeader = Request.Headers.Authorization.ToString();
2222

23-
// raises an error if the authorization header is not Basic
23+
// checks authorization header starts with Basic
2424
if (!authorizationHeader.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase))
2525
{
2626
return Task.FromResult(AuthenticateResult.Fail("Authorization header does not start with 'Basic'"));
2727
}
2828

29-
// decrypts the authorization header and split out the client id/secret which is separated by the first ':'
29+
// decrypts the authorization header and split out the client id/secret
3030
var authBase64Decoded = Encoding.UTF8.GetString(Convert.FromBase64String(authorizationHeader.Replace("Basic ", "", StringComparison.OrdinalIgnoreCase)));
3131
var authSplit = authBase64Decoded.Split([':'], 2);
32-
33-
// sends an error if no username and password
3432
if (authSplit.Length != 2)
3533
{
3634
return Task.FromResult(AuthenticateResult.Fail("Invalid Authorization header format"));
3735
}
3836

39-
// stores the client ID and secret
4037
var clientId = authSplit[0];
4138
var clientSecret = authSplit[1];
4239

@@ -47,21 +44,18 @@ protected override Task<AuthenticateResult> HandleAuthenticateAsync()
4744
return Task.FromResult(AuthenticateResult.Fail(string.Format("The secret is incorrect for the client '{0}'", clientId)));
4845
}
4946

50-
// authenticates the client using basic authentication
5147
var client = new BasicAuthenticationClient
5248
{
5349
AuthenticationType = BasicAuthenticationDefaults.AuthenticationScheme,
5450
IsAuthenticated = true,
5551
Name = clientId
5652
};
5753

58-
// set the client ID as the name claim type
5954
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(client,
6055
[
6156
new Claim(ClaimTypes.Name, clientId)
6257
]));
6358

64-
// returns a success result
6559
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(claimsPrincipal, Scheme.Name)));
6660
}
6761
}

src/WebApi/ImplicitUsings.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
global using Devpro.Common.AspNetCore;
1+
global using Devpro.Common.AspNetCore.DependencyInjection;
2+
global using Devpro.Common.AspNetCore.Formatters;
23
global using Devpro.Common.AspNetCore.WebApi.Builder;
34
global using Devpro.Common.AspNetCore.WebApi.Configuration;
5+
global using Devpro.Common.AspNetCore.WebApi.DependencyInjection;
46
global using Devpro.TerraformBackend.WebApi;
57
global using Devpro.TerraformBackend.WebApi.DependencyInjection;

src/WebApi/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
builder.Services.AddSwaggerGenWithBasicAuth(configuration);
1010
builder.Services.AddBasicAuthentication();
1111
builder.Services.AddHealthChecks();
12-
builder.Services.AddBehaviors();
12+
builder.Services.AddInvalidModelStateLog();
1313

1414
// create the application and configures the HTTP request pipeline
1515
var app = builder.Build();
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using System.Net;
2+
3+
namespace Devpro.TerraformBackend.WebApi.IntegrationTests.Http;
4+
5+
internal static class HttpResponseMessageExtensions
6+
{
7+
public static async Task<string?> CheckResponseAndGetContent(this HttpResponseMessage response, HttpStatusCode expectedStatusCode, string? expectedContentType, string? expectedContent)
8+
{
9+
response.StatusCode.Should().Be(expectedStatusCode);
10+
11+
if (expectedContentType == null)
12+
{
13+
response.Content.Headers.ContentType.Should().BeNull();
14+
}
15+
else
16+
{
17+
response.Content.Headers.ContentType.Should().NotBeNull();
18+
response.Content.Headers.ContentType?.ToString().Should().Be(expectedContentType);
19+
}
20+
21+
var result = await response.Content.ReadAsStringAsync();
22+
23+
if (expectedContent == null)
24+
{
25+
result.Should().BeNull();
26+
}
27+
else
28+
{
29+
result.Should().NotBeNull();
30+
result.Should().Be(expectedContent);
31+
}
32+
33+
return result;
34+
}
35+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
global using System.Text;
2+
global using System.Text.Json;
3+
global using AwesomeAssertions;
4+
global using Bogus;
5+
global using Microsoft.AspNetCore.Mvc.Testing;
6+
global using Xunit;

0 commit comments

Comments
 (0)