test: repair test suite broken by feature drift (red -> 81 passing)
CI/CD / CI · API (dotnet build + test) (pull_request) Successful in 43s
CI/CD / CI · Admin API (dotnet build) (pull_request) Successful in 44s
CI/CD / CI · Dashboard (tsc) (pull_request) Successful in 1m7s
CI/CD / CI · Admin Web (tsc) (pull_request) Successful in 36s
CI/CD / CI · Website (tsc) (pull_request) Successful in 45s
CI/CD / CI · Koja (tsc) (pull_request) Successful in 51s
CI/CD / Deploy · all services (pull_request) Has been skipped
CI/CD / CI · API (dotnet build + test) (pull_request) Successful in 43s
CI/CD / CI · Admin API (dotnet build) (pull_request) Successful in 44s
CI/CD / CI · Dashboard (tsc) (pull_request) Successful in 1m7s
CI/CD / CI · Admin Web (tsc) (pull_request) Successful in 36s
CI/CD / CI · Website (tsc) (pull_request) Successful in 45s
CI/CD / CI · Koja (tsc) (pull_request) Successful in 51s
CI/CD / Deploy · all services (pull_request) Has been skipped
The test project no longer compiled: recent feature commits changed interfaces and DTOs without updating the test doubles/call sites, so the whole suite (and therefore CI) was failing to build. - NoOpInventoryService: add IInventoryService.GetPurchasesSummaryAsync and the new string? userId param on AdjustAsync. - NoOpLoyaltyService: add ILoyaltyService.RedeemOnOrderAsync. - NoOpOrderNotificationService: add NotifyCallWaiterAsync. - New NoOpAbuseProtectionService and NoOpMediaStorageService test doubles. - QrMenuTests: ReviewService/PublicService gained IAbuseProtectionService + IHttpContextAccessor (and ReviewService an IMediaStorageService); wire the new no-op doubles + a real HttpContextAccessor. - PrintingTests: OrderDto gained a DisplayNumber int between CreatedAt and Items; pass it. - DiscoverFilterTests: add missing `using Xunit;` and the new openNow arg on DiscoverFilterParams.FromQuery. Result: dotnet test -> Passed: 81, Failed: 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
using Meezi.API.Services;
|
using Meezi.API.Services;
|
||||||
using Meezi.Core.Discover;
|
using Meezi.Core.Discover;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace Meezi.API.Tests;
|
namespace Meezi.API.Tests;
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ public class DiscoverFilterTests
|
|||||||
noise: "quiet",
|
noise: "quiet",
|
||||||
priceTier: "mid",
|
priceTier: "mid",
|
||||||
size: null,
|
size: null,
|
||||||
requireProfile: true);
|
requireProfile: true,
|
||||||
|
openNow: false);
|
||||||
Assert.Equal("تهران", f.City);
|
Assert.Equal("تهران", f.City);
|
||||||
Assert.Equal(4, f.MinRating);
|
Assert.Equal(4, f.MinRating);
|
||||||
Assert.Contains("modern", f.Themes!);
|
Assert.Contains("modern", f.Themes!);
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using Meezi.API.Security;
|
||||||
|
|
||||||
|
namespace Meezi.API.Tests;
|
||||||
|
|
||||||
|
/// <summary>Test double that allows every action and has no captcha configured.</summary>
|
||||||
|
internal sealed class NoOpAbuseProtectionService : IAbuseProtectionService
|
||||||
|
{
|
||||||
|
public bool IsCaptchaConfigured => false;
|
||||||
|
public string? CaptchaSiteKey => null;
|
||||||
|
|
||||||
|
public Task<(bool Allowed, string? ErrorCode, string? Message)> CheckAuthOtpByIpAsync(
|
||||||
|
string clientIp, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<(bool, string?, string?)>((true, null, null));
|
||||||
|
|
||||||
|
public Task<(bool Allowed, string? ErrorCode, string? Message)> CheckGuestOrderAsync(
|
||||||
|
string cafeId, string clientIp, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<(bool, string?, string?)>((true, null, null));
|
||||||
|
|
||||||
|
public Task<(bool Allowed, string? ErrorCode, string? Message)> CheckPublicWriteByIpAsync(
|
||||||
|
string clientIp, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<(bool, string?, string?)>((true, null, null));
|
||||||
|
|
||||||
|
public Task<(bool Ok, string? ErrorCode, string? Message)> VerifyCaptchaAsync(
|
||||||
|
string? captchaToken, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<(bool, string?, string?)>((true, null, null));
|
||||||
|
}
|
||||||
@@ -16,9 +16,17 @@ internal sealed class NoOpInventoryService : IInventoryService
|
|||||||
public Task<IngredientDto?> UpdateAsync(string cafeId, string ingredientId, UpdateIngredientRequest request, CancellationToken ct = default) =>
|
public Task<IngredientDto?> UpdateAsync(string cafeId, string ingredientId, UpdateIngredientRequest request, CancellationToken ct = default) =>
|
||||||
Task.FromResult<IngredientDto?>(null);
|
Task.FromResult<IngredientDto?>(null);
|
||||||
|
|
||||||
public Task<IngredientDto?> AdjustAsync(string cafeId, string ingredientId, AdjustStockRequest request, CancellationToken ct = default) =>
|
public Task<IngredientDto?> AdjustAsync(string cafeId, string ingredientId, AdjustStockRequest request, string? userId, CancellationToken ct = default) =>
|
||||||
Task.FromResult<IngredientDto?>(null);
|
Task.FromResult<IngredientDto?>(null);
|
||||||
|
|
||||||
|
public Task<InventoryPurchasesSummaryDto> GetPurchasesSummaryAsync(
|
||||||
|
string cafeId,
|
||||||
|
string branchId,
|
||||||
|
DateOnly from,
|
||||||
|
DateOnly to,
|
||||||
|
CancellationToken ct = default) =>
|
||||||
|
Task.FromResult(new InventoryPurchasesSummaryDto(0, 0, []));
|
||||||
|
|
||||||
public Task<MenuItemRecipeDto?> GetRecipeAsync(string cafeId, string menuItemId, CancellationToken ct = default) =>
|
public Task<MenuItemRecipeDto?> GetRecipeAsync(string cafeId, string menuItemId, CancellationToken ct = default) =>
|
||||||
Task.FromResult<MenuItemRecipeDto?>(null);
|
Task.FromResult<MenuItemRecipeDto?>(null);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Meezi.API.Services;
|
using Meezi.API.Services;
|
||||||
|
using Meezi.Core.Entities;
|
||||||
|
|
||||||
namespace Meezi.API.Tests;
|
namespace Meezi.API.Tests;
|
||||||
|
|
||||||
@@ -10,4 +11,11 @@ internal sealed class NoOpLoyaltyService : ILoyaltyService
|
|||||||
decimal paidAmount,
|
decimal paidAmount,
|
||||||
CancellationToken ct = default) =>
|
CancellationToken ct = default) =>
|
||||||
Task.CompletedTask;
|
Task.CompletedTask;
|
||||||
|
|
||||||
|
public Task<(bool Success, LoyaltyRedeemResult? Data, string? ErrorCode)> RedeemOnOrderAsync(
|
||||||
|
string cafeId,
|
||||||
|
Order order,
|
||||||
|
int pointsRequested,
|
||||||
|
CancellationToken ct = default) =>
|
||||||
|
Task.FromResult<(bool, LoyaltyRedeemResult?, string?)>((false, null, null));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
using Meezi.API.Services;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
|
namespace Meezi.API.Tests;
|
||||||
|
|
||||||
|
/// <summary>Test double that stores nothing and returns no URL.</summary>
|
||||||
|
internal sealed class NoOpMediaStorageService : IMediaStorageService
|
||||||
|
{
|
||||||
|
public Task<string?> SaveMenuImageAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveMenuVideoAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveTableImageAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveTableVideoAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveCafeLogoAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveCafeCoverAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveMenuModel3dAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveMenuModel3dFromBytesAsync(string cafeId, byte[] glbBytes, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveReviewPhotoAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
public Task<string?> SaveCafeGalleryPhotoAsync(string cafeId, IFormFile file, CancellationToken cancellationToken = default) =>
|
||||||
|
Task.FromResult<string?>(null);
|
||||||
|
}
|
||||||
@@ -11,4 +11,7 @@ internal sealed class NoOpOrderNotificationService : IOrderNotificationService
|
|||||||
|
|
||||||
public Task NotifyOrderStatusChangedAsync(Order order, CancellationToken ct = default) =>
|
public Task NotifyOrderStatusChangedAsync(Order order, CancellationToken ct = default) =>
|
||||||
Task.CompletedTask;
|
Task.CompletedTask;
|
||||||
|
|
||||||
|
public Task NotifyCallWaiterAsync(string cafeId, string tableId, string tableNumber, CancellationToken ct = default) =>
|
||||||
|
Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ public class PrintingTests
|
|||||||
218_000m,
|
218_000m,
|
||||||
0m,
|
0m,
|
||||||
DateTime.UtcNow,
|
DateTime.UtcNow,
|
||||||
|
1,
|
||||||
[
|
[
|
||||||
new OrderItemDto("i1", "m1", "Espresso", 2, 100_000m, null),
|
new OrderItemDto("i1", "m1", "Espresso", 2, 100_000m, null),
|
||||||
new OrderItemDto("i2", "m2", "Void Latte", 1, 50_000m, null, true)
|
new OrderItemDto("i2", "m2", "Void Latte", 1, 50_000m, null, true)
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
using Meezi.API.Models.Menu;
|
using Meezi.API.Models.Menu;
|
||||||
using Meezi.API.Models.Orders;
|
using Meezi.API.Models.Orders;
|
||||||
using Meezi.API.Models.Public;
|
using Meezi.API.Models.Public;
|
||||||
|
using Meezi.API.Security;
|
||||||
using Meezi.API.Services;
|
using Meezi.API.Services;
|
||||||
using Meezi.Core.Entities;
|
using Meezi.Core.Entities;
|
||||||
using Meezi.Core.Enums;
|
using Meezi.Core.Enums;
|
||||||
using Meezi.Core.Interfaces;
|
using Meezi.Core.Interfaces;
|
||||||
using Meezi.Infrastructure.Data;
|
using Meezi.Infrastructure.Data;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -114,7 +116,11 @@ public class QrMenuTests
|
|||||||
var tables = new TableService(db, config, kds, identity);
|
var tables = new TableService(db, config, kds, identity);
|
||||||
var shifts = new ShiftService(db);
|
var shifts = new ShiftService(db);
|
||||||
var orders = new OrderService(db, kds, new NoOpSnappfood(), new NoOpDeliverySync(), shifts, TestServiceScopeFactory.Create(), new NoOpOrderNotificationService(), new NoOpInventoryService(), new NoOpLoyaltyService());
|
var orders = new OrderService(db, kds, new NoOpSnappfood(), new NoOpDeliverySync(), shifts, TestServiceScopeFactory.Create(), new NoOpOrderNotificationService(), new NoOpInventoryService(), new NoOpLoyaltyService());
|
||||||
var publicSvc = new PublicService(db, orders, new ReviewService(db), kds, branchMenu, identity);
|
var abuse = new NoOpAbuseProtectionService();
|
||||||
|
var http = new HttpContextAccessor();
|
||||||
|
var media = new NoOpMediaStorageService();
|
||||||
|
var reviews = new ReviewService(db, abuse, http, media);
|
||||||
|
var publicSvc = new PublicService(db, orders, reviews, kds, branchMenu, identity, abuse, http);
|
||||||
|
|
||||||
return (db, tables, publicSvc, cafeId, branchId, tableId, itemA, itemB, qrCode);
|
return (db, tables, publicSvc, cafeId, branchId, tableId, itemA, itemB, qrCode);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user