Files
Check/MagicCarpetProject/MagicCarpetTests/LocalizationTests/BaseLocalizationControllerTests.cs
2025-05-13 18:08:27 +04:00

453 lines
18 KiB
C#

using MagicCarpetContracts.BindingModels;
using MagicCarpetContracts.Enums;
using MagicCarpetContracts.Infrastructure.PostConfigurations;
using MagicCarpetDatabase;
using MagicCarpetTests.Infrastructure;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using Serilog;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace MagicCarpetTests.LocalizationTests;
internal abstract class BaseLocalizationControllerTests
{
protected abstract string GetLocale();
private WebApplicationFactory<Program> _webApplication;
protected HttpClient HttpClient { get; private set; }
protected static MagicCarpetDbContext MagicCarpetDbContext { get; private set; }
protected static readonly JsonSerializerOptions JsonSerializerOptions = new() { PropertyNameCaseInsensitive = true };
private static string _employeeId;
private static string _postId;
private static string _tourId;
[OneTimeSetUp]
public void OneTimeSetUp()
{
_webApplication = new CustomWebApplicationFactory<Program>();
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());
MagicCarpetDbContext = _webApplication.Services.GetRequiredService<MagicCarpetDbContext>();
MagicCarpetDbContext.Database.EnsureDeleted();
MagicCarpetDbContext.Database.EnsureCreated();
}
[SetUp]
public void SetUp()
{
_employeeId = MagicCarpetDbContext.InsertEmployeeToDatabaseAndReturn(fio: "Employee").Id;
_postId = MagicCarpetDbContext.InsertPostToDatabaseAndReturn(postName: "Post").PostId;
_tourId = MagicCarpetDbContext.InsertTourToDatabaseAndReturn().Id;
}
[TearDown]
public void TearDown()
{
MagicCarpetDbContext.RemoveSalariesFromDatabase();
MagicCarpetDbContext.RemoveEmployeesFromDatabase();
MagicCarpetDbContext.RemovePostsFromDatabase();
MagicCarpetDbContext.RemoveToursFromDatabase();
MagicCarpetDbContext.RemoveSalesFromDatabase();
}
[OneTimeTearDown]
public void OneTimeTearDown()
{
MagicCarpetDbContext?.Database.EnsureDeleted();
MagicCarpetDbContext?.Dispose();
HttpClient?.Dispose();
_webApplication?.Dispose();
}
protected static async Task<T?> GetModelFromResponseAsync<T>(HttpResponseMessage response) =>
JsonSerializer.Deserialize<T>(await response.Content.ReadAsStringAsync(), JsonSerializerOptions);
protected static StringContent MakeContent(object model) =>
new(JsonSerializer.Serialize(model), Encoding.UTF8, "application/json");
[Test]
public async Task LoadToursHistory_ReturnsFile()
{
//Arrange
MagicCarpetDbContext.InsertTourToDatabaseAndReturn(tourName: "Tour1");
MagicCarpetDbContext.InsertTourToDatabaseAndReturn(tourName: "Tour2");
MagicCarpetDbContext.InsertTourToDatabaseAndReturn(tourName: "Tour3");
//Act
var response = await HttpClient.GetAsync("/api/report/LoadHistories");
//Assert
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 AssertStreamAsync(response, $"file-{GetLocale()}.docx");
}
[Test]
public async Task LoadSales_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var employee = MagicCarpetDbContext.InsertEmployeeToDatabaseAndReturn();
var tour1 = MagicCarpetDbContext.InsertTourToDatabaseAndReturn(tourName: "name 1");
var tour2 = MagicCarpetDbContext.InsertTourToDatabaseAndReturn(tourName: "name 2");
MagicCarpetDbContext.InsertSaleToDatabaseAndReturn(employee.Id, tours: [(tour1.Id, 10, 1.1), (tour2.Id, 10, 1.1)]);
MagicCarpetDbContext.InsertSaleToDatabaseAndReturn(employee.Id, tours: [(tour1.Id, 10, 1.1)]);
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsales?fromDate={DateTime.Now.AddDays(-1):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.AddDays(1):MM/dd/yyyy HH:mm:ss}");
//Assert
await AssertStreamAsync(response, $"file-{GetLocale()}.xlsx");
}
[Test]
public async Task LoadSalary_WhenHaveRecords_ShouldSuccess_Test()
{
//Arrange
var post = MagicCarpetDbContext.InsertPostToDatabaseAndReturn();
var employee1 = MagicCarpetDbContext.InsertEmployeeToDatabaseAndReturn(fio: "Иванов И.И", postId: post.PostId).AddPost(post);
var employee2 = MagicCarpetDbContext.InsertEmployeeToDatabaseAndReturn(fio: "Ванов И.И", postId: post.PostId).AddPost(post);
MagicCarpetDbContext.InsertSalaryToDatabaseAndReturn(employee1.Id, employeeSalary: 100, salaryDate: DateTime.UtcNow.AddDays(-10));
MagicCarpetDbContext.InsertSalaryToDatabaseAndReturn(employee1.Id, employeeSalary: 1000, salaryDate: DateTime.UtcNow.AddDays(-5));
MagicCarpetDbContext.InsertSalaryToDatabaseAndReturn(employee1.Id, employeeSalary: 200, salaryDate: DateTime.UtcNow.AddDays(5));
MagicCarpetDbContext.InsertSalaryToDatabaseAndReturn(employee2.Id, employeeSalary: 500, salaryDate: DateTime.UtcNow.AddDays(-5));
MagicCarpetDbContext.InsertSalaryToDatabaseAndReturn(employee2.Id, employeeSalary: 300, salaryDate: DateTime.UtcNow.AddDays(-3));
//Act
var response = await HttpClient.GetAsync($"/api/report/loadsalary?fromDate={DateTime.Now.AddDays(-7):MM/dd/yyyy HH:mm:ss}&toDate={DateTime.Now.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();
[TestCase("posts")]
[TestCase("employees/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<TestCaseData> TestDataElementExists()
{
yield return new TestCaseData(() => {
var model = CreatePostModel();
MagicCarpetDbContext.InsertPostToDatabaseAndReturn(model.Id);
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateEmployeeModel(_postId);
MagicCarpetDbContext.InsertEmployeeToDatabaseAndReturn(model.Id, postId: _postId);
return model;
}, "employees/register");
}
protected abstract string MessageElementExists();
[TestCaseSource(nameof(TestDataElementExists))]
public async Task Api_Post_WhenHaveRecordWithSameId_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var response = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await response.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementExists()));
}
private static IEnumerable<TestCaseData> TestDataIdIncorrect()
{
yield return new TestCaseData(() => {
var model = CreateSaleModel();
model.Id = "Id";
return model;
}, "sales/sale");
yield return new TestCaseData(() => {
var model = CreateTourModel();
model.Id = "Id";
return model;
}, "tours/register");
yield return new TestCaseData(() => {
var model = CreateEmployeeModel(_postId);
model.Id = "Id";
return model;
}, "employees/register");
yield return new TestCaseData(() => {
var model = CreateClientModel();
model.Id = "Id";
return model;
}, "clients");
}
protected abstract string MessageElementIdIncorrect();
[TestCaseSource(nameof(TestDataIdIncorrect))]
public async Task Api_Post_WhenDataIsIncorrect_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PostAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElementIdIncorrect()));
}
[TestCase("tours/delete")]
[TestCase("sales/cancel")]
[TestCase("posts")]
[TestCase("employees/delete")]
[TestCase("clients")]
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()));
}
private static PostBindingModel CreatePostModel(string? postId = null, string postName = "name", PostType postType = PostType.Manager, string? configuration = null)
=> new()
{
Id = postId ?? Guid.NewGuid().ToString(),
PostName = postName,
PostType = postType.ToString(),
ConfigurationJson = configuration ?? JsonSerializer.Serialize(new PostConfiguration() { Rate = 10 })
};
protected abstract string MessageValidationErrorIDIsEmpty();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsEmpty()
{
yield return new TestCaseData(() =>
{
var model = CreatePostModel();
model.Id = "";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateTourModel();
model.Id = "";
return model;
}, "tours/changeinfo");
yield return new TestCaseData(() => {
var model = CreateEmployeeModel(_postId);
model.Id = "";
return model;
}, "employees/changeinfo/");
yield return new TestCaseData(() =>
{
var model = CreateClientModel();
model.Id = "";
return model;
}, "clients");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsEmpty))]
public async Task Api_Put_ValidationError_IdIsEmpty_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageValidationErrorIDIsEmpty()));
}
protected abstract string MessageValidationErrorIDIsNotGuid();
private static IEnumerable<TestCaseData> TestDataValidationErrorIdIsNotGuid()
{
yield return new TestCaseData(() =>
{
var model = CreatePostModel();
model.Id = "id";
return model;
}, "posts");
yield return new TestCaseData(() =>
{
var model = CreateTourModel();
model.Id = "id";
return model;
}, "tours/changeinfo");
yield return new TestCaseData(() => {
var model = CreateEmployeeModel(_postId);
model.Id = "id";
return model;
}, "employees/changeinfo/");
yield return new TestCaseData(() =>
{
var model = CreateClientModel();
model.Id = "id";
return model;
}, "clients");
}
[TestCaseSource(nameof(TestDataValidationErrorIdIsNotGuid))]
public async Task Api_Put_ValidationError_IIsNotGuid_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageValidationErrorIDIsNotGuid()));
}
protected abstract string MessageValidationStringIsEmpty();
private static IEnumerable<TestCaseData> TestDataValidationErrorStringIsEmpty()
{
yield return new TestCaseData(() =>
{
var model = CreateTourModel();
model.TourName = "";
return model;
}, "tours/changeinfo");
}
[TestCaseSource(nameof(TestDataValidationErrorStringIsEmpty))]
public async Task Api_Put_ValidationError_StringIsEmpty_ShouldBadRequest_Test(Func<object> createModel, string path)
{
//Arrange
var model = createModel();
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageValidationStringIsEmpty()));
}
protected abstract string MessageElemenValidationErrorPostNameEmpty();
[TestCase("posts")]
public async Task Api_Put_ValidationError_PostNameIsEmpty_ShouldBadRequest_Test(string path)
{
//Arrange
var model = CreatePostModel();
model.PostName = "";
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElemenValidationErrorPostNameEmpty()));
}
protected abstract string MessageElemenValidationErrorFioISEmpty();
[TestCase("employees/changeinfo/")]
public async Task Api_Put_ValidationError_FioIsEmpty_ShouldBadRequest_Test(string path)
{
//Arrange
var model = CreateEmployeeModel(_postId);
model.FIO = "";
//Act
var responseWithIdIncorrect = await HttpClient.PutAsync($"/api/{path}", MakeContent(model));
//Assert
Assert.That(JToken.Parse(await responseWithIdIncorrect.Content.ReadAsStringAsync()).ToString(), Does.StartWith(MessageElemenValidationErrorFioISEmpty()));
}
private static EmployeeBindingModel CreateEmployeeModel(string postId, string? id = null, string fio = "fio", string email = "abc@gmail.com", DateTime? birthDate = null, DateTime? employmentDate = null)
{
return new()
{
Id = id ?? Guid.NewGuid().ToString(),
FIO = fio,
Email = email,
BirthDate = birthDate ?? DateTime.UtcNow.AddYears(-22),
EmploymentDate = employmentDate ?? DateTime.UtcNow.AddDays(-5),
PostId = postId
};
}
private static TourBindingModel CreateTourModel(string? id = null, string name = "name", string country = "country", TourType type = TourType.Beach, double price = 1)
=> new()
{
Id = id ?? Guid.NewGuid().ToString(),
TourName = name,
TourCountry = country,
TourType = type.ToString(),
Price = price
};
private static SaleBindingModel CreateSaleModel(string? employeeId = null, string? clientId = null, string? tourId = null, string? id = null, DiscountType discountType = DiscountType.OnSale, int count = 1, double price = 1.1)
{
var saleId = id ?? Guid.NewGuid().ToString();
return new()
{
Id = saleId,
EmployeeId = employeeId,
ClientId = clientId,
DiscountType = (int)discountType,
Tours = [new SaleTourBindingModel { SaleId = saleId, TourId = tourId, Count = count, Price = price }]
};
}
private static ClientBindingModel CreateClientModel(string? id = null, string fio = "fio", string phoneNumber = "+7-666-666-66-66", double discountSize = 10) =>
new()
{
Id = id ?? Guid.NewGuid().ToString(),
FIO = fio,
PhoneNumber = phoneNumber,
DiscountSize = discountSize
};
}