Files
meezi/tests/Meezi.API.Tests/PrintingTests.cs
T
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
3.4 KiB
C#

using Meezi.API.Models.Orders;
using Meezi.API.Services.Printing;
using Meezi.Core.Enums;
using Xunit;
namespace Meezi.API.Tests;
public class PrintingTests
{
private static OrderDto SampleOrder() => new(
"order-abc12345",
"cafe-1",
"branch-1",
"table-1",
"5",
"Ali",
null,
null,
null,
null,
null,
OrderType.DineIn,
OrderSource.Pos,
OrderStatus.Pending,
200_000m,
18_000m,
0m,
218_000m,
0m,
DateTime.UtcNow,
[
new OrderItemDto("i1", "m1", "Espresso", 2, 100_000m, null),
new OrderItemDto("i2", "m2", "Void Latte", 1, 50_000m, null, true)
],
[new PaymentDto("p1", PaymentMethod.Cash, 218_000m, PaymentStatus.Completed, null)]);
private static ReceiptPrintContext Ctx(int paper = 80) => new(
SampleOrder(),
"کافه دمو",
"شعبه اصلی",
"خوش آمدید",
"با تشکر",
"wifi1234",
paper,
true);
[Fact]
public void ReceiptBuilder_ExcludesVoidedItems()
{
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
var text = System.Text.Encoding.UTF8.GetString(bytes);
Assert.Contains("Espresso", text);
Assert.DoesNotContain("Void Latte", text);
}
[Fact]
public void ReceiptBuilder_AppliesPersianCalendarDate()
{
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
var text = System.Text.Encoding.UTF8.GetString(bytes);
Assert.Contains("تاریخ:", text);
}
[Fact]
public void ReceiptBuilder_ShowsTaxLine_WhenTaxNonZero()
{
var bytes = new ReceiptBuilder().BuildReceipt(Ctx());
var text = System.Text.Encoding.UTF8.GetString(bytes);
Assert.Contains("مالیات", text);
}
[Fact]
public void ReceiptBuilder_80mm_Uses48CharWidth()
{
var sep = new EscPosBuilder().Separator(48).Build();
var receipt = new ReceiptBuilder().BuildReceipt(Ctx(80));
Assert.NotEmpty(receipt);
Assert.Contains(sep, receipt);
}
[Fact]
public void ReceiptBuilder_58mm_Uses32CharWidth()
{
var sep = new EscPosBuilder().Separator(32).Build();
var receipt = new ReceiptBuilder().BuildReceipt(Ctx(58));
Assert.Contains(sep, receipt);
}
[Fact]
public void KitchenTicket_IncludesItemNotes()
{
var order = SampleOrder() with
{
Items =
[
new OrderItemDto("i1", "m1", "Burger", 1, 100_000m, "بدون پیاز")
]
};
var ctx = Ctx() with { Order = order };
var text = System.Text.Encoding.UTF8.GetString(new ReceiptBuilder().BuildKitchenTicket(ctx));
Assert.Contains("بدون پیاز", text);
Assert.Contains("آشپزخانه", text);
}
[Fact]
public void EscPosBuilder_Cut_AppendsCorrectBytes()
{
var bytes = new EscPosBuilder().Cut().Build();
Assert.Equal([0x1D, 0x56, 0x42, 0x03], bytes);
}
[Fact]
public void EscPosBuilder_TwoColumns_PadsCorrectly()
{
var bytes = new EscPosBuilder().TwoColumns("کالا", "1000", 10).Build();
var line = System.Text.Encoding.UTF8.GetString(bytes).TrimEnd('\n');
Assert.Equal(10, line.Length);
Assert.EndsWith("1000", line);
}
}