forked from slavaxom9k/PIBD-23_Fomichev_V.S._MagicCarpet
453 lines
18 KiB
C#
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
|
|
};
|
|
}
|