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>
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
using System.Net;
|
||||
using Xunit;
|
||||
|
||||
namespace Meezi.API.Tests.Integration;
|
||||
|
||||
[Collection(nameof(MeeziIntegrationCollection))]
|
||||
public class HealthIntegrationTests
|
||||
{
|
||||
private readonly MeeziWebApplicationFactory _factory;
|
||||
|
||||
public HealthIntegrationTests(MeeziWebApplicationFactory factory) => _factory = factory;
|
||||
|
||||
[Fact]
|
||||
public async Task Health_ReturnsOk()
|
||||
{
|
||||
using var client = _factory.CreateClient();
|
||||
var response = await client.GetAsync("/health");
|
||||
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Meezi.API.Tests.Integration;
|
||||
|
||||
[CollectionDefinition(nameof(MeeziIntegrationCollection))]
|
||||
public class MeeziIntegrationCollection : ICollectionFixture<MeeziWebApplicationFactory>;
|
||||
@@ -0,0 +1,49 @@
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Meezi.API;
|
||||
using Meezi.Infrastructure.Data;
|
||||
|
||||
namespace Meezi.API.Tests.Integration;
|
||||
|
||||
public class MeeziWebApplicationFactory : WebApplicationFactory<Program>
|
||||
{
|
||||
protected override IHost CreateHost(IHostBuilder builder)
|
||||
{
|
||||
var app = Program.BuildWebApplication(
|
||||
Array.Empty<string>(),
|
||||
ConfigureTestingBeforeServices,
|
||||
ConfigureTestingAfterServices);
|
||||
app.StartAsync().GetAwaiter().GetResult();
|
||||
return app;
|
||||
}
|
||||
|
||||
private static void ConfigureTestingBeforeServices(WebApplicationBuilder webBuilder)
|
||||
{
|
||||
webBuilder.Environment.EnvironmentName = "Testing";
|
||||
webBuilder.WebHost.UseTestServer();
|
||||
webBuilder.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
|
||||
{
|
||||
["Testing:Enabled"] = "true",
|
||||
["Testing:SkipSeed"] = "true",
|
||||
["RUN_MIGRATIONS"] = "false",
|
||||
["ConnectionStrings:Redis"] = "127.0.0.1:6379"
|
||||
});
|
||||
}
|
||||
|
||||
private static void ConfigureTestingAfterServices(WebApplicationBuilder webBuilder)
|
||||
{
|
||||
var dbDescriptor = webBuilder.Services.SingleOrDefault(d =>
|
||||
d.ServiceType == typeof(DbContextOptions<AppDbContext>));
|
||||
if (dbDescriptor is not null)
|
||||
webBuilder.Services.Remove(dbDescriptor);
|
||||
|
||||
webBuilder.Services.AddDbContext<AppDbContext>(options =>
|
||||
options.UseInMemoryDatabase("meezi_test_db"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user