Files
meezi/tests/Meezi.API.Tests/DeliveryIntegrationTests.cs
soroush.asadi ef15fd6247 feat(api): .NET 10 multi-tenant REST API
Full backend implementation:
- Multi-tenant cafe/restaurant management (menus, orders, tables, staff)
- POS order flow with ZarinPal and Snappfood payment integration
- OTP authentication via Kavenegar SMS
- QR digital menu with public discover/finder endpoints
- Customer loyalty, coupons, CRM
- PostgreSQL via EF Core, Redis for caching/sessions
- Background jobs, webhook handlers
- Full migration history

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-05-27 21:33:48 +03:30

121 lines
4.1 KiB
C#

using Meezi.API.Configuration;
using Meezi.API.Models.Snappfood;
using Meezi.API.Models.Tap30;
using Meezi.API.Services.Delivery;
using Meezi.Core.Delivery;
using Meezi.Core.Enums;
using Meezi.Infrastructure.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Options;
using Xunit;
namespace Meezi.API.Tests;
public class DeliveryIntegrationTests
{
private static DeliveryPlatformsOptions TestOptions() => new()
{
DefaultSnappfoodCommissionPercent = 18,
DefaultTap30CommissionPercent = 15
};
[Fact]
public void OrderNormalizer_Snappfood_MapsToUnifiedOrder()
{
var normalizer = new OrderNormalizer();
var unified = normalizer.FromSnappfood(new SnappfoodWebhookOrder(
"sf-100",
"vendor-1",
"Ali",
"09121234567",
250_000m,
[new SnappfoodWebhookItem("Espresso", 2, 100_000m)]));
Assert.NotNull(unified);
Assert.Equal("sf-100", unified!.ExternalId);
Assert.Equal(DeliveryPlatform.Snappfood, unified.Platform);
Assert.Equal(2, unified.Items[0].Quantity);
Assert.Equal(UnifiedDeliveryStatus.Confirmed, unified.Status);
}
[Fact]
public void OrderNormalizer_Tap30_MapsToUnifiedOrder()
{
var normalizer = new OrderNormalizer();
var unified = normalizer.FromTap30(new Tap30WebhookOrder(
"t30-55",
"tap-vendor",
new Tap30Customer("Sara", "09129876543", "Tehran", null, null),
180_000m,
"online",
true,
null,
"delivery",
35,
null,
null,
"confirmed",
[new Tap30WebhookItem("latte-1", "Latte", 1, 180_000m, null)]));
Assert.NotNull(unified);
Assert.Equal(DeliveryPlatform.Tap30, unified!.Platform);
Assert.Equal("Sara", unified.Customer.Name);
Assert.Equal(35, unified.Delivery.EstimatedMinutes);
}
[Fact]
public async Task CommissionCalculator_SnappfoodDefault_Is18Percent()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
await using var db = new AppDbContext(options);
var calc = new CommissionCalculator(db, Options.Create(TestOptions()));
var commission = await calc.CalculateForOrderAsync(
"cafe-1",
new UnifiedDeliveryOrder(
"x1",
DeliveryPlatform.Snappfood,
"v1",
DateTime.UtcNow,
new UnifiedDeliveryCustomer("A", "09"),
[new UnifiedDeliveryItem("1", "Coffee", 1, 100_000m)],
new UnifiedDeliveryPayment(100_000m, "online", true),
new UnifiedDeliveryInfo("delivery"),
UnifiedDeliveryStatus.Confirmed));
Assert.Equal(18_000m, commission);
}
[Fact]
public async Task CommissionCalculator_Tap30Default_Is15Percent()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
await using var db = new AppDbContext(options);
var calc = new CommissionCalculator(db, Options.Create(TestOptions()));
var rate = await calc.ResolveRatePercentAsync("cafe-1", DeliveryPlatform.Tap30);
Assert.Equal(15m, rate);
Assert.Equal(15_000m, calc.CalculateCommission(100_000m, rate));
}
[Fact]
public void WebhookSignature_ValidHmac_Accepts()
{
const string secret = "test-secret";
const string body = """{"orderId":"1"}""";
var expected = WebhookSignatureService.ComputeHmacSha256Hex(body, secret);
var svc = new WebhookSignatureService(Options.Create(new DeliveryPlatformsOptions
{
Snappfood = new SnappfoodPlatformOptions { WebhookSecret = secret }
}));
Assert.True(svc.Verify(DeliveryPlatform.Snappfood, body, expected));
Assert.True(svc.Verify(DeliveryPlatform.Snappfood, body, $"sha256={expected}"));
}
}