-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: adding unit and integration tests for filter recipe
- Loading branch information
1 parent
cf97bb5
commit 4f89ede
Showing
8 changed files
with
364 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
using Bogus; | ||
using MyRecipes.Domain.Entities; | ||
using MyRecipes.Domain.Enums; | ||
|
||
namespace CommonTestsUtilities.Entities; | ||
public class RecipeBuilder | ||
{ | ||
public static IList<Recipe> Collecion(User user, uint count = 2) | ||
{ | ||
var list = new List<Recipe>(); | ||
|
||
if (count == 0) | ||
count = 1; | ||
|
||
var recipeId = 1; | ||
|
||
for (int i = 0; i < count; i++) | ||
{ | ||
var fakeRecipe = Build(user); | ||
fakeRecipe.Id = recipeId++; | ||
list.Add(fakeRecipe); | ||
} | ||
|
||
return list; | ||
} | ||
|
||
public static Recipe Build(User user) | ||
{ | ||
return new Faker<Recipe>() | ||
.RuleFor(r => r.Id, () => 1) | ||
.RuleFor(r => r.Title, (f) => f.Lorem.Word()) | ||
.RuleFor(r => r.CookingTime, (f) => f.PickRandom<CookingTime>()) | ||
.RuleFor(r => r.Difficulty, (f) => f.PickRandom<Difficulty>()) | ||
.RuleFor(r => r.Ingredients, (f) => f.Make(1, () => new Ingredient | ||
{ | ||
Id = 1, | ||
Item = f.Commerce.ProductName() | ||
})) | ||
.RuleFor(r => r.Instructions, (f) => f.Make(1, () => new Instruction | ||
{ | ||
Id = 1, | ||
Step = 1, | ||
Text = f.Lorem.Paragraph() | ||
})) | ||
.RuleFor(r => r.DishTypes, (f) => f.Make(1, () => new MyRecipes.Domain.Entities.DishType | ||
{ | ||
Id = 1, | ||
Type = f.PickRandom<MyRecipes.Domain.Enums.DishType>() | ||
})) | ||
.RuleFor(r => r.UserId, () => user.Id); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
tests/CommonTestsUtilities/Repositories/RecipeReadOnlyRepositoryBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using Moq; | ||
using MyRecipes.Domain.Dtos; | ||
using MyRecipes.Domain.Entities; | ||
using MyRecipes.Domain.Repositories.Recipe; | ||
|
||
namespace CommonTestsUtilities.Repositories; | ||
public class RecipeReadOnlyRepositoryBuilder | ||
{ | ||
private readonly Mock<IRecipeReadOnlyRepository> _repository; | ||
|
||
public RecipeReadOnlyRepositoryBuilder(Mock<IRecipeReadOnlyRepository> repository) => _repository = repository; | ||
|
||
public RecipeReadOnlyRepositoryBuilder Filter(User user, IList<Recipe> recipes) | ||
{ | ||
_repository.Setup(r => r.Filter(user, It.IsAny<FilterRecipesDto>())).ReturnsAsync(recipes); | ||
return this; | ||
} | ||
|
||
public RecipeReadOnlyRepositoryBuilder() => _repository = new Mock<IRecipeReadOnlyRepository>(); | ||
|
||
public IRecipeReadOnlyRepository Build() => _repository.Object; | ||
} |
16 changes: 16 additions & 0 deletions
16
tests/CommonTestsUtilities/Requests/RequestFilterRecipeJsonBuilder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
using Bogus; | ||
using MyRecipes.Communication.Enums; | ||
using MyRecipes.Communication.Requests; | ||
|
||
namespace CommonTestsUtilities.Requests; | ||
public class RequestFilterRecipeJsonBuilder | ||
{ | ||
public static RequestFilterRecipeJson Build() | ||
{ | ||
return new Faker<RequestFilterRecipeJson>() | ||
.RuleFor(r => r.CookingTimes, f => f.Make(1, () => f.PickRandom<CookingTime>())) | ||
.RuleFor(r => r.Difficulties, f => f.Make(1, () => f.PickRandom<Difficulty>())) | ||
.RuleFor(r => r.DishTypes, f => f.Make(1, () => f.PickRandom<DishType>())) | ||
.RuleFor(r => r.RecipeTitle_Ingredient, f => f.Lorem.Word()); | ||
} | ||
} |
61 changes: 61 additions & 0 deletions
61
tests/UseCases.Tests/Recipe/Filter/FilterRecipeUseCaseTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
using CommonTestsUtilities.Entities; | ||
using CommonTestsUtilities.LoggedUser; | ||
using CommonTestsUtilities.Mapper; | ||
using CommonTestsUtilities.Repositories; | ||
using CommonTestsUtilities.Requests; | ||
using FluentAssertions; | ||
using MyRecipes.Application.UseCases.Recipe.Filter; | ||
using MyRecipes.Communication.Enums; | ||
using MyRecipes.Exceptions; | ||
using MyRecipes.Exceptions.ExceptionsBase; | ||
|
||
namespace UseCases.Tests.Recipe.Filter; | ||
public class FilterRecipeUseCaseTest | ||
{ | ||
[Fact] | ||
public async Task Success() | ||
{ | ||
var (user, _) = UserBuilder.Build(); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
var recipes = RecipeBuilder.Collecion(user); | ||
|
||
var useCase = CreateUseCase(user, recipes); | ||
|
||
var result = await useCase.Execute(request); | ||
|
||
result.Should().NotBeNull(); | ||
result.Recipes.Should().NotBeNullOrEmpty(); | ||
result.Recipes.Should().HaveCount(recipes.Count); | ||
} | ||
|
||
[Fact] | ||
public async Task Error_CookintTime_Invalid() | ||
{ | ||
var (user, _) = UserBuilder.Build(); | ||
|
||
var recipes = RecipeBuilder.Collecion(user); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.CookingTimes.Add((CookingTime)99999); | ||
|
||
|
||
var useCase = CreateUseCase(user, recipes); | ||
|
||
Func<Task> act = async () => await useCase.Execute(request); | ||
|
||
(await act.Should().ThrowAsync<ErrorOnValidationException>()) | ||
.Where(e => e.ErrorMessages.Count == 1 && | ||
e.ErrorMessages.Contains(ResourceMessagesExceptions.COOKING_TIME_NOT_SUPPORTED)); | ||
} | ||
|
||
private static FilterRecipeUseCase CreateUseCase(MyRecipes.Domain.Entities.User user, | ||
IList<MyRecipes.Domain.Entities.Recipe> recipes) | ||
{ | ||
var mapper = MapperBuilder.Build(); | ||
var loggedUser = LoggedUserBuilder.Build(user); | ||
var repository = new RecipeReadOnlyRepositoryBuilder().Filter(user, recipes).Build(); | ||
|
||
return new FilterRecipeUseCase(loggedUser, mapper, repository); | ||
} | ||
} |
66 changes: 66 additions & 0 deletions
66
tests/Validators.Tests/Recipe/Filter/FilterRecipeValidatorTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
using CommonTestsUtilities.Requests; | ||
using FluentAssertions; | ||
using MyRecipes.Application.UseCases.Recipe.Filter; | ||
using MyRecipes.Communication.Enums; | ||
using MyRecipes.Exceptions; | ||
|
||
namespace Validators.Tests.Recipe.Filter; | ||
public class FilterRecipeValidatorTest | ||
{ | ||
[Fact] | ||
public void Success() | ||
{ | ||
var validator = new FilterRecipeValidator(); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
|
||
var result = validator.Validate(request); | ||
|
||
result.IsValid.Should().BeTrue(); | ||
} | ||
|
||
[Fact] | ||
public void Error_Invalid_Cooking_Time() | ||
{ | ||
var validator = new FilterRecipeValidator(); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.CookingTimes.Add((CookingTime)1000); | ||
|
||
var result = validator.Validate(request); | ||
|
||
result.IsValid.Should().BeFalse(); | ||
result.Errors.Should().ContainSingle() | ||
.And.Contain(e => e.ErrorMessage.Equals(ResourceMessagesExceptions.COOKING_TIME_NOT_SUPPORTED)); | ||
} | ||
|
||
[Fact] | ||
public void Error_Invalid_Difficulty() | ||
{ | ||
var validator = new FilterRecipeValidator(); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.Difficulties.Add((Difficulty)1000); | ||
|
||
var result = validator.Validate(request); | ||
|
||
result.IsValid.Should().BeFalse(); | ||
result.Errors.Should().ContainSingle() | ||
.And.Contain(e => e.ErrorMessage.Equals(ResourceMessagesExceptions.DIFFICULTY_LEVEL_NOT_SUPPORTED)); | ||
} | ||
|
||
[Fact] | ||
public void Error_Invalid_DishType() | ||
{ | ||
var validator = new FilterRecipeValidator(); | ||
|
||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.DishTypes.Add((DishType)1000); | ||
|
||
var result = validator.Validate(request); | ||
|
||
result.IsValid.Should().BeFalse(); | ||
result.Errors.Should().ContainSingle() | ||
.And.Contain(e => e.ErrorMessage.Equals(ResourceMessagesExceptions.DISH_TYPE_NOT_SUPPORTED)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
44 changes: 44 additions & 0 deletions
44
tests/WebApi.Tests/Recipe/Filter/FilterRecipeInvalidTokenTest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
using CommonTestsUtilities.Requests; | ||
using CommonTestsUtilities.Tokens; | ||
using FluentAssertions; | ||
using System.Net; | ||
|
||
namespace WebApi.Tests.Recipe.Filter; | ||
public class FilterRecipeInvalidTokenTest : MyRecipesClassFixture | ||
{ | ||
private const string METHOD = "recipes/filter"; | ||
public FilterRecipeInvalidTokenTest(CustomWebApplicationFactory factory) : base(factory) | ||
{ | ||
} | ||
|
||
[Fact] | ||
public async Task Error_Token_Invalid() | ||
{ | ||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
|
||
var response = await DoPost(method: METHOD, request: request, token: "invalidToken"); | ||
|
||
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); | ||
} | ||
|
||
[Fact] | ||
public async Task Error_Without_Token() | ||
{ | ||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
|
||
var response = await DoPost(method: METHOD, request: request, token: string.Empty); | ||
|
||
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); | ||
} | ||
|
||
[Fact] | ||
public async Task Error_Token_With_User_NotFound() | ||
{ | ||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
var token = JwtTokenGeneratorBuilder.Build().Generate(Guid.NewGuid()); | ||
|
||
var response = await DoPost(method: METHOD, request: request, token: token); | ||
|
||
response.StatusCode.Should().Be(HttpStatusCode.Unauthorized); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using CommonTestsUtilities.Requests; | ||
using CommonTestsUtilities.Tokens; | ||
using FluentAssertions; | ||
using MyRecipes.Communication.Requests; | ||
using MyRecipes.Exceptions; | ||
using System.Globalization; | ||
using System.Net; | ||
using System.Text.Json; | ||
using WebApi.Tests.InlineData; | ||
|
||
namespace WebApi.Tests.Recipe.Filter; | ||
public class FilterRecipeTest : MyRecipesClassFixture | ||
{ | ||
private const string METHOD = "recipes/filter"; | ||
|
||
private readonly Guid _userIdentifier; | ||
private readonly string _recipeTitle; | ||
private readonly MyRecipes.Domain.Enums.CookingTime _recipeCookingTime; | ||
private readonly MyRecipes.Domain.Enums.Difficulty _recipeDifficultyLevel; | ||
private readonly IList<MyRecipes.Domain.Enums.DishType> _recipeDishTypes; | ||
|
||
|
||
public FilterRecipeTest(CustomWebApplicationFactory factory) : base(factory) | ||
{ | ||
_userIdentifier = factory.GetUserIdentifier(); | ||
|
||
_recipeTitle = factory.GetRecipeTitle(); | ||
_recipeCookingTime = factory.GetRecipeCookingTime(); | ||
_recipeDifficultyLevel = factory.GetRecipeDifficulty(); | ||
_recipeDishTypes = factory.GetDishTypes(); | ||
} | ||
|
||
[Fact] | ||
public async Task Success() | ||
{ | ||
var request = new RequestFilterRecipeJson | ||
{ | ||
CookingTimes = [(MyRecipes.Communication.Enums.CookingTime)_recipeCookingTime], | ||
Difficulties = [(MyRecipes.Communication.Enums.Difficulty)_recipeDifficultyLevel], | ||
DishTypes = [.. _recipeDishTypes.Select(dishType => (MyRecipes.Communication.Enums.DishType)dishType)], | ||
RecipeTitle_Ingredient = _recipeTitle, | ||
}; | ||
|
||
var token = JwtTokenGeneratorBuilder.Build().Generate(_userIdentifier); | ||
|
||
var response = await DoPost(method: METHOD, request: request, token: token); | ||
|
||
response.StatusCode.Should().Be(HttpStatusCode.OK); | ||
|
||
using var resopnseBody = await response.Content.ReadAsStreamAsync(); | ||
var responseData = await JsonDocument.ParseAsync(resopnseBody); | ||
|
||
responseData.RootElement.GetProperty("recipes").EnumerateArray().Should().NotBeNullOrEmpty(); | ||
} | ||
|
||
[Fact] | ||
public async Task Success_NoContent() | ||
{ | ||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.RecipeTitle_Ingredient = "recipe-not-found"; | ||
|
||
var token = JwtTokenGeneratorBuilder.Build().Generate(_userIdentifier); | ||
|
||
var response = await DoPost(method: METHOD, request: request, token: token); | ||
|
||
response.StatusCode.Should().Be(HttpStatusCode.NoContent); | ||
} | ||
|
||
[Theory] | ||
[ClassData(typeof(CultureInlineDataTest))] | ||
public async Task Error_CookingTime_Invalid(string culture) | ||
{ | ||
var request = RequestFilterRecipeJsonBuilder.Build(); | ||
request.CookingTimes.Add((MyRecipes.Communication.Enums.CookingTime)999); | ||
var token = JwtTokenGeneratorBuilder.Build().Generate(_userIdentifier); | ||
|
||
var result = await DoPost(method: METHOD, request: request, token: token, culture: culture); | ||
|
||
result.StatusCode.Should().Be(HttpStatusCode.BadRequest); | ||
|
||
await using var responseBody = await result.Content.ReadAsStreamAsync(); | ||
|
||
var responseData = await JsonDocument.ParseAsync(responseBody); | ||
|
||
var errors = responseData.RootElement.GetProperty("errors").EnumerateArray(); | ||
|
||
var expectedMessage = ResourceMessagesExceptions.ResourceManager.GetString("COOKING_TIME_NOT_SUPPORTED", new CultureInfo(culture)); | ||
|
||
errors.Should().HaveCount(1).And.Contain(c => c.GetString()!.Equals(expectedMessage)); | ||
} | ||
} |