using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Persistence.API; using Persistence.Database.Model; using Persistence.Database.Postgres; using Refit; using RestSharp; using System.Net.Http.Headers; using System.Text.Json; namespace Persistence.IntegrationTests; public class WebAppFactoryFixture : WebApplicationFactory { private static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, PropertyNameCaseInsensitive = true, //Converters = { new ValidationResultConverter() } }; private static readonly RefitSettings RefitSettings = new(new SystemTextJsonContentSerializer(JsonSerializerOptions)); private readonly string connectionString; private readonly KeyCloakUser keycloakTestUser; public readonly string KeycloakGetTokenUrl; public WebAppFactoryFixture() { var configuration = new ConfigurationBuilder() .AddJsonFile("appsettings.Tests.json") .Build(); var dbConnection = configuration.GetSection("DbConnection").Get()!; connectionString = dbConnection.GetConnectionString(); keycloakTestUser = configuration.GetSection("KeycloakTestUser").Get()!; KeycloakGetTokenUrl = configuration.GetSection("KeycloakGetTokenUrl").Value!; } protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureServices(services => { var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions)); if (descriptor != null) services.Remove(descriptor); services.AddDbContext(options => options.UseNpgsql(connectionString)); var serviceProvider = services.BuildServiceProvider(); using var scope = serviceProvider.CreateScope(); var scopedServices = scope.ServiceProvider; var dbContext = scopedServices.GetRequiredService(); dbContext.Database.EnsureCreatedAndMigrated(); dbContext.SaveChanges(); }); } public override async ValueTask DisposeAsync() { var dbContext = new PersistenceDbContext( new DbContextOptionsBuilder() .UseNpgsql(connectionString) .Options); await dbContext.Database.EnsureDeletedAsync(); } public T GetHttpClient(string uriSuffix) { var httpClient = CreateClient(); if (string.IsNullOrEmpty(uriSuffix)) return RestService.For(httpClient, RefitSettings); if (httpClient.BaseAddress is not null) httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); return RestService.For(httpClient, RefitSettings); } public async Task GetAuthorizedHttpClient(string uriSuffix) { var httpClient = await GetAuthorizedHttpClient(); if (string.IsNullOrEmpty(uriSuffix)) return RestService.For(httpClient, RefitSettings); if (httpClient.BaseAddress is not null) httpClient.BaseAddress = new Uri(httpClient.BaseAddress, uriSuffix); return RestService.For(httpClient, RefitSettings); } private async Task GetAuthorizedHttpClient() { var httpClient = CreateClient(); var token = await GetTokenAsync(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return httpClient; } private async Task GetTokenAsync() { var restClient = new RestClient(); var request = new RestRequest(KeycloakGetTokenUrl, Method.Post); request.AddParameter("username", keycloakTestUser.Username); request.AddParameter("password", keycloakTestUser.Password); request.AddParameter("client_id", keycloakTestUser.ClientId); request.AddParameter("grant_type", keycloakTestUser.GrantType); var keyCloackResponse = await restClient.PostAsync(request); if (keyCloackResponse.IsSuccessful && !String.IsNullOrEmpty(keyCloackResponse.Content)) { var token = JsonSerializer.Deserialize(keyCloackResponse.Content)!; return token.AccessToken; } return String.Empty; } }