diff --git a/Api/Controllers/RestaurantController.cs b/Api/Controllers/RestaurantController.cs index dffbce2a6916b8c274a592c82b2a648cd370b29f..32b38062d3dd3156746937441835326472ec47ae 100644 --- a/Api/Controllers/RestaurantController.cs +++ b/Api/Controllers/RestaurantController.cs @@ -64,8 +64,8 @@ namespace Api.Controllers [FromBody] RestaurantUpdateModel data) { if (data.Name is null && data.About is null - && data.Email is null && data.Web is null - && data.Phone is null && data.Category is null) + && data.Email is null && data.Web is null + && data.Phone is null && data.Category is null) { return BadRequest("No data was provided."); } diff --git a/BusinessLayer.Tests/BusinessLayer.Tests.csproj b/BusinessLayer.Tests/BusinessLayer.Tests.csproj index 71f2579101b96524dbd6633cd14fb9f2753e0279..eb0347ea50bf01aba69ae88b7337c60528a39d2d 100644 --- a/BusinessLayer.Tests/BusinessLayer.Tests.csproj +++ b/BusinessLayer.Tests/BusinessLayer.Tests.csproj @@ -19,6 +19,7 @@ <ItemGroup> <ProjectReference Include="..\BusinessLayer\BusinessLayer.csproj" /> + <ProjectReference Include="..\TestUtilities\TestUtilities.csproj" /> </ItemGroup> <ItemGroup> diff --git a/BusinessLayer.Tests/Services/LocationServiceTests.cs b/BusinessLayer.Tests/Services/LocationServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..8c12ec67dfc5cfe6f32598f860e9891b18e5fc48 --- /dev/null +++ b/BusinessLayer.Tests/Services/LocationServiceTests.cs @@ -0,0 +1,326 @@ +using BusinessLayer.DTOs.Location; +using BusinessLayer.Services.LocationService; +using BusinessLayer.Utils.Filters; +using BusinessLayer.Utils.Ordering; +using TestUtilities.Constants; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Mocks; + +namespace BusinessLayer.Tests.Services +{ + public class LocationServiceTests + { + private readonly DbContextOptions<RestaurantDBContext> _dbContextOptions; + private readonly RestaurantDBContext _dbContext; + private readonly LocationService _service; + + public LocationServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new LocationService(_dbContext); + } + + [Fact] + public async Task GetLocations_IdMatch_Success() + { + // Arrange + // Locations are identified by their corresponding restaurants. + var ids = new Guid[] { FakeSeedingValues.Restaurant1Id, FakeSeedingValues.Restaurant2Id }; + + // Act + var result = await _service.GetLocationsAsync(new Utils.Filters.LocationFilter(), + LocationOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Equal(ids.Length, result.Count); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + Assert.All(ids, id => Assert.Contains(result, l => l.RestaurantId == id)); + } + + [Fact] + public async Task GetLocations_IdMatch_NotExists_ReturnsEmpty() + { + // Arrange + // Locations are identified by their corresponding restaurants. + var ids = new Guid[] { Guid.NewGuid(), Guid.NewGuid() }; + + // Act + var result = await _service.GetLocationsAsync(new LocationFilter(), + LocationOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetLocations_IdMatch_Deleted_ReturnsEmpty() + { + // Arrange + // Locations are identified by their corresponding restaurants. + var ids = new Guid[] { FakeSeedingValues.DeletedRestaurantId }; + + // Act + var result = await _service.GetLocationsAsync(new LocationFilter(), + LocationOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + + [Theory] + [InlineData(LocationOrdering.CityDesc)] + [InlineData(LocationOrdering.City)] + [InlineData(LocationOrdering.CountryDesc)] + [InlineData(LocationOrdering.Country)] + [InlineData(LocationOrdering.CreatedAtDesc)] + public async Task GetLocations_OrderBy_ValidOrdering(LocationOrdering ordering) + { + // Arrange + // Whoops, nothing to arrange here! ÂŻ\_(ă„)_/ÂŻ + + // Act + var result = await _service.GetLocationsAsync(new LocationFilter(), ordering); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + var first = result.First(); + foreach (var second in result.Skip(1)) + { + CheckOrdering(ordering, first, second); + first = second; + } + } + + private static void CheckOrdering(LocationOrdering ordering, LocationDto first, LocationDto second) + { + switch (ordering) + { + case LocationOrdering.City: + Assert.True(first.City.CompareTo(second.City) <= 0); + return; + case LocationOrdering.CityDesc: + Assert.True(first.City.CompareTo(second.City) >= 0); + return; + case LocationOrdering.Country: + Assert.True(first.Country.CompareTo(second.Country) <= 0); + return; + case LocationOrdering.CountryDesc: + Assert.True(first.Country.CompareTo(second.Country) >= 0); + return; + case LocationOrdering.CreatedAtDesc: + Assert.True(first.CreatedAt >= second.CreatedAt); + return; + } + } + + [Fact] + public async Task GetLocations_Filter_Country_ContainsOnlyValid() + { + // Arrange + var filterValue = "Fake"; + + var filter = new LocationFilter() + { + CountryLike = filterValue + }; + + // Act + var result = await _service.GetLocationsAsync(filter, LocationOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + result.ForEach(r => Assert.Contains(filterValue, r.Country)); + } + + [Fact] + public async Task GetLocations_Filter_City_ContainsOnlyValid() + { + // Arrange + var filterValue = "no"; + + var filter = new LocationFilter() + { + CityLike = filterValue + }; + + // Act + var result = await _service.GetLocationsAsync(filter, LocationOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + result.ForEach(r => Assert.Contains(filterValue, r.City)); + } + + [Fact] + public async Task GetLocations_Filter_Address_ContainsOnlyValid() + { + // Arrange + var filterValue = "Ĺ tef"; + + var filter = new LocationFilter() + { + AddressLike = filterValue + }; + + // Act + var result = await _service.GetLocationsAsync(filter, LocationOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + result.ForEach(r => Assert.Contains(filterValue, r.Address)); + } + + [Fact] + public async Task GetLocations_Filter_Zipcode_ContainsOnlyValid() + { + // Arrange + var filterValue = "60201"; + + var filter = new LocationFilter() + { + Zipcode = filterValue + }; + + // Act + var result = await _service.GetLocationsAsync(filter, LocationOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, l => Assert.Null(l.DeletedAt)); + result.ForEach(r => Assert.Equal(filterValue, r.Zipcode)); + } + + [Fact] + public async Task GetLocation_Exists_Succeeds() + { + // Arrange + var id = FakeSeedingValues.Restaurant1Id; + + // Act + var result = await _service.GetLocationAsync(id); + + // Assert + Assert.NotNull(result); + Assert.Null(result.DeletedAt); + Assert.Equal(id, result.RestaurantId); + } + + [Fact] + public async Task GetLocation_NotExists_ReturnsNull() + { + // Arrange + var id = Guid.NewGuid(); + + // Act + var result = await _service.GetLocationAsync(id); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task GetLocation_Deleted_ReturnsNull() + { + // Arrange + var id = FakeSeedingValues.DeletedRestaurantId; + + // Act + var result = await _service.GetLocationAsync(id); + + // Assert + Assert.Null(result); + } + + + [Theory] + [InlineData("Redania", null, null, null)] + [InlineData("Redania", "Oxenfurt", null, null)] + [InlineData("Redania", "Oxenfurt", "Random 15", null)] + [InlineData("Redania", "Oxenfurt", "Random 15", "43212")] + [InlineData("Redania", "Oxenfurt", null, "43212")] + [InlineData("Redania", null, "Random 15", "43212")] + [InlineData(null, null, "Random 15", "43212")] + [InlineData("Redania", null, null, "43212")] + [InlineData(null, "Oxenfurt", "Random 15", "43212")] + public async Task UpdateLocation_Valid(string? country, string? city, + string? address, string? zipcode) + { + // Arrange + var id = FakeSeedingValues.Restaurant1Id; + var data = new LocationUpdateDto + { + Country = country, + City = city, + Address = address, + Zipcode = zipcode + }; + + // Act + var result = await _service.UpdateLocationAsync(id, data); + + // Assert + Assert.NotNull(result); + Assert.Null(result.DeletedAt); + Assert.True(result.CreatedAt < result.UpdatedAt); + + if (country is not null) + { + Assert.Equal(country, result.Country); + } + + if (city is not null) + { + Assert.Equal(city, result.City); + } + + if (address is not null) + { + Assert.Equal(address, result.Address); + } + + if (zipcode is not null) + { + Assert.Equal(zipcode, result.Zipcode); + } + } + + [Fact] + public async Task UpdateLocation_NotExists_ReturnsNull() + { + var id = Guid.NewGuid(); + var data = new LocationUpdateDto + { + Country = "wontMatter", + }; + + // Act + var result = await _service.UpdateLocationAsync(id, data); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task UpdateLocation_Deleted_ReturnsNull() + { + var id = FakeSeedingValues.DeletedRestaurantId; + var data = new LocationUpdateDto + { + Country = "wontMatter", + }; + + // Act + var result = await _service.UpdateLocationAsync(id, data); + + // Assert + Assert.Null(result); + } + } +} diff --git a/BusinessLayer.Tests/Services/RestaurantServiceTests.cs b/BusinessLayer.Tests/Services/RestaurantServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..78508388feaefe2d6745ebe651baee93c3183313 --- /dev/null +++ b/BusinessLayer.Tests/Services/RestaurantServiceTests.cs @@ -0,0 +1,358 @@ +using BusinessLayer.DTOs.Location; +using BusinessLayer.DTOs.Restaurant; +using BusinessLayer.Services.RestaurantService; +using BusinessLayer.Utils.Filters; +using BusinessLayer.Utils.Ordering; +using TestUtilities.Constants; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Mocks; + +namespace BusinessLayer.Tests.Services +{ + public class RestaurantServiceTests + { + private DbContextOptions<RestaurantDBContext> _dbContextOptions; + private RestaurantDBContext _dbContext; + private RestaurantService _service; + + public RestaurantServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new RestaurantService(_dbContext); + } + + [Fact] + public async Task GetRestaurants_IdMatch_Succeeds() + { + // Arrange + var ids = new Guid[] { FakeSeedingValues.Restaurant1Id, FakeSeedingValues.Restaurant2Id }; + + // Act + var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), RestaurantOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Equal(ids.Length, result.Count); + Assert.All(result, r => Assert.Null(r.DeletedAt)); + Assert.All(ids, id => Assert.Contains(result, r => r.Id == id)); + } + + [Fact] + public async Task GetRestaurants_IdMatch_NotExists_ReturnsEmptyList() + { + // Arrange + var ids = new Guid[] { Guid.NewGuid() }; + + // Act + var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), RestaurantOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetRestaurants_IdMatch_Deleted_ReturnsEmptyList() + { + // Arrange + var ids = new Guid[] { FakeSeedingValues.DeletedRestaurantId }; + + // Act + var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), RestaurantOrdering.CreatedAtDesc, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + [Theory] + [InlineData(RestaurantOrdering.Name)] + [InlineData(RestaurantOrdering.NameDesc)] + [InlineData(RestaurantOrdering.CreatedAtDesc)] + public async Task GetRestaurants_OrderBy_OrderingIsValid(RestaurantOrdering ordering) + { + // Arrange + // Whoops, nothing to arrange here! ÂŻ\_(ă„)_/ÂŻ + + // Act + var result = await _service.GetRestaurantsAsync(new RestaurantFilter(), ordering); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.Null(r.DeletedAt)); + var first = result.First(); + foreach (var second in result.Skip(1)) + { + CheckOrdering(ordering, first, second); + first = second; + } + } + + private static void CheckOrdering(RestaurantOrdering ordering, RestaurantDto first, RestaurantDto second) + { + switch (ordering) + { + case RestaurantOrdering.Name: + Assert.True(first.Name.CompareTo(second.Name) <= 0); + return; + case RestaurantOrdering.NameDesc: + Assert.True(first.Name.CompareTo(second.Name) >= 0); + return; + case RestaurantOrdering.CreatedAtDesc: + Assert.True(first.CreatedAt >= second.CreatedAt); + return; + } + } + + [Fact] + public async Task GetRestaurants_CategoryFiltering_ContainsOnlyValid() + { + // Arrange + string expectedCategoryPart = "izza"; + RestaurantFilter ordering = new() + { + CategoryLike = expectedCategoryPart, + }; + + // Act + var result = await _service.GetRestaurantsAsync(ordering, RestaurantOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.Null(r.DeletedAt)); + Assert.All(result, r => r.Category.Contains(expectedCategoryPart)); + } + + [Fact] + public async Task GetRestaurants_NameFiltering_ContainsOnlyValid() + { + // Arrange + string expectedNamePart = "Doe"; + RestaurantFilter ordering = new() + { + NameLike = expectedNamePart, + }; + + // Act + var result = await _service.GetRestaurantsAsync(ordering, RestaurantOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.Null(r.DeletedAt)); + Assert.All(result, r => r.Name.Contains(expectedNamePart)); + } + + [Fact] + public async Task GetRestaurant_Exists_Succeeds() + { + // Arrange + Guid expectedId = FakeSeedingValues.Restaurant1Id; + + // Act + var result = await _service.GetRestaurantAsync(expectedId); + + // Assert + Assert.NotNull(result); + Assert.Equal(expectedId, result.Id); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task GetRestaurant_NotExists_ReturnsNull() + { + // Arrange + var notExistsId = Guid.NewGuid(); + + // Act + var result = await _service.GetRestaurantAsync(notExistsId); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task GetRestaurant_Deleted_ReturnsNull() + { + // Arrange + var deletedId = FakeSeedingValues.DeletedRestaurantId; + + // Act + var result = await _service.GetRestaurantAsync(deletedId); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task CreateRestaurant_Valid_Succeeds() + { + // Arrange + var mainterId = FakeSeedingValues.User1Id; + const string name = "OloMocTvaruzku"; + const string about = "Come eat your heart out in our all you can eat menu composed mostly of variants of olomoucke tvaruzky."; + const string category = "CHEESE!!!!!"; + + var location = new LocationCreateDto() + { + Country = "Czech Republic", + City = "Brno", + Address = "Holandska 68a", + Zipcode = "60200" + }; + + var data = new RestaurantCreateDto() + { + MaintainerId = mainterId, + Name = name, + About = about, + Category = category, + Location = location + }; + + // Act + var result = await _service.CreateRestaurantAsync(data); + + // Assert + Assert.NotNull(result); + Assert.Equal(name, result.Name); + Assert.Equal(about, result.About); + Assert.Equal(category, result.Category); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task CreateRestaurant_MaintainerNotExists_ReturnsNull() + { + // Arrange + var mainterId = FakeSeedingValues.User1Id; + const string name = "OloMocTvaruzku"; + const string about = "Come eat your heart out in our all you can eat menu composed mostly of variants of olomoucke tvaruzky."; + const string category = "CHEESE!!!!!"; + + var location = new LocationCreateDto() + { + Country = "Czech Republic", + City = "Brno", + Address = "Holandska 68a", + Zipcode = "60200" + }; + + var data = new RestaurantCreateDto() + { + MaintainerId = mainterId, + Name = name, + About = about, + Category = category, + Location = location + }; + + // Act + var result = await _service.CreateRestaurantAsync(data); + + // Assert + Assert.NotNull(result); + Assert.Equal(name, result.Name); + Assert.Equal(about, result.About); + Assert.Equal(category, result.Category); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task UpdateRestaurant_Valid_Succeeds() + { + // Arrange + string name = "MyRestaurant.exe"; + var restaurantData = new RestaurantUpdateDto + { + Name = name + }; + + var restaurantId = FakeSeedingValues.Restaurant1Id; + + // Act + var result = await _service.UpdateRestaurantAsync(restaurantId, restaurantData); + + // Assert + Assert.NotNull(result); + Assert.Equal(name, result.Name); + Assert.NotEqual(result.CreatedAt, result.UpdatedAt); + } + + [Fact] + public async Task UpdateRestaurant_NotExists_ReturnsNull() + { + // Arrange + string name = "MyRestaurant.exe"; + var restaurantData = new RestaurantUpdateDto + { + Name = name + }; + + var restaurantId = Guid.NewGuid(); + + // Act + var result = await _service.UpdateRestaurantAsync(restaurantId, restaurantData); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task UpdateRestaurant_Deleted_ReturnsNull() + { + // Arrange + string name = "MyRestaurant.exe"; + var restaurantData = new RestaurantUpdateDto + { + Name = name + }; + + var restaurantId = FakeSeedingValues.DeletedRestaurantId; + + // Act + var result = await _service.UpdateRestaurantAsync(restaurantId, restaurantData); + + // Assert + Assert.Null(result); + } + + + [Fact] + public async Task DeleteRestaurant_Exists_Succeeds() + { + // Arrange + var restaurantId = FakeSeedingValues.Restaurant1Id; + + // Act + var result = await _service.DeleteRestaurantAsync(restaurantId); + + // Assert + Assert.True(result); + } + + [Fact] + public async Task DeletedRestaurant_NotExists_Fails() + { + // Arrange + var restaurantId = Guid.NewGuid(); + + // Act + var result = await _service.DeleteRestaurantAsync(restaurantId); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task DeletedRestaurant_Deleted_Fails() + { + // Arrange + var restaurantId = FakeSeedingValues.DeletedRestaurantId; + + // Act + var result = await _service.DeleteRestaurantAsync(restaurantId); + + // Assert + Assert.False(result); + } + } +} diff --git a/BusinessLayer.Tests/Services/ReviewAggregateResultService.cs b/BusinessLayer.Tests/Services/ReviewAggregateResultService.cs new file mode 100644 index 0000000000000000000000000000000000000000..aa6c0da73088d5e24fb499dcef755a529aa91c42 --- /dev/null +++ b/BusinessLayer.Tests/Services/ReviewAggregateResultService.cs @@ -0,0 +1,109 @@ +using BusinessLayer.Services.ReviewAggregateService; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Constants; +using TestUtilities.Mocks; + +namespace BusinessLayer.Tests.Services +{ + public class ReviewAggregateResultServiceTests + { + private readonly DbContextOptions<RestaurantDBContext> _dbContextOptions; + private readonly RestaurantDBContext _dbContext; + private readonly ReviewAggregateResultService _service; + + public ReviewAggregateResultServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new ReviewAggregateResultService(_dbContext); + } + + [Fact] + public async Task DoesAggregateExist_ExistingId_ReturnsTrue() + { + // Arrange + var ids = new Guid[] { FakeSeedingValues.Restaurant1Id }; + + // Act + var result = await _service.DoesAggregateExistAsync(ids); + + // Assert + Assert.True(result); + } + + [Fact] + public async Task DoesAggregateExist_NonExistingId_ReturnsFalse() + { + // Arrange + var ids = new Guid[] { Guid.NewGuid() }; + + // Act + var result = await _service.DoesAggregateExistAsync(ids); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task GetAggregateByIdAsync_ExistingAggregate_ReturnsAggregate() + { + // Arrange + var id = FakeSeedingValues.Restaurant1Id; + + // Act + var result = await _service.GetAggregateByIdAsync(id); + + // Assert + Assert.NotNull(result); + Assert.Equal(id, result.RestaurantId); + Assert.InRange(result.FoodRating, (uint)1, (uint)10); + Assert.InRange(result.ServiceRating, (uint)1, (uint)10); + Assert.InRange(result.EnvironmentRating, (uint)1, (uint)10); + } + + [Fact] + public async Task GetAggregateByIdAsync_NonExistingAggregate_ReturnsNull() + { + // Arrange + var id = Guid.NewGuid(); + + // Act + var result = await _service.GetAggregateByIdAsync(id); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task GetAggregatesAsync_Limit_AppliesCorrectly() + { + // Arrange + int limit = 1; + + // Act + var result = await _service.GetAggregatesAsync(limit: limit); + + // Assert + Assert.Equal(limit, result.Count); + Assert.NotEmpty(result); + } + + [Theory] + [InlineData("food", true)] + [InlineData("service_desc", true)] + [InlineData("environment", true)] + [InlineData("", true)] + public async Task GetAggregatesAsync_OrderByOption_ReturnsOrderedResults(string orderBy, bool includeRestaurant) + { + // Act + var result = await _service.GetAggregatesAsync(orderBy: orderBy, includeRestaurant: includeRestaurant); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.InRange(r.FoodRating, (uint)1, (uint)10)); + Assert.All(result, r => Assert.InRange(r.ServiceRating, (uint)1, (uint)10)); + Assert.All(result, r => Assert.InRange(r.EnvironmentRating, (uint)1, (uint)10)); + } + } +} diff --git a/BusinessLayer.Tests/Services/ReviewCommentServiceTests.cs b/BusinessLayer.Tests/Services/ReviewCommentServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..54464af0585823d28003a5c2e64c90fbd0b82a3a --- /dev/null +++ b/BusinessLayer.Tests/Services/ReviewCommentServiceTests.cs @@ -0,0 +1,155 @@ +using BusinessLayer.DTOs.ReviewComment; +using BusinessLayer.Services.ReviewCommentService; +using BusinessLayer.Utils.Filters; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Constants; +using TestUtilities.Mocks; + +namespace BusinessLayer.Tests.Services +{ + public class ReviewCommentServiceTests + { + private readonly DbContextOptions<RestaurantDBContext> _dbContextOptions; + private readonly RestaurantDBContext _dbContext; + private readonly ReviewCommentService _service; + + public ReviewCommentServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new ReviewCommentService(_dbContext); + } + + [Fact] + public async Task CreateCommentAsync_ValidData_Succeeds() + { + // Arrange + var data = new ReviewCommentCreateDTO + { + PosterId = FakeSeedingValues.User1Id, + ReviewId = FakeSeedingValues.Review1Id, + Content = "This is a test comment." + }; + + // Act + var result = await _service.CreateCommentAsync(data); + + // Assert + Assert.NotNull(result); + Assert.Equal(data.Content, result.Content); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task CreateCommentAsync_NonExistentUserOrReview_ReturnsNull() + { + // Arrange + var data = new ReviewCommentCreateDTO + { + PosterId = Guid.NewGuid(), // Non-existent user + ReviewId = Guid.NewGuid(), // Non-existent review + Content = "Invalid comment due to missing user/review." + }; + + // Act + var result = await _service.CreateCommentAsync(data); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task DeleteCommentAsync_CommentExists_Succeeds() + { + // Arrange + var commentId = FakeSeedingValues.ReviewComment1Id; + + // Act + var result = await _service.DeleteCommentAsync(commentId); + + // Assert + Assert.True(result); + } + + [Fact] + public async Task DeleteCommentAsync_CommentNotExists_ReturnsFalse() + { + // Arrange + var commentId = Guid.NewGuid(); + + // Act + var result = await _service.DeleteCommentAsync(commentId); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task GetByIdAsync_CommentExists_Succeeds() + { + // Arrange + var commentId = FakeSeedingValues.ReviewComment1Id; + + // Act + var result = await _service.GetByIdAsync(commentId); + + // Assert + Assert.NotNull(result); + Assert.Equal(commentId, result.Id); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task GetCommentsAsync_Filtered_ReturnsExpectedResults() + { + // Arrange + var filter = new ReviewCommentFilter + { + ReviewId = FakeSeedingValues.Review1Id + }; + + // Act + var result = await _service.GetCommentsAsync(filter); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.Equal(FakeSeedingValues.Review1Id, r.ReviewId)); + } + + [Fact] + public async Task UpdateCommentAsync_CommentExists_Succeeds() + { + // Arrange + var commentId = FakeSeedingValues.ReviewComment1Id; + var updateData = new ReviewCommentUpdateDTO + { + Content = "Updated comment content." + }; + + // Act + var result = await _service.UpdateCommentAsync(commentId, updateData); + + // Assert + Assert.NotNull(result); + Assert.Equal(updateData.Content, result.Content); + } + + [Fact] + public async Task UpdateCommentAsync_CommentNotExists_ReturnsNull() + { + // Arrange + var commentId = Guid.NewGuid(); + var updateData = new ReviewCommentUpdateDTO + { + Content = "Non-existent comment update." + }; + + // Act + var result = await _service.UpdateCommentAsync(commentId, updateData); + + // Assert + Assert.Null(result); + } + } +} diff --git a/BusinessLayer.Tests/Services/ReviewServiceTests.cs b/BusinessLayer.Tests/Services/ReviewServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..f71bb6a3cfafa0246337bf457e21b44a04c7873a --- /dev/null +++ b/BusinessLayer.Tests/Services/ReviewServiceTests.cs @@ -0,0 +1,213 @@ +using BusinessLayer.DTOs.Review; +using BusinessLayer.Services.ReviewService; +using BusinessLayer.Utils.Filters; +using BusinessLayer.Utils.Ordering; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Constants; +using TestUtilities.Mocks; + + +namespace BusinessLayer.Tests.Services +{ + public class ReviewServiceTests + { + private readonly DbContextOptions<RestaurantDBContext> _dbContextOptions; + private readonly RestaurantDBContext _dbContext; + private readonly ReviewService _service; + + public ReviewServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new ReviewService(_dbContext); + } + + [Fact] + public async Task CreateReviewAsync_ValidData_Succeeds() + { + // Arrange + var data = new ReviewCreateDTO + { + PosterId = FakeSeedingValues.User1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, + Content = "Great restaurant!", + FoodRating = 9, + ServiceRating = 8, + EnvironmentRating = 7, + ServesFreeWater = true, + TimeSpent = 1.5f, + LeftTip = true + }; + + // Act + var result = await _service.CreateReviewAsync(data); + + // Assert + Assert.NotNull(result); + Assert.Equal(data.Content, result.Content); + Assert.Equal(data.FoodRating, result.FoodRating); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task CreateReviewAsync_UserOrRestaurantNotFound_ReturnsNull() + { + // Arrange + var data = new ReviewCreateDTO + { + PosterId = Guid.NewGuid(), // Non-existent user + RestaurantId = Guid.NewGuid(), // Non-existent restaurant + Content = "Great restaurant!", + FoodRating = 9, + ServiceRating = 8, + EnvironmentRating = 7 + }; + + // Act + var result = await _service.CreateReviewAsync(data); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task DeleteReviewByIdAsync_ReviewExists_Succeeds() + { + // Arrange + var reviewId = FakeSeedingValues.Review1Id; + + // Act + var result = await _service.DeleteReviewByIdAsync(reviewId); + + // Assert + Assert.True(result); + } + + [Fact] + public async Task DeleteReviewByIdAsync_ReviewNotExists_ReturnsFalse() + { + // Arrange + var reviewId = Guid.NewGuid(); + + // Act + var result = await _service.DeleteReviewByIdAsync(reviewId); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task DeleteReviewByIdAsync_DeletedReview_ReturnsFalse() + { + // Arrange + var reviewId = FakeSeedingValues.DeletedReviewId; + + // Act + var result = await _service.DeleteReviewByIdAsync(reviewId); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task GetReviewAsync_ReviewExists_Succeeds() + { + // Arrange + var reviewId = FakeSeedingValues.Review1Id; + + // Act + var result = await _service.GetReviewAsync(reviewId); + + // Assert + Assert.NotNull(result); + Assert.Equal(reviewId, result.Id); + Assert.Null(result.DeletedAt); + } + + [Fact] + public async Task GetReviewsAsync_Filtered_ReturnsExpectedResults() + { + // Arrange + var filter = new ReviewFilter + { + RestaurantId = FakeSeedingValues.Restaurant1Id + }; + + // Act + var result = await _service.GetReviewsAsync(filter, ReviewOrdering.CreatedAtDesc); + + // Assert + Assert.NotEmpty(result); + Assert.All(result, r => Assert.Equal(FakeSeedingValues.Restaurant1Id, r.RestaurantId)); + } + + [Fact] + public async Task GetReviewAsync_DeletedReview_ReturnsNull() + { + // Arrange + var reviewId = FakeSeedingValues.DeletedReviewId; + + // Act + var result = await _service.GetReviewAsync(reviewId); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task UpdateReviewAsync_ReviewExists_Succeeds() + { + // Arrange + var reviewId = FakeSeedingValues.Review1Id; + var updateData = new ReviewUpdateDTO + { + Content = "Updated review content", + FoodRating = 10 + }; + + // Act + var result = await _service.UpdateReviewAsync(reviewId, updateData); + + // Assert + Assert.NotNull(result); + Assert.Equal(updateData.Content, result.Content); + Assert.Equal(updateData.FoodRating, result.FoodRating); + } + + [Fact] + public async Task UpdateReviewAsync_ReviewNotExists_ReturnsNull() + { + // Arrange + var reviewId = Guid.NewGuid(); + var updateData = new ReviewUpdateDTO + { + Content = "Non-existent review content" + }; + + // Act + var result = await _service.UpdateReviewAsync(reviewId, updateData); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task UpdateReviewAsync_DeletedReview_ReturnsNull() + { + // Arrange + var reviewId = FakeSeedingValues.DeletedReviewId; + var updateData = new ReviewUpdateDTO + { + Content = "Updated content for a deleted review" + }; + + // Act + var result = await _service.UpdateReviewAsync(reviewId, updateData); + + // Assert + Assert.Null(result); + } + + } +} diff --git a/BusinessLayer.Tests/Services/UserServiceTests.cs b/BusinessLayer.Tests/Services/UserServiceTests.cs new file mode 100644 index 0000000000000000000000000000000000000000..53ec3389c2ef56059c5a28da6de8e154d8daa80c --- /dev/null +++ b/BusinessLayer.Tests/Services/UserServiceTests.cs @@ -0,0 +1,268 @@ + +using BusinessLayer.DTOs.User; +using BusinessLayer.Services.UserService; +using BusinessLayer.Utils.Filters; +using BusinessLayer.Utils.Ordering; +using DAL.Data; +using Microsoft.EntityFrameworkCore; +using TestUtilities.Constants; +using TestUtilities.Mocks; + +namespace BusinessLayer.Tests.Services +{ + public class UserServiceTests + { + private readonly DbContextOptions<RestaurantDBContext> _dbContextOptions; + private readonly RestaurantDBContext _dbContext; + private readonly UserService _service; + + public UserServiceTests() + { + _dbContextOptions = MockedDbContext.CreateInMemoryContextOptions(); + _dbContext = MockedDbContext.CreateContext(_dbContextOptions); + _service = new UserService(_dbContext); + } + + [Fact] + public async Task GetUsersAsync_IdMatch_Succeeds() + { + // Arrange + var ids = new Guid[] { FakeSeedingValues.User1Id, FakeSeedingValues.User2Id }; + + // Act + var result = await _service.GetUsersAsync(new UserFilter(), UserOrdering.Name, 0, 0, ids); + + // Assert + Assert.Equal(ids.Length, result.Count); + Assert.All(result, u => Assert.Null(u.DeletedAt)); + Assert.All(ids, id => Assert.Contains(result, u => u.Id == id)); + } + + [Fact] + public async Task GetUsersAsync_IdMatch_NotExists_ReturnsEmpty() + { + // Arrange + var ids = new Guid[] { Guid.NewGuid(), Guid.NewGuid() }; + + // Act + var result = await _service.GetUsersAsync(new UserFilter(), UserOrdering.Name, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetUsersAsync_IdMatch_DeletedUser_ReturnsEmpty() + { + // Arrange + var ids = new Guid[] { FakeSeedingValues.DeletedUserId }; + + // Act + var result = await _service.GetUsersAsync(new UserFilter(), UserOrdering.Name, 0, 0, ids); + + // Assert + Assert.Empty(result); + } + + [Fact] + public async Task GetUsersAsync_Filtering_Name_ContainsOnlyValid() + { + // Arrange + var name = "Erik"; + var filter = new UserFilter + { + NameLike = name + }; + + // Act + var result = await _service.GetUsersAsync(filter, UserOrdering.Name); + + // Assert + Assert.NotNull(result); + Assert.All(result, u => Assert.Null(u.DeletedAt)); + Assert.All(result, u => u.Name.Contains(name)); + } + + [Theory] + [InlineData(UserOrdering.Name)] + [InlineData(UserOrdering.NameDesc)] + [InlineData(UserOrdering.CreatedAtDesc)] + public async Task GetUsersAsync_Ordering_ValidOrdering(UserOrdering ordering) + { + // Arrange - Not needed + // Act + var result = await _service.GetUsersAsync(new UserFilter(), ordering); + + // Assert + Assert.NotEmpty(result); + var first = result.First(); + foreach (var second in result.Skip(1)) + { + CheckOrdering(ordering, first, second); + first = second; + } + } + + private static void CheckOrdering(UserOrdering ordering, UserDto first, UserDto second) + { + switch (ordering) + { + case UserOrdering.Name: + Assert.True(first.Name.CompareTo(second.Name) <= 0); + return; + case UserOrdering.NameDesc: + Assert.True(first.Name.CompareTo(second.Name) >= 0); + return; + case UserOrdering.CreatedAtDesc: + Assert.True(first.CreatedAt >= second.CreatedAt); + return; + } + } + + [Fact] + public async Task GetUserAsync_Exists_Succeeds() + { + // Arrange + var id = FakeSeedingValues.User1Id; + + // Act + var result = await _service.GetUserAsync(id); + + // Assert + Assert.NotNull(result); + Assert.Equal(id, result.Id); + } + + [Fact] + public async Task GetUserAsync_NotExists_ReturnsNull() + { + // Arrange + var id = Guid.NewGuid(); + + // Act + var result = await _service.GetUserAsync(id); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task GetUserAsync_DeletedUser_ReturnsNull() + { + // Arrange + var id = FakeSeedingValues.DeletedUserId; + + // Act + var result = await _service.GetUserAsync(id); + + // Assert + Assert.Null(result); + } + + [Theory] + [InlineData("Fedorrr", null)] + [InlineData(null, "Bombuliak123@mail.muni.cz")] + [InlineData("Fedorrr", "Bombuliak123@mail.muni.cz")] + public async Task UpdateUserAsync_Valid_Succeeds(string? name, string? email) + { + // Arrange + var id = FakeSeedingValues.User1Id; + var data = new UserUpdateDto() + { + Name = name, + Email = email + }; + + // Act + var result = await _service.UpdateUserAsync(id, data); + + // Assert + Assert.NotNull(result); + Assert.Equal(id, result.Id); + Assert.True(result.CreatedAt < result.UpdatedAt); + + if (name is not null) + { + Assert.Equal(name, result.Name); + } + + if (email is not null) + { + Assert.Equal(email, result.Email); + } + } + + [Fact] + public async Task UpdateUserAsync_NotExists_ReturnsNull() + { + // Arrange + var id = Guid.NewGuid(); + var data = new UserUpdateDto() + { + Name = "name", + }; + + // Act + var result = await _service.UpdateUserAsync(id, data); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task UpdateUserAsync_DeletedUser_ReturnsNull() + { + // Arrange + var id = FakeSeedingValues.DeletedUserId; + var data = new UserUpdateDto() + { + Name = "name", + }; + + // Act + var result = await _service.UpdateUserAsync(id, data); + + // Assert + Assert.Null(result); + } + + [Fact] + public async Task DeleteUser_Exists_Succeeds() + { + // Arrange + var id = FakeSeedingValues.User1Id; + + // Act + var result = await _service.DeleteUserAsync(id); + + // Assert + Assert.True(result); + } + + [Fact] + public async Task DeleteUser_NotExists_Fails() + { + // Arrange + var id = Guid.NewGuid(); + + // Act + var result = await _service.DeleteUserAsync(id); + + // Assert + Assert.False(result); + } + + [Fact] + public async Task DeleteUser_AlreadyDeleted_Fails() + { + // Arrange + var id = FakeSeedingValues.DeletedUserId; + + // Act + var result = await _service.DeleteUserAsync(id); + + // Assert + Assert.False(result); + } + } +} diff --git a/BusinessLayer/DTOs/Location/LocationDto.cs b/BusinessLayer/DTOs/Location/LocationDto.cs index e718660e98e08c52ffd002bd16b8831c9b862a96..7fb9d3512a2d89b646b6ad4272ceeb94d2e079a6 100644 --- a/BusinessLayer/DTOs/Location/LocationDto.cs +++ b/BusinessLayer/DTOs/Location/LocationDto.cs @@ -6,7 +6,7 @@ public record LocationDto public required string Country { get; set; } public required string City { get; set; } public required string Address { get; set; } - public string? ZipCode { get; set; } + public string? Zipcode { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } public DateTime? DeletedAt { get; set; } diff --git a/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs b/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs index 3e7f1537095f1a4b6d847e86c2586d4907fbec8d..c4220b200483c485d1834d7b69509b7553d7eb80 100644 --- a/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs +++ b/BusinessLayer/DTOs/Restaurant/RestaurantDetailDto.cs @@ -6,21 +6,18 @@ namespace BusinessLayer.DTOs.Restaurant { public record RestaurantDetailDto { - public record RestaurantDto - { - public Guid Id { get; set; } - public required LocationDto Location { get; set; } - public ReviewAggregateDTO? ReviewAggregate { get; set; } - public required List<UserDto> RestaurantMaintainers { get; set; } - public required string Name { get; set; } - public string? About { get; set; } - public string? Phone { get; set; } - public string? Email { get; set; } - public string? Web { get; set; } - public required string Category { get; set; } - public DateTime CreatedAt { get; set; } - public DateTime UpdatedAt { get; set; } - public DateTime? DeletedAt { get; set; } - } + public Guid Id { get; set; } + public required LocationDto Location { get; set; } + public ReviewAggregateDTO? ReviewAggregate { get; set; } + public required List<UserDto> RestaurantMaintainers { get; set; } + public required string Name { get; set; } + public string? About { get; set; } + public string? Phone { get; set; } + public string? Email { get; set; } + public string? Web { get; set; } + public required string Category { get; set; } + public DateTime CreatedAt { get; set; } + public DateTime UpdatedAt { get; set; } + public DateTime? DeletedAt { get; set; } } } \ No newline at end of file diff --git a/BusinessLayer/DTOs/Review/ReviewDTO.cs b/BusinessLayer/DTOs/Review/ReviewDTO.cs index de76c673b7d13ca4306713a0e77ac57d10512971..17eb0319691b58cce4d388ed1e25d251908b1392 100644 --- a/BusinessLayer/DTOs/Review/ReviewDTO.cs +++ b/BusinessLayer/DTOs/Review/ReviewDTO.cs @@ -9,6 +9,7 @@ namespace BusinessLayer.DTOs.Review public uint FoodRating { get; set; } public uint ServiceRating { get; set; } public uint EnvironmentRating { get; set; } + public Guid RestaurantId { get; set; } public DateTime CreatedAt { get; set; } public DateTime UpdatedAt { get; set; } public DateTime? DeletedAt { get; set; } diff --git a/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs b/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs index 93be3a4fd836f5fa69d5a2803bcc70f26783a3ad..d3ebd049163e446d1dd8e23b2004b9ea981fbb66 100644 --- a/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs +++ b/BusinessLayer/DTOs/ReviewAggregate/ReviewAggregateDTO.cs @@ -1,11 +1,8 @@ -using BusinessLayer.DTOs.Restaurant; - -namespace BusinessLayer.DTOs.ReviewAggregate +namespace BusinessLayer.DTOs.ReviewAggregate { public record ReviewAggregateDTO { public Guid RestaurantId { get; set; } - public RestaurantDto? Restaurant { get; set; } public uint FoodRating { get; set; } public uint ServiceRating { get; set; } public uint EnvironmentRating { get; set; } diff --git a/BusinessLayer/Services/LocationService/ILocationService.cs b/BusinessLayer/Services/LocationService/ILocationService.cs index c62b32379413620ed861b9d0a322a82cd41f636d..a15ab6f3636fd6256a80b9a3f7b519f60e02f710 100644 --- a/BusinessLayer/Services/LocationService/ILocationService.cs +++ b/BusinessLayer/Services/LocationService/ILocationService.cs @@ -15,6 +15,7 @@ namespace BusinessLayer.Services.LocationService public Task<LocationDto?> GetLocationAsync(Guid id); public Task<LocationDto?> UpdateLocationAsync( Guid id, - LocationUpdateDto restaurant); + LocationUpdateDto restaurant, + bool save = true); } } diff --git a/BusinessLayer/Services/LocationService/LocationService.cs b/BusinessLayer/Services/LocationService/LocationService.cs index 278b52672b9fdc9278c762ceac80526d26853a2b..f0227c9816fa5ecdbd1659cb26b52f741aec986a 100644 --- a/BusinessLayer/Services/LocationService/LocationService.cs +++ b/BusinessLayer/Services/LocationService/LocationService.cs @@ -22,8 +22,8 @@ namespace BusinessLayer.Services.LocationService return await _dbContext.Locations .Include(l => l.Restaurant) .Where(filter.ComposeFilterFunc(ids)) - .ApplyPagination(limit, offset) .ApplyOrdering(orderBy) + .ApplyPagination(limit, offset) .Select(l => l.Adapt<LocationDto>()).ToListAsync(); } @@ -41,11 +41,12 @@ namespace BusinessLayer.Services.LocationService public async Task<LocationDto?> UpdateLocationAsync( Guid id, - LocationUpdateDto data) + LocationUpdateDto data, + bool save = true) { var location = await _dbContext.Locations.FindAsync(id); - if (location is null) + if (location is null || location.DeletedAt is not null) { return null; } @@ -57,7 +58,7 @@ namespace BusinessLayer.Services.LocationService location.UpdatedAt = DateTime.UtcNow; _dbContext.Locations.Update(location); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return location.Adapt<LocationDto>(); } diff --git a/BusinessLayer/Services/RestaurantService/IRestaurantService.cs b/BusinessLayer/Services/RestaurantService/IRestaurantService.cs index 5c356b748200b518773e688670d1ced286386460..c37174c50ee52cb39ee5865ba57b6023bc850d0b 100644 --- a/BusinessLayer/Services/RestaurantService/IRestaurantService.cs +++ b/BusinessLayer/Services/RestaurantService/IRestaurantService.cs @@ -13,10 +13,13 @@ namespace BusinessLayer.Services.RestaurantService int offset = 0, Guid[]? ids = null); public Task<RestaurantDetailDto?> GetRestaurantAsync(Guid id); - public Task<RestaurantDetailDto?> CreateRestaurantAsync(RestaurantCreateDto restaurant); + public Task<RestaurantDetailDto?> CreateRestaurantAsync( + RestaurantCreateDto restaurant, + bool save = true); public Task<RestaurantDetailDto?> UpdateRestaurantAsync( Guid id, - RestaurantUpdateDto restaurant); + RestaurantUpdateDto restaurant, + bool save = true); public Task<bool> DeleteRestaurantAsync( Guid id, bool save = true); diff --git a/BusinessLayer/Services/RestaurantService/RestaurantService.cs b/BusinessLayer/Services/RestaurantService/RestaurantService.cs index 5f88f284598c7f0f876aefe812ce5ec2121ee2a1..40926cfca7e0007519d32420e7a6c5bc751f0f30 100644 --- a/BusinessLayer/Services/RestaurantService/RestaurantService.cs +++ b/BusinessLayer/Services/RestaurantService/RestaurantService.cs @@ -23,9 +23,10 @@ namespace BusinessLayer.Services.RestaurantService return await _dbContext.Restaurants .Include(r => r.ReviewAggregate) .Where(filter.ComposeFilterFunc(ids)) - .ApplyPagination(limit, offset) .ApplyOrdering(orderBy) - .Select(r => r.Adapt<RestaurantDto>()).ToListAsync(); + .ApplyPagination(limit, offset) + .Select(r => r.Adapt<RestaurantDto>()) + .ToListAsync(); } public async Task<RestaurantDetailDto?> GetRestaurantAsync(Guid id) @@ -35,9 +36,10 @@ namespace BusinessLayer.Services.RestaurantService .Include(r => r.ReviewAggregate) .Include(r => r.RestaurantMaintainers) .Include(r => r.Location) - .SingleOrDefaultAsync(r => r.Id == id); + .SingleOrDefaultAsync(r => r.Id == id + && r.DeletedAt == null); - if (restaurant is null || restaurant.DeletedAt is not null) + if (restaurant is null) { return null; } @@ -45,7 +47,8 @@ namespace BusinessLayer.Services.RestaurantService return restaurant.Adapt<RestaurantDetailDto>(); } - public async Task<RestaurantDetailDto?> CreateRestaurantAsync(RestaurantCreateDto data) + public async Task<RestaurantDetailDto?> CreateRestaurantAsync( + RestaurantCreateDto data, bool save = true) { var maintainer = await _dbContext.Users.FindAsync(data.MaintainerId); @@ -78,12 +81,13 @@ namespace BusinessLayer.Services.RestaurantService await _dbContext.Restaurants.AddAsync(restaurant); maintainer.MaintainedRestaurants.Add(restaurant); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return restaurant.Adapt<RestaurantDetailDto>(); } - public async Task<RestaurantDetailDto?> UpdateRestaurantAsync(Guid id, RestaurantUpdateDto data) + public async Task<RestaurantDetailDto?> UpdateRestaurantAsync( + Guid id, RestaurantUpdateDto data, bool save = true) { var restaurant = await _dbContext.Restaurants.FindAsync(id); @@ -101,7 +105,7 @@ namespace BusinessLayer.Services.RestaurantService restaurant.UpdatedAt = DateTime.UtcNow; _dbContext.Restaurants.Update(restaurant); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return restaurant.Adapt<RestaurantDetailDto>(); } @@ -131,7 +135,7 @@ namespace BusinessLayer.Services.RestaurantService _dbContext.Restaurants.Update(restaurant); _dbContext.Locations.Update(location); - await _dbContext.SaveChangesAsync(save); + await SaveAsync(save); return true; } diff --git a/BusinessLayer/Services/ReviewAggregateResultService/IReviewAggregateResultService.cs b/BusinessLayer/Services/ReviewAggregateResultService/IReviewAggregateResultService.cs index 892d4d9781c63b24f7efb04a38120bbb1d040341..564803c8cc4dbfd3534c447c5897f2cf14e31f44 100644 --- a/BusinessLayer/Services/ReviewAggregateResultService/IReviewAggregateResultService.cs +++ b/BusinessLayer/Services/ReviewAggregateResultService/IReviewAggregateResultService.cs @@ -4,7 +4,7 @@ namespace BusinessLayer.Services.ReviewAggregateService { public interface IReviewAggregateResultService : IBaseService { - public Task<bool> DoesAggregateExist(params Guid[] ids); + public Task<bool> DoesAggregateExistAsync(params Guid[] ids); public Task<List<ReviewAggregateDTO>> GetAggregatesAsync( string orderBy = "", diff --git a/BusinessLayer/Services/ReviewAggregateResultService/ReviewAggregateResultService.cs b/BusinessLayer/Services/ReviewAggregateResultService/ReviewAggregateResultService.cs index 134c17fb4c625f2f5a4bce1e843c1a0d92a25a86..28cb3c82450b5c31727ea6a136b6f63292207b32 100644 --- a/BusinessLayer/Services/ReviewAggregateResultService/ReviewAggregateResultService.cs +++ b/BusinessLayer/Services/ReviewAggregateResultService/ReviewAggregateResultService.cs @@ -14,7 +14,7 @@ namespace BusinessLayer.Services.ReviewAggregateService _dbContext = dbContext; } - public async Task<bool> DoesAggregateExist(params Guid[] ids) + public async Task<bool> DoesAggregateExistAsync(params Guid[] ids) { return await _dbContext.ReviewAggregateResults.AnyAsync(r => ids.Contains(r.RestaurantId)); } diff --git a/BusinessLayer/Services/ReviewService/ReviewService.cs b/BusinessLayer/Services/ReviewService/ReviewService.cs index 1334ed57a22c8b5c4c0e3d0ced4f2fc6ca558ec4..ff27b8590d9a4b1e7408262c658f1dec4b754ef2 100644 --- a/BusinessLayer/Services/ReviewService/ReviewService.cs +++ b/BusinessLayer/Services/ReviewService/ReviewService.cs @@ -50,7 +50,7 @@ namespace BusinessLayer.Services.ReviewService { var review = await _dbContext.Reviews.FindAsync(id); - if (review is null) + if (review is null || review.DeletedAt is not null) { return false; } diff --git a/BusinessLayer/Services/UserService/IUserService.cs b/BusinessLayer/Services/UserService/IUserService.cs index 1a8b49c6562e32e858ddf2775dfd3d89e46f9757..7e3c32d9d95395bf49725fe0fe23e3bf9a478017 100644 --- a/BusinessLayer/Services/UserService/IUserService.cs +++ b/BusinessLayer/Services/UserService/IUserService.cs @@ -13,10 +13,13 @@ namespace BusinessLayer.Services.UserService int offset = 0, Guid[]? ids = null); public Task<UserDetailDto?> GetUserAsync(Guid id); - public Task<UserDetailDto> CreateUserAsync(UserCreateDto restaurant); + public Task<UserDetailDto?> CreateUserAsync( + UserCreateDto restaurant, + bool save = true); public Task<UserDetailDto?> UpdateUserAsync( Guid id, - UserUpdateDto restaurant); + UserUpdateDto restaurant, + bool save = true); public Task<bool> DeleteUserAsync( Guid id, bool save = true); diff --git a/BusinessLayer/Services/UserService/UserService.cs b/BusinessLayer/Services/UserService/UserService.cs index 95da007ed699c131f3a2a641368c897ad2457ae9..d50128fd456aec73fba7b07f4f0330394d46a84b 100644 --- a/BusinessLayer/Services/UserService/UserService.cs +++ b/BusinessLayer/Services/UserService/UserService.cs @@ -22,8 +22,8 @@ namespace BusinessLayer.Services.UserService { return await _dbContext.Users .Where(filter.ComposeFilterFunc(ids)) - .ApplyPagination(limit, offset) .ApplyOrdering(orderBy) + .ApplyPagination(limit, offset) .Select(u => u.Adapt<UserDto>()).ToListAsync(); } @@ -31,9 +31,10 @@ namespace BusinessLayer.Services.UserService { var user = await _dbContext.Users .Include(u => u.MaintainedRestaurants) - .SingleOrDefaultAsync(u => u.Id == id); + .SingleOrDefaultAsync(u => u.Id == id + && u.DeletedAt == null); - if (user is null || user.DeletedAt is not null) + if (user is null) { return null; } @@ -41,7 +42,7 @@ namespace BusinessLayer.Services.UserService return user.Adapt<UserDetailDto>(); } - public async Task<UserDetailDto> CreateUserAsync(UserCreateDto data) + public async Task<UserDetailDto?> CreateUserAsync(UserCreateDto data, bool save = true) { var user = new User { @@ -50,15 +51,17 @@ namespace BusinessLayer.Services.UserService Email = data.Email, MaintainedRestaurants = [], }; + await _dbContext.Users.AddAsync(user); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return user.Adapt<UserDetailDto>(); } public async Task<UserDetailDto?> UpdateUserAsync( Guid id, - UserUpdateDto data) + UserUpdateDto data, + bool save = true) { var user = await _dbContext.Users.FindAsync(id); @@ -72,7 +75,7 @@ namespace BusinessLayer.Services.UserService user.UpdatedAt = DateTime.UtcNow; _dbContext.Users.Update(user); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return user.Adapt<UserDetailDto>(); } @@ -83,7 +86,7 @@ namespace BusinessLayer.Services.UserService { var user = await _dbContext.Users.FindAsync(id); - if (user is null) + if (user is null || user.DeletedAt is not null) { return false; } @@ -92,7 +95,7 @@ namespace BusinessLayer.Services.UserService user.DeletedAt = DateTime.UtcNow; _dbContext.Users.Update(user); - await _dbContext.SaveChangesAsync(); + await SaveAsync(save); return true; } diff --git a/BusinessLayer/Utils/Ordering/OrderingManager.cs b/BusinessLayer/Utils/Ordering/OrderingManager.cs index 96c0a02cee09a264daa8a6ef24c9621b4212c2d4..4c422961c13721d6bd62265abeab993f89ff1387 100644 --- a/BusinessLayer/Utils/Ordering/OrderingManager.cs +++ b/BusinessLayer/Utils/Ordering/OrderingManager.cs @@ -32,8 +32,6 @@ namespace BusinessLayer.Utils.Ordering { UserOrdering.Name => query.OrderBy(c => c.Name), UserOrdering.NameDesc => query.OrderByDescending(c => c.Name), - UserOrdering.Email => query.OrderBy(c => c.Email), - UserOrdering.EmailDesc => query.OrderByDescending(c => c.Email), _ => query.OrderByDescending(c => c.CreatedAt) }; } diff --git a/BusinessLayer/Utils/Ordering/UserOrdering.cs b/BusinessLayer/Utils/Ordering/UserOrdering.cs index d49c3703948bd3bd744660065dc8a5ce79967bfa..46c7a5ccfab0103b0f9756d3caf3b1ea26cbb6bf 100644 --- a/BusinessLayer/Utils/Ordering/UserOrdering.cs +++ b/BusinessLayer/Utils/Ordering/UserOrdering.cs @@ -4,8 +4,6 @@ namespace BusinessLayer.Utils.Ordering { Name, NameDesc, - Email, - EmailDesc, CreatedAtDesc } } diff --git a/DAL/Constants/SeedingValues.cs b/DAL/Constants/SeedingValues.cs index 5f9f5a9514ba71bc2d726bc7ad1d67f6857c0ed0..f73ee97054bec3a14881a4bbaaf6bae2f339b6f5 100644 --- a/DAL/Constants/SeedingValues.cs +++ b/DAL/Constants/SeedingValues.cs @@ -33,9 +33,5 @@ // Event Comment IDs public static readonly Guid EventComment1Id = new("88a4b4d4-b74d-40c5-823e-e708f15664d3"); public static readonly Guid EventComment2Id = new("e0e27f5b-bd6f-47d9-b5fa-5b7e7e77d462"); - - // Location IDs - public static readonly Guid Location1Id = new("879b11c9-cf58-4fb4-bb31-08a930add99c"); - public static readonly Guid Location2Id = new("2128e797-4ba9-443b-971a-62dbcca081e0"); } } diff --git a/DAL/Data/RestaurantDBContext.cs b/DAL/Data/RestaurantDBContext.cs index 1b380f37c940f637b155146245aa3087a223e370..520a700818e3e049793b793ed79d3fac00587724 100644 --- a/DAL/Data/RestaurantDBContext.cs +++ b/DAL/Data/RestaurantDBContext.cs @@ -5,17 +5,17 @@ namespace DAL.Data { public class RestaurantDBContext : DbContext { - public DbSet<User> Users { get; set; } - public DbSet<Review> Reviews { get; set; } - public DbSet<ReviewComment> ReviewComments { get; set; } - public DbSet<ReviewAggregateResult> ReviewAggregateResults { get; set; } - public DbSet<Event> Events { get; set; } - public DbSet<EventComment> EventComments { get; set; } - public DbSet<EventParticipant> EventParticipants { get; set; } + public virtual DbSet<User> Users { get; set; } + public virtual DbSet<Review> Reviews { get; set; } + public virtual DbSet<ReviewComment> ReviewComments { get; set; } + public virtual DbSet<ReviewAggregateResult> ReviewAggregateResults { get; set; } + public virtual DbSet<Event> Events { get; set; } + public virtual DbSet<EventComment> EventComments { get; set; } + public virtual DbSet<EventParticipant> EventParticipants { get; set; } - public DbSet<Restaurant> Restaurants { get; set; } + public virtual DbSet<Restaurant> Restaurants { get; set; } - public DbSet<Location> Locations { get; set; } + public virtual DbSet<Location> Locations { get; set; } public RestaurantDBContext(DbContextOptions<RestaurantDBContext> options) : base(options) { } diff --git a/TestUtilities/Constants/FakeSeedingValues.cs b/TestUtilities/Constants/FakeSeedingValues.cs new file mode 100644 index 0000000000000000000000000000000000000000..48d7183322b3dd2d62338d0b7dd39b06ad100b2c --- /dev/null +++ b/TestUtilities/Constants/FakeSeedingValues.cs @@ -0,0 +1,40 @@ +namespace TestUtilities.Constants +{ + public class FakeSeedingValues + { + // User IDs + public static readonly Guid User1Id = new("afde48a8-99e3-423e-a48d-9e4e6a3d823a"); + public static readonly Guid User2Id = new("32669bac-a1bd-4e9d-9580-ee4a7764cda3"); + public static readonly Guid User3Id = new("99499984-8947-4b85-bea2-9cfd487c55d3"); + public static readonly Guid DeletedUserId = new("bd2d0401-6020-4988-b683-7927c1a5c66d"); + + // Review IDs + public static readonly Guid Review1Id = new("32669bac-a1bd-4e9d-9580-ee4a7764cda3"); + public static readonly Guid Review2Id = new("e8f210bd-5666-40c7-bc61-4d8ef17c5191"); + public static readonly Guid Review3Id = new("d748b6c9-8d9b-4809-b425-766cfc705b01"); + public static readonly Guid DeletedReviewId = new("bd2d0401-0000-4988-b683-7927c1a5c66d"); + + // Review Comment IDs + public static readonly Guid ReviewComment1Id = new("af16972e-d611-4c1c-8ce3-a93d667c1b9a"); + public static readonly Guid ReviewComment2Id = new("9ddbe84f-f2f4-4532-bca7-13152905c3b1"); + public static readonly Guid ReviewComment3Id = new("b8046e83-94c9-4b48-8035-28a5873e1526"); + public static readonly Guid ReviewComment4Id = new("652ba3f0-ad48-4e71-a791-f16b5707003d"); + + // Restaurant IDs + public static readonly Guid Restaurant1Id = new("104fdc28-a328-4f7b-85fe-81550cf1e247"); + public static readonly Guid Restaurant2Id = new("e9921304-5657-40b2-9bb6-28ca03d3a45e"); + public static readonly Guid DeletedRestaurantId = new("1dfdd405-338b-47f4-84a6-466d9f79de5b"); + + // Event IDs + public static readonly Guid Event1Id = new("10ba7f93-895f-4be5-987e-45e6d55bda3f"); + public static readonly Guid Event2Id = new("c68be8ab-fc64-456a-a5fb-f97f2a96e2d1"); + + // Event Participant IDs + public static readonly Guid EventParticipant1Id = new("7c673b56-473e-4fd4-b49b-f69e8fd9adbb"); + public static readonly Guid EventParticipant2Id = new("6f995134-cbcf-42d2-9ec9-e028d85726b9"); + + // Event Comment IDs + public static readonly Guid EventComment1Id = new("88a4b4d4-b74d-40c5-823e-e708f15664d3"); + public static readonly Guid EventComment2Id = new("e0e27f5b-bd6f-47d9-b5fa-5b7e7e77d462"); + } +} diff --git a/TestUtilities/FakeData/FakeDataInitializer.cs b/TestUtilities/FakeData/FakeDataInitializer.cs index 201bca8407a7911e1553c7d446c10b473b65faf9..56c4bc2a565bf4bb4aa3093e6734095c7568b133 100644 --- a/TestUtilities/FakeData/FakeDataInitializer.cs +++ b/TestUtilities/FakeData/FakeDataInitializer.cs @@ -1,4 +1,4 @@ -using DAL.Constants; +using TestUtilities.Constants; using DAL.Models; using DAL.Enums; using DAL.Data; @@ -21,7 +21,7 @@ namespace TestUtilities.FakeData var reviewAggregates = reviews .GroupBy(r => r.RestaurantId) - .Select(group => new ReviewAggregate + .Select(group => new ReviewAggregateResult { RestaurantId = group.Key, FoodRating = (uint)Math.Round(group.Average(item => item.FoodRating)), @@ -29,7 +29,8 @@ namespace TestUtilities.FakeData EnvironmentRating = (uint)Math.Round(group.Average(item => item.EnvironmentRating)) }); - context.ReviewAggregate.AddRange(reviewAggregates); + context.ReviewAggregateResults.AddRange(reviewAggregates); + context.SaveChanges(); } private static List<User> PrepareUserModels() { @@ -37,7 +38,7 @@ namespace TestUtilities.FakeData [ new User { - Id = SeedingValues.User1Id, + Id = FakeSeedingValues.User1Id, Name = "Vit23", Email = "Vit23@gmail.com", CreatedAt = new DateTime(2024, 10, 01, 08, 20, 05), @@ -45,7 +46,7 @@ namespace TestUtilities.FakeData }, new User { - Id = SeedingValues.User2Id, + Id = FakeSeedingValues.User2Id, Name = "Erik512", Email = "Erikuss.Cool@gmail.com", CreatedAt = new DateTime(2024, 10, 01, 04, 20, 00), @@ -53,11 +54,20 @@ namespace TestUtilities.FakeData }, new User { - Id = SeedingValues.User3Id, + Id = FakeSeedingValues.User3Id, Name = "Jakub23423", Email = "Jaqub@azet.sk", CreatedAt = new DateTime(2024, 10, 05, 14, 23, 21), UpdatedAt = new DateTime(2024, 10, 05, 14, 23, 21) + }, + new User + { + Id = FakeSeedingValues.DeletedUserId, + Name = "Pneumonoultramicroscopicsilicovolcanoconiosis", + Email = "Pneumonoultramicroscopicsilicovolcanoconiosis32@gmail.com", + CreatedAt = new DateTime(2024, 10, 08, 08, 20, 05), + UpdatedAt = new DateTime(2024, 10, 10, 03, 00, 00), + DeletedAt = new DateTime(2024, 10, 10, 03, 00, 00), } ]; } @@ -68,9 +78,9 @@ namespace TestUtilities.FakeData [ new Review { - Id = SeedingValues.Review1Id, - PosterId = SeedingValues.User1Id, - RestaurantId = SeedingValues.Restaurant1Id, + Id = FakeSeedingValues.Review1Id, + PosterId = FakeSeedingValues.User1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, Content = "The food was pretty good, but there were a lot of people and I could barely hear my friend. Due to this, the service was quite busy and it took them a while to get me food.", FoodRating = 8, EnvironmentRating = 3, @@ -82,9 +92,9 @@ namespace TestUtilities.FakeData }, new Review { - Id = SeedingValues.Review2Id, - PosterId = SeedingValues.User3Id, - RestaurantId = SeedingValues.Restaurant1Id, + Id = FakeSeedingValues.Review2Id, + PosterId = FakeSeedingValues.User3Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, Content = "Good restaurant, very enjoy. Environment not so good - toilet door stuck. Send help.", FoodRating = 10, EnvironmentRating = 1, @@ -97,9 +107,9 @@ namespace TestUtilities.FakeData }, new Review { - Id = SeedingValues.Review3Id, - PosterId = SeedingValues.User3Id, - RestaurantId = SeedingValues.Restaurant2Id, + Id = FakeSeedingValues.Review3Id, + PosterId = FakeSeedingValues.User3Id, + RestaurantId = FakeSeedingValues.Restaurant2Id, Content = "The pizza is great, burned my tongue with how excited I was to eat. Service was decent. The environment was amazing, too!", FoodRating = 10, EnvironmentRating = 8, @@ -108,6 +118,19 @@ namespace TestUtilities.FakeData LeftTip = true, CreatedAt = new DateTime(2024, 10, 10, 16, 41, 2), UpdatedAt = new DateTime(2024, 10, 10, 16, 41, 2) + }, + new Review + { + Id = FakeSeedingValues.DeletedReviewId, + PosterId = FakeSeedingValues.User1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, + Content = "This is a deleted review.", + FoodRating = 7, + ServiceRating = 7, + EnvironmentRating = 7, + CreatedAt = DateTime.UtcNow, + UpdatedAt = DateTime.UtcNow, + DeletedAt = DateTime.UtcNow } ]; } @@ -118,38 +141,38 @@ namespace TestUtilities.FakeData [ new ReviewComment { - Id = SeedingValues.ReviewComment1Id, - PosterId = SeedingValues.User2Id, - ReviewId = SeedingValues.Review1Id, + Id = FakeSeedingValues.ReviewComment1Id, + PosterId = FakeSeedingValues.User2Id, + ReviewId = FakeSeedingValues.Review1Id, Content = "Hello, I am the owner of this restaurant. I don't think it is right for you to rate us badly because we get a lot of customers.", CreatedAt = new DateTime(2024, 10, 05, 23, 14, 5), UpdatedAt = new DateTime(2024, 10, 05, 23, 14, 5) }, new ReviewComment { - Id = SeedingValues.ReviewComment2Id, - PosterId = SeedingValues.User1Id, - ReviewId = SeedingValues.Review1Id, - ParentCommentId = SeedingValues.ReviewComment1Id, + Id = FakeSeedingValues.ReviewComment2Id, + PosterId = FakeSeedingValues.User1Id, + ReviewId = FakeSeedingValues.Review1Id, + ParentCommentId = FakeSeedingValues.ReviewComment1Id, Content = "OK.", CreatedAt = new DateTime(2024, 10, 06, 23, 18, 1), UpdatedAt = new DateTime(2024, 10, 06, 23, 18, 1) }, new ReviewComment { - Id = SeedingValues.ReviewComment3Id, - PosterId = SeedingValues.User2Id, - ReviewId = SeedingValues.Review2Id, + Id = FakeSeedingValues.ReviewComment3Id, + PosterId = FakeSeedingValues.User2Id, + ReviewId = FakeSeedingValues.Review2Id, Content = "Oh my god! Are you still in there?!", CreatedAt = new DateTime(2024, 10, 06, 10, 5, 6), UpdatedAt = new DateTime(2024, 10, 06, 10, 5, 6) }, new ReviewComment { - Id = SeedingValues.ReviewComment4Id, - PosterId = SeedingValues.User3Id, - ReviewId = SeedingValues.Review2Id, - ParentCommentId = SeedingValues.ReviewComment3Id, + Id = FakeSeedingValues.ReviewComment4Id, + PosterId = FakeSeedingValues.User3Id, + ReviewId = FakeSeedingValues.Review2Id, + ParentCommentId = FakeSeedingValues.ReviewComment3Id, Content = "No, no, it's all good now. Turns out I just locked it.", CreatedAt = new DateTime(2024, 10, 06, 11, 3, 0), UpdatedAt = new DateTime(2024, 10, 06, 11, 3, 0), @@ -164,9 +187,9 @@ namespace TestUtilities.FakeData { new Event { - Id = SeedingValues.Event1Id, + Id = FakeSeedingValues.Event1Id, Title = "Exclusive Dinner Event", - RestaurantId = SeedingValues.Restaurant1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, Date = new DateTime(2024, 10, 30, 12, 20, 23), Content = "Join us for an exclusive dinner with gourmet cuisine.", CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23), @@ -174,9 +197,9 @@ namespace TestUtilities.FakeData }, new Event { - Id = SeedingValues.Event2Id, + Id = FakeSeedingValues.Event2Id, Title = "Wine Tasting Evening", - RestaurantId = SeedingValues.Restaurant1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, Date = new DateTime(2024, 10, 27, 10, 23, 23), Content = "An evening of exquisite wine tasting with fine cheeses.", CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23), @@ -191,32 +214,32 @@ namespace TestUtilities.FakeData { new EventParticipant { - UserId = SeedingValues.User3Id, - EventId = SeedingValues.Event1Id, + UserId = FakeSeedingValues.User3Id, + EventId = FakeSeedingValues.Event1Id, Attendance = ParticipantType.Creator, CreatedAt = new DateTime(2024, 10, 20, 12, 20, 23), UpdatedAt = new DateTime(2024, 10, 20, 12, 20, 23) }, new EventParticipant { - UserId = SeedingValues.User1Id, - EventId = SeedingValues.Event1Id, + UserId = FakeSeedingValues.User1Id, + EventId = FakeSeedingValues.Event1Id, Attendance = ParticipantType.Attending, CreatedAt = new DateTime(2024, 10, 21, 10, 23, 23), UpdatedAt = new DateTime(2024, 10, 21, 10, 23, 23) }, new EventParticipant { - UserId = SeedingValues.User2Id, - EventId = SeedingValues.Event1Id, + UserId = FakeSeedingValues.User2Id, + EventId = FakeSeedingValues.Event1Id, Attendance = ParticipantType.Tentative, CreatedAt = new DateTime(2024, 10, 20, 15, 20, 23), UpdatedAt = new DateTime(2024, 10, 20, 15, 20, 23) }, new EventParticipant { - UserId = SeedingValues.User1Id, - EventId = SeedingValues.Event2Id, + UserId = FakeSeedingValues.User1Id, + EventId = FakeSeedingValues.Event2Id, Attendance = ParticipantType.Attending, CreatedAt = new DateTime(2024, 10, 12, 10, 23, 23), UpdatedAt = new DateTime(2024, 10, 12, 10, 23, 23) @@ -230,19 +253,19 @@ namespace TestUtilities.FakeData { new EventComment { - Id = SeedingValues.EventComment1Id, - PosterId = SeedingValues.User2Id, - EventId = SeedingValues.Event1Id, + Id = FakeSeedingValues.EventComment1Id, + PosterId = FakeSeedingValues.User2Id, + EventId = FakeSeedingValues.Event1Id, Content = "Looking forward to this event!", CreatedAt = new DateTime(2024, 10, 21, 18, 23, 23), UpdatedAt = new DateTime(2024, 10, 21, 18, 23, 23) }, new EventComment { - Id = SeedingValues.EventComment2Id, - PosterId = SeedingValues.User1Id, - EventId = SeedingValues.Event1Id, - ParentCommentId = SeedingValues.EventComment1Id, + Id = FakeSeedingValues.EventComment2Id, + PosterId = FakeSeedingValues.User1Id, + EventId = FakeSeedingValues.Event1Id, + ParentCommentId = FakeSeedingValues.EventComment1Id, Content = "Me too! It sounds like a great night.", CreatedAt = new DateTime(2024, 10, 21, 19, 26, 23), UpdatedAt = new DateTime(2024, 10, 21, 19, 26, 23) @@ -254,7 +277,7 @@ namespace TestUtilities.FakeData [ new Restaurant { - Id = SeedingValues.Restaurant1Id, + Id = FakeSeedingValues.Restaurant1Id, Name = "U DĹ™eváka Beer&Grill", Category = "pub", About = "V tomhle jednoduchĂ©m, ale ĂştulnĂ©m podniku se zahrádkou je k dostánĂ poctivĂ© jĂdlo i pivo nÄ›kolika pivovarĹŻ.", @@ -266,7 +289,7 @@ namespace TestUtilities.FakeData }, new Restaurant { - Id = SeedingValues.Restaurant2Id, + Id = FakeSeedingValues.Restaurant2Id, Name = "Doe Boy Brno", Category = "pizza", About = "Authentic Neapolitan Pizza // The taste of Naples in Brno", @@ -275,6 +298,16 @@ namespace TestUtilities.FakeData Web = "https://facebook.com/pages/category/Pizza-Place/Doe-Boy-Brno-101177877951369/", CreatedAt = new DateTime(2024, 10, 01, 12, 1, 0), UpdatedAt = new DateTime(2024, 10, 01, 12, 1, 0), + }, + new Restaurant + { + Id = FakeSeedingValues.DeletedRestaurantId, + Name = "DeletedTastes", + Category = "pizza", + About = "So tasty we had to delete it.", + CreatedAt = new DateTime(2024, 10, 05, 12, 1, 0), + UpdatedAt = new DateTime(2024, 10, 08, 12, 1, 0), + DeletedAt = new DateTime(2024, 10, 08, 12, 1, 0), } ]; @@ -282,7 +315,7 @@ namespace TestUtilities.FakeData [ new Location { - RestaurantId = SeedingValues.Restaurant1Id, + RestaurantId = FakeSeedingValues.Restaurant1Id, Country = "Czech Republic", City = "Brno", Address = "DĹ™evaĹ™ská 806/22", @@ -292,13 +325,24 @@ namespace TestUtilities.FakeData }, new Location { - RestaurantId = SeedingValues.Restaurant2Id, - Country = "Czech Republic", - City = "Brno", + RestaurantId = FakeSeedingValues.Restaurant2Id, + Country = "Fake Republic", + City = "Bryes", Address = "Ĺ tefánikova 39", - Zipcode = "60200", + Zipcode = "60201", CreatedAt = new DateTime(2024, 10, 01, 12, 1, 0), UpdatedAt = new DateTime(2024, 10, 01, 12, 1, 0) + }, + new Location + { + RestaurantId = FakeSeedingValues.DeletedRestaurantId, + Country = "Deleted Republic", + City = "Brdeleted", + Address = "Street 39", + Zipcode = "60290", + CreatedAt = new DateTime(2024, 10, 05, 12, 1, 0), + UpdatedAt = new DateTime(2024, 10, 07, 02, 30, 0), + DeletedAt = new DateTime(2024, 10, 07, 02, 30, 0) } ]; } diff --git a/TestUtilities/Mocks/MockedDbContext.cs b/TestUtilities/Mocks/MockedDbContext.cs index 56ddac6b3b4459ed0a69ce922be0267eff1505ad..14bc67ca0016698b08d3732cd525ea9efbcb6cc5 100644 --- a/TestUtilities/Mocks/MockedDbContext.cs +++ b/TestUtilities/Mocks/MockedDbContext.cs @@ -11,7 +11,7 @@ namespace TestUtilities.Mocks public static DbContextOptions<RestaurantDBContext> CreateInMemoryContextOptions() { return new DbContextOptionsBuilder<RestaurantDBContext>() - .UseInMemoryDatabase(DBName).Options; + .UseInMemoryDatabase(Guid.NewGuid().ToString()).Options; } public static RestaurantDBContext CreateContext(DbContextOptions<RestaurantDBContext> options) diff --git a/TestUtilities/TestUtilities.csproj b/TestUtilities/TestUtilities.csproj index d672305f76d4daa8c616dc694c5e30d9a084a1d3..947d4fb506de822cf9cc2169f797bc7fdac89e21 100644 --- a/TestUtilities/TestUtilities.csproj +++ b/TestUtilities/TestUtilities.csproj @@ -7,8 +7,8 @@ </PropertyGroup> <ItemGroup> + <PackageReference Include="EntityFrameworkCore.Testing.NSubstitute" Version="8.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" /> - <PackageReference Include="NSubstitute" Version="5.3.0" /> </ItemGroup> <ItemGroup> diff --git a/pv179-project.sln b/pv179-project.sln index 6475a2f196024eead565e820b6cd220d3eacd5da..fb9b03f362eee76411b522aa59b361f000a1b371 100644 --- a/pv179-project.sln +++ b/pv179-project.sln @@ -7,11 +7,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Api", "Api\Api.csproj", "{3 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DAL", "DAL\DAL.csproj", "{5BA37FEF-E2CC-43A8-8D69-FD40FB2B9454}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLayer", "BusinessLayer\BusinessLayer.csproj", "{539D3A8E-5CD3-4236-81B0-C36537BC6B68}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BusinessLayer", "BusinessLayer\BusinessLayer.csproj", "{539D3A8E-5CD3-4236-81B0-C36537BC6B68}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MVC", "MVC\MVC.csproj", "{11AD9763-446E-4FD8-AC2D-BF092CAE16DE}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MVC", "MVC\MVC.csproj", "{11AD9763-446E-4FD8-AC2D-BF092CAE16DE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BusinessLayer.Tests", "BusinessLayer.Tests\BusinessLayer.Tests.csproj", "{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BusinessLayer.Tests", "BusinessLayer.Tests\BusinessLayer.Tests.csproj", "{B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "TestUtilities\TestUtilities.csproj", "{7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -39,6 +41,10 @@ Global {B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Debug|Any CPU.Build.0 = Debug|Any CPU {B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Release|Any CPU.ActiveCfg = Release|Any CPU {B244DC7E-77CF-4B9A-B382-BC8E1E4B057C}.Release|Any CPU.Build.0 = Release|Any CPU + {7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7F02D143-33B1-4A83-BE5E-8AE192DA6A8D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE