using System.Text; using FindAndDrive.Domain.Models.DTO; using FindAndDrive.Domain.Models.DTO.Request; using FindAndDrive.Domain.Models.DTO.Response; using FindAndDrive.Tests.Performance.Helpers; using NBomber.Contracts; using NBomber.CSharp; using Newtonsoft.Json; namespace FindAndDrive.Tests.Performance.Scenarios; public class FinanceUserScenario { private readonly TokenRequest _tokenRequest; private readonly HttpClient _httpClient; public FinanceUserScenario(TokenRequest tokenRequest, string baseUrl) { _tokenRequest = tokenRequest; _httpClient = new HttpClient() { BaseAddress = new Uri(baseUrl) }; } public async Task> GetScenarios() { var token = await AuthenticationHelper.GetToken(_httpClient, _tokenRequest); var scenarios = new List(); var financingNormalScenario = Scenario.Create("financing_normal_scenario", async context => { var preVettingStep = await Step.Run("prevetting_request", context, async () => { var preVetting = await CreatePreVetting(token.Token); return Response.Ok(preVetting); }); var predictionStep = await Step.Run("prediction_request", context, async () => { var prediction = await CreatePrediction(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(prediction); }); var getApplicantStep = await Step.Run("applicant_request", context, async () => { var applicant = await GetApplicant(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(applicant); }); return Response.Ok(); }) .WithoutWarmUp() .WithLoadSimulations( Simulation.RampingInject(rate: 1, interval: TimeSpan.FromSeconds(3), during: TimeSpan.FromSeconds(30)) ); var financingStressScenario = Scenario.Create("financing_stress_scenario", async context => { var preVettingStep = await Step.Run("prevetting_request", context, async () => { var preVetting = await CreatePreVetting(token.Token); return Response.Ok(preVetting); }); var predictionStep = await Step.Run("prediction_request", context, async () => { var prediction = await CreatePrediction(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(prediction); }); var getApplicantStep = await Step.Run("applicant_request", context, async () => { var applicant = await GetApplicant(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(applicant); }); return Response.Ok(); }) .WithoutWarmUp() .WithLoadSimulations( Simulation.Inject(rate: 10, interval: TimeSpan.FromSeconds(3), during: TimeSpan.FromSeconds(30)) ); var financingHighStressScenario = Scenario.Create("financing_high_stress_scenario", async context => { var preVettingStep = await Step.Run("prevetting_request", context, async () => { var preVetting = await CreatePreVetting(token.Token); return Response.Ok(preVetting); }); var predictionStep = await Step.Run("prediction_request", context, async () => { var prediction = await CreatePrediction(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(prediction); }); var getApplicantStep = await Step.Run("applicant_request", context, async () => { var applicant = await GetApplicant(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(applicant); }); return Response.Ok(); }) .WithoutWarmUp() .WithLoadSimulations( Simulation.Inject(rate: 100, interval: TimeSpan.FromSeconds(3), during: TimeSpan.FromSeconds(30)) ); var financingSpikeScenario = Scenario.Create("financing_spike_scenario", async context => { var preVettingStep = await Step.Run("prevetting_request", context, async () => { var preVetting = await CreatePreVetting(token.Token); return Response.Ok(preVetting); }); var predictionStep = await Step.Run("prediction_request", context, async () => { var prediction = await CreatePrediction(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(prediction); }); var getApplicantStep = await Step.Run("applicant_request", context, async () => { var applicant = await GetApplicant(token.Token, preVettingStep.Payload.Value.ApplicantId); return Response.Ok(applicant); }); return Response.Ok(); }) .WithoutWarmUp() .WithLoadSimulations( Simulation.Inject(rate: 1000, interval: TimeSpan.FromSeconds(5), during: TimeSpan.FromSeconds(10)), Simulation.Inject(rate: 0, interval: TimeSpan.FromSeconds(1), during: TimeSpan.FromSeconds(30)) ); scenarios.Add(financingNormalScenario); scenarios.Add(financingStressScenario); scenarios.Add(financingHighStressScenario); scenarios.Add(financingSpikeScenario); return scenarios; } private async Task CreatePreVetting(string token) { var rand = new Random(); var payload = new PreVettingRequest { Deposit = NextDecimal(rand), FirstName = "name", LastName = "lastname", MobileNumber = $"+27827654135", MonthlyBudget = NextDecimal(rand), NetIncome = NextDecimal(rand) }; var uriBuilder = new UriBuilder(_httpClient.BaseAddress) { Path = $"api/Financing/Pre-Qualification" }; using var request = new HttpRequestMessage(HttpMethod.Post, uriBuilder.Uri); request.Headers.Add("Authorization", $"Bearer {token}"); request.Content = new StringContent( JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json" ); var response = await _httpClient.SendAsync(request); response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); var result = JsonConvert.DeserializeObject(body); return result; } private async Task CreatePrediction(string token, Guid applicantId) { var rand = new Random(); var payload = new AnalyticsRequest { NetIncome = rand.Next(0, 50_000_000), ApplicantId = applicantId, FirstName = Guid.NewGuid().ToString(), LastName = Guid.NewGuid().ToString(), MobileNumber = $"+27827654135", EmailAddress = "email@test.com", GrossIncome = rand.Next(0, 50_000_000), LivingExpenses = rand.Next(0, 50_000_000), IDNumber = "2001015800085" }; var uriBuilder = new UriBuilder(_httpClient.BaseAddress) { Path = $"api/Financing/Prediction" }; using var request = new HttpRequestMessage(HttpMethod.Post, uriBuilder.Uri); request.Headers.Add("Authorization", $"Bearer {token}"); request.Content = new StringContent( JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json" ); var response = await _httpClient.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); response.EnsureSuccessStatusCode(); var result = JsonConvert.DeserializeObject(body); return result; } private async Task GetApplicant(string token, Guid applicantId) { var uriBuilder = new UriBuilder(_httpClient.BaseAddress) { Path = $"api/Financing/GetApplicantById" }; using var request = new HttpRequestMessage(HttpMethod.Get, uriBuilder.Uri); request.Headers.Add("Authorization", $"Bearer {token}"); request.Content = new FormUrlEncodedContent(new KeyValuePair[] { new("id", $"{applicantId}") }); var response = await _httpClient.SendAsync(request); var body = await response.Content.ReadAsStringAsync(); response.EnsureSuccessStatusCode(); var result = JsonConvert.DeserializeObject(body); return result; } private static decimal NextDecimal(Random rng) { return new decimal(rng.Next(0, 50_000_000)); } private static string RandomScoreIndicator(Random rng) { var scoreIndicator = ""; var num = rng.Next(0, 4); scoreIndicator = num switch { 0 => "01", 1 => "02", 2 => "03", _ => scoreIndicator }; return scoreIndicator; } }