using AutoTazTest.Infrastructure; using AvtoTAZContratcs.BindingModels; using AvtoTAZContratcs.Enums; using AvtoTAZContratcs.Infrastructure.PostConfigurations; using AvtoTAZDatabase; using AvtoTAZDatabase.Models; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.AspNetCore.TestHost; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestPlatform.TestHost; using Newtonsoft.Json.Linq; using Serilog; using System.Net; using System.Text; using System.Text.Json; namespace AutoTazTest.LocalizationTests; internal abstract class BaseLocalizationControllerTest { protected abstract string GetLocale(); private WebApplicationFactory _webApplication; protected HttpClient HttpClient { get; private set; } protected static AvtoTAZDbContext AvtoTAZDbContext { get; private set; } protected static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true }; private static string _manufacturerId; private static string _customerId; private static string _workerId; private static string _productId; private static string _postId; [OneTimeSetUp] public void OneTimeSetUp() { _webApplication = new CustomWebApplicationFactory(); HttpClient = _webApplication .WithWebHostBuilder(builder => { builder.ConfigureTestServices(services => { using var loggerFactory = new LoggerFactory(); loggerFactory.AddSerilog(new LoggerConfiguration() .ReadFrom.Configuration(new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json") .Build()) .CreateLogger()); services.AddSingleton(loggerFactory); }); }) .CreateClient(); var request = HttpClient.GetAsync("/login/user").GetAwaiter().GetResult(); var data = request.Content.ReadAsStringAsync().GetAwaiter().GetResult(); HttpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {data}"); HttpClient.DefaultRequestHeaders.Add("Accept-Language", GetLocale()); AvtoTAZDbContext = _webApplication.Services.GetRequiredService(); AvtoTAZDbContext.Database.EnsureDeleted(); AvtoTAZDbContext.Database.EnsureCreated(); } [SetUp] public void SetUp() { // Очищаем базу данных перед каждым тестом AvtoTAZDbContext.RemoveSalariesFromDatabase(); AvtoTAZDbContext.RemoveShipmentFromDatabase(); AvtoTAZDbContext.RemoveWorkersFromDatabase(); AvtoTAZDbContext.RemovePostsFromDatabase(); AvtoTAZDbContext.RemoveDealerFromDatabase(); AvtoTAZDbContext.RemoveCarAssemblyFromDatabase(); AvtoTAZDbContext.RemoveAccessoriesFromDatabase(); AvtoTAZDbContext.ChangeTracker.Clear(); // Создаем базовые записи _customerId = AvtoTAZDbContext.InsertDealerToDatabaseAndReturn( nameDealer: $"Customer_{Guid.NewGuid()}" ).Id; _workerId = AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn( fio: $"Worker_{Guid.NewGuid()}" ).Id; _postId = AvtoTAZDbContext.InsertPostToDatabaseAndReturn( postName: $"Post_{Guid.NewGuid()}" ).PostId; } [TearDown] public void TearDown() { AvtoTAZDbContext.RemoveSalariesFromDatabase(); AvtoTAZDbContext.RemoveShipmentFromDatabase(); AvtoTAZDbContext.RemoveWorkersFromDatabase(); AvtoTAZDbContext.RemovePostsFromDatabase(); AvtoTAZDbContext.RemoveDealerFromDatabase(); AvtoTAZDbContext.RemoveCarAssemblyFromDatabase(); AvtoTAZDbContext.RemoveAccessoriesFromDatabase(); AvtoTAZDbContext.ChangeTracker.Clear(); } [OneTimeTearDown] public void OneTimeTearDown() { AvtoTAZDbContext?.Database.EnsureDeleted(); AvtoTAZDbContext?.Dispose(); HttpClient?.Dispose(); _webApplication?.Dispose(); } [Test] public async Task LoadComponents_WhenHaveRecords_ShouldSuccess_Test() { // Arrange var component1 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "Тормоза", price: 1500); var component2 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "Выхлоп Акрапович", price: 12000); var component3 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "Спортивный руль", price: 18000); var component4 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "Якорь", price: 18000); AvtoTAZDbContext.InsertComponentHistoryToDatabaseAndReturn(component1.Id, price: 1400, changeDate: DateTime.UtcNow.AddDays(-2)); AvtoTAZDbContext.InsertComponentHistoryToDatabaseAndReturn(component1.Id, price: 1000, changeDate: DateTime.UtcNow.AddDays(-1)); AvtoTAZDbContext.InsertComponentHistoryToDatabaseAndReturn(component2.Id, price: 1100, changeDate: DateTime.UtcNow.AddDays(-1)); AvtoTAZDbContext.InsertComponentHistoryToDatabaseAndReturn(component3.Id, price: 1700, changeDate: DateTime.UtcNow.AddDays(-3)); AvtoTAZDbContext.InsertComponentHistoryToDatabaseAndReturn(component4.Id, price: 3000, changeDate: DateTime.UtcNow.AddDays(-3)); // Act var response = await HttpClient.GetAsync("/api/report/loadaccessories"); // Assert await AssertStreamAsync(response, $"file-components-{GetLocale()}.docx"); } [Test] public async Task LoadSales_WhenHaveRecords_ShouldSuccess_Test() { // Arrange var post = AvtoTAZDbContext.InsertPostToDatabaseAndReturn(postName: $"Post_{Guid.NewGuid().ToString()}"); var worker1 = AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(fio: "Владимир Владимирович Гусь", postId: post.Id); var worker2 = AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(fio: "Игорь Иванович Сладких", postId: post.Id); Console.WriteLine($"Worker1: ID={worker1.Id}, FIO={worker1.FIO}"); Console.WriteLine($"Worker2: ID={worker2.Id}, FIO={worker2.FIO}"); var customer = AvtoTAZDbContext.InsertDealerToDatabaseAndReturn(nameDealer: "кэтчешир"); var component1 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "Процессор Intel i5", price: 15000); var component2 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "1050 ТИ АЙ", price: 30000); var component3 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "РЫКСА 580", price: 32000); var component4 = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(accessoriesName: "SSD 1TB", price: 10000); var product1 = AvtoTAZDbContext.InsertCarAssemblyToDatabaseAndReturn( workerId: worker1.Id, modelName: "Lada Samara", autoType: AutoType.Jeep, accessories: new List<(string, int, double)> { (component1.Id, 1, 100.0) } ); var product2 = AvtoTAZDbContext.InsertCarAssemblyToDatabaseAndReturn( workerId: worker2.Id, modelName: "Vaz Sputnik", autoType: AutoType.Jeep, accessories: new List<(string, int, double)> { (component2.Id, 1, 100.0) } ); var product3 = AvtoTAZDbContext.InsertCarAssemblyToDatabaseAndReturn( workerId: worker1.Id, modelName: "Lada Creta", autoType: AutoType.Jeep, accessories: new List<(string, int, double)> { (component3.Id, 1, 100.0) } ); AvtoTAZDbContext.InsertProductComponentToDatabaseAndReturn(product1.Id, component1.Id, 1); AvtoTAZDbContext.SaveChanges(); AvtoTAZDbContext.InsertProductComponentToDatabaseAndReturn(product2.Id, component2.Id, 1); AvtoTAZDbContext.SaveChanges(); AvtoTAZDbContext.InsertProductComponentToDatabaseAndReturn(product2.Id, component3.Id, 1); AvtoTAZDbContext.SaveChanges(); AvtoTAZDbContext.InsertProductComponentToDatabaseAndReturn(product3.Id, component4.Id, 1); AvtoTAZDbContext.SaveChanges(); var shipmentDate1 = DateTime.UtcNow; var shipmentDate2 = shipmentDate1.AddSeconds(1); AvtoTAZDbContext.InsertShipmentToDatabaseAndReturn( workerId: worker1.Id, dealerId: customer.Id, modelId: product1.Id, shipmentDate: shipmentDate1, count: 3, sum: 1457000 ); AvtoTAZDbContext.InsertShipmentToDatabaseAndReturn( workerId: worker2.Id, dealerId: customer.Id, modelId: product2.Id, shipmentDate: shipmentDate2, count: 8, sum: 1004563 ); AvtoTAZDbContext.InsertShipmentToDatabaseAndReturn( workerId: worker1.Id, dealerId: customer.Id, modelId: product2.Id, shipmentDate: shipmentDate2, count: 15, sum: 1200000 ); AvtoTAZDbContext.SaveChanges(); var workers = AvtoTAZDbContext.Workers.ToList(); Console.WriteLine($"Workers in DB: {workers.Count}"); foreach (var w in workers) { Console.WriteLine($"Worker: ID={w.Id}, FIO={w.FIO}"); } var shipments = AvtoTAZDbContext.Shipments.Include(s => s.Worker).ToList(); Console.WriteLine($"Shipments in DB: {shipments.Count}"); foreach (var s in shipments) { Console.WriteLine($"Shipment: ID={s.Id}, WorkerId={s.WorkerId}, WorkerFIO={s.Worker?.FIO ?? "Неизвестный"}, ModelId={s.ModelId}, Sum={s.Sum}"); } // Act var response = await HttpClient.GetAsync($"/api/report/loadshipment?fromDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(2):MM/dd/yyyy HH:mm:ss}"); var responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Response from /api/report/loadshipment: {responseContent}"); Console.WriteLine($"Status Code: {response.StatusCode}"); // Assert Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK), $"Expected OK but got {response.StatusCode}. Response: {responseContent}"); await AssertStreamAsync(response, $"file-{GetLocale()}.xlsx"); } [Test] public async Task LoadSalary_WhenHaveRecords_ShouldSuccess_Test() { // Arrange var post = AvtoTAZDbContext.InsertPostToDatabaseAndReturn(); var worker1 = AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(fio: "Чеширский Котчешир Чеширович", postId: post.PostId).AddPost(post); var worker2 = AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(fio: "Алиулов Салих Рамисович", postId: post.PostId).AddPost(post); AvtoTAZDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 100, salaryDate: DateTime.UtcNow.AddDays(-10)); AvtoTAZDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 1000, salaryDate: DateTime.UtcNow.AddDays(-5)); AvtoTAZDbContext.InsertSalaryToDatabaseAndReturn(worker1.Id, workerSalary: 200, salaryDate: DateTime.UtcNow.AddDays(5)); AvtoTAZDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 500, salaryDate: DateTime.UtcNow.AddDays(-5)); AvtoTAZDbContext.InsertSalaryToDatabaseAndReturn(worker2.Id, workerSalary: 300, salaryDate: DateTime.UtcNow.AddDays(-3)); // Act var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.UtcNow.AddDays(-7):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.UtcNow.AddDays(-1):MM/dd/yyyy HH:mm:ss}"); // Assert await AssertStreamAsync(response, $"file-{GetLocale()}.pdf"); } private static async Task AssertStreamAsync(HttpResponseMessage response, string fileNameForSave = "") { Assert.That(response.StatusCode, Is.EqualTo(HttpStatusCode.OK)); using var data = await response.Content.ReadAsStreamAsync(); Assert.That(data, Is.Not.Null); Assert.That(data.Length, Is.GreaterThan(0)); await SaveStreamAsync(data, fileNameForSave); } private static async Task SaveStreamAsync(Stream stream, string fileName) { if (string.IsNullOrEmpty(fileName)) { return; } var path = Path.Combine(Directory.GetCurrentDirectory(), fileName); if (File.Exists(path)) { File.Delete(path); } stream.Position = 0; using var fileStream = new FileStream(path, FileMode.OpenOrCreate); await stream.CopyToAsync(fileStream); } protected abstract string MessageElementNotFound(); protected abstract string MessageElementExists(); protected abstract string MessageElementIdIncorrect(); [TestCase("dealer")] [TestCase("post")] [TestCase("carassembly/delete")] public async Task Api_DelElement_NotFound_Test(string path) { // Act var response = await HttpClient.DeleteAsync($"/api/{path}/{Guid.NewGuid()}"); // Assert Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementNotFound())); } [TestCase("dealer")] [TestCase("post")] [TestCase("carassembly/getrecord")] public async Task Api_GetElement_NotFound_Test(string path) { // Act var response = await HttpClient.GetAsync($"/api/{path}/{Guid.NewGuid()}"); // Assert Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementNotFound())); } private static IEnumerable TestDataElementExists() { yield return new TestCaseData(() => { var model = CreateDealerBindingModel(); model.Id = Guid.NewGuid().ToString(); AvtoTAZDbContext.InsertDealerToDatabaseAndReturn(model.Id); return model; }, "dealer"); yield return new TestCaseData(() => { var model = CreatePostModel(); AvtoTAZDbContext.InsertPostToDatabaseAndReturn(model.Id); return model; }, "post"); yield return new TestCaseData(() => { var component = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn(); var model = CreateCarAssemblyModel( components: new List { new Accessories_CarsBindingModel { ModelId = Guid.NewGuid().ToString(), AccessoriesId = component.Id, Count = 1 } } ); AvtoTAZDbContext.InsertCarAssemblyToDatabaseAndReturn( workerId: model.WorkerId ?? throw new ArgumentNullException(nameof(model.WorkerId)), id: model.Id, modelName: model.ModelName ?? throw new ArgumentNullException(nameof(model.ModelName)), accessories: model.Accessories?.Select(c => (c.AccessoriesId ?? throw new ArgumentNullException(nameof(c.AccessoriesId)), c.Count, 0.0)).ToList() ); return model; }, "carassembly/register"); yield return new TestCaseData(() => { var post = AvtoTAZDbContext.InsertPostToDatabaseAndReturn(); var model = CreateWorkerModel(post.PostId); AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(model.Id, postId: post.PostId); return model; }, "workers/register"); } private static IEnumerable TestDataIdIncorrectForPut() { yield return new TestCaseData(() => { var model = CreateDealerBindingModel(); AvtoTAZDbContext.InsertDealerToDatabaseAndReturn(id: model.Id, nameDealer: model.NameDealer); model.Id = "invalid-id"; return model; }, "dealer"); yield return new TestCaseData(() => { var model = CreatePostModel(); AvtoTAZDbContext.InsertPostToDatabaseAndReturn(model.Id); model.Id = "invalid-id"; // Изменяем Id на невалидный return model; }, "post"); yield return new TestCaseData(() => { var uniqueId = Guid.NewGuid().ToString(); var component = AvtoTAZDbContext.InsertAccessoriesToDatabaseAndReturn( accessoriesName: $"Accessory_{uniqueId}", price: 100.0 ); var model = CreateCarAssemblyModel( components: new List { new Accessories_CarsBindingModel { ModelId = Guid.NewGuid().ToString(), AccessoriesId = component.Id, Count = 1 } } ); AvtoTAZDbContext.InsertCarAssemblyToDatabaseAndReturn( workerId: model.WorkerId ?? throw new ArgumentNullException(nameof(model.WorkerId)), id: model.Id, modelName: model.ModelName ?? throw new ArgumentNullException(nameof(model.ModelName)), accessories: model.Accessories?.Select(c => (c.AccessoriesId ?? throw new ArgumentNullException(nameof(c.AccessoriesId)), c.Count, 0.0)).ToList() ); model.Id = "ne Id"; return model; }, "carassembly/changeinfo"); yield return new TestCaseData(() => { var post = AvtoTAZDbContext.InsertPostToDatabaseAndReturn(); var model = CreateWorkerModel(post.PostId); AvtoTAZDbContext.InsertWorkerToDatabaseAndReturn(model.Id, postId: post.PostId); model.Id = "ne Id"; return model; }, "workers/changeinfo"); } [TestCaseSource(nameof(TestDataIdIncorrectForPut))] public async Task Api_Put_WhenDataIsIncorrect_ShouldBadRequest_Test(Func createModel, string path) { // Arrange var model = createModel(); // Act var response = await HttpClient.PutAsync($"/api/{path}", MakeContent(model)); // Assert Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementIdIncorrect())); } [TestCaseSource(nameof(TestDataElementExists))] public async Task Api_Post_WhenHaveRecordWithSameId_ShouldBadRequest_Test(Func createModel, string path) { // Arrange var model = createModel(); // Act var response = await HttpClient.PostAsync($"/api/{path}", MakeContent(model)); // Логирование для диагностики var responseContent = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Response for path {path}: {responseContent}"); Console.WriteLine($"Status Code: {response.StatusCode}"); // Assert Assert.That(JToken.Parse(responseContent).ToString(), Does.StartWith(MessageElementExists())); } private static async Task GetModelFromResponseAsync(HttpResponseMessage response) => JsonSerializer.Deserialize(await response.Content.ReadAsStringAsync(), JsonSerializerOptions); private static StringContent MakeContent(object model) => new(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json"); private static DealerBindingModel CreateDealerBindingModel( string? id = null, string fio = "fio", string? phone = null, string? email = null, double discountSize = 10) { var uniqueId = Guid.NewGuid().ToString(); return new() { Id = id ?? Guid.NewGuid().ToString(), NameDealer = fio, }; } private static PostBindingModel CreatePostModel(string? postId = null, string? postName = null, PostType postType = PostType.Manager, string? configuration = null) { var uniqueId = Guid.NewGuid().ToString(); return new() { Id = postId ?? uniqueId, PostName = postName ?? $"Post_{uniqueId}", PostType = postType.ToString(), ConfigurationJson = configuration ?? JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 }) }; } private static CarAssemblyBindingModel CreateCarAssemblyModel(string? id = null, string productName = "name", int count = 2, double totalPrice = 10, List? components = null) { var uniqueId = Guid.NewGuid().ToString(); var productId = id ?? uniqueId; return new CarAssemblyBindingModel { Id = productId, ModelName = $"{productName}_{uniqueId}", WorkerId = _workerId, AutoType = AutoType.Jeep, Accessories = components }; } private static WorkerBindingModel CreateWorkerModel(string postId, string? id = null, string fio = "fio", DateTime? birthDate = null, DateTime? employmentDate = null) => new() { Id = id ?? Guid.NewGuid().ToString(), FIO = fio, BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-22), EmploymentDate = employmentDate ?? DateTime.UtcNow.AddDays(-5), PostId = postId }; }