94 lines
3.4 KiB
C#
94 lines
3.4 KiB
C#
using System.Net;
|
|
using System.Net.Http.Json;
|
|
using System.Text.Json;
|
|
|
|
namespace ClaudeMailbox.Tests;
|
|
|
|
public sealed class MailboxEndToEndTests
|
|
{
|
|
[Fact]
|
|
public async Task Health_Returns_Ok()
|
|
{
|
|
await using var host = await TestHost.StartAsync();
|
|
|
|
var res = await host.Client.GetAsync("/health");
|
|
res.EnsureSuccessStatusCode();
|
|
|
|
var body = await res.Content.ReadFromJsonAsync<JsonElement>();
|
|
Assert.Equal("ok", body.GetProperty("status").GetString());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Send_Without_Header_Is_BadRequest()
|
|
{
|
|
await using var host = await TestHost.StartAsync();
|
|
|
|
var res = await host.Client.PostAsJsonAsync("/v1/send", new { to = "anyone", body = "hi" });
|
|
Assert.Equal(HttpStatusCode.BadRequest, res.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Two_Mailboxes_Coordinate()
|
|
{
|
|
await using var host = await TestHost.StartAsync();
|
|
using var backend = host.NewClientFor("backend");
|
|
using var frontend = host.NewClientFor("frontend");
|
|
|
|
// backend sends to frontend
|
|
var send = await backend.PostAsJsonAsync("/v1/send", new { to = "frontend", body = "API shape changed" });
|
|
send.EnsureSuccessStatusCode();
|
|
|
|
// frontend peeks — expects 1
|
|
var peek1 = await frontend.GetFromJsonAsync<JsonElement>("/v1/peek?name=frontend");
|
|
Assert.Equal(1, peek1.GetProperty("pending").GetInt32());
|
|
|
|
// frontend consumes
|
|
var check = await frontend.PostAsync("/v1/check-inbox?name=frontend", null);
|
|
check.EnsureSuccessStatusCode();
|
|
var messages = await check.Content.ReadFromJsonAsync<JsonElement>();
|
|
Assert.Equal(1, messages.GetArrayLength());
|
|
var msg = messages[0];
|
|
Assert.Equal("backend", msg.GetProperty("from").GetString());
|
|
Assert.Equal("API shape changed", msg.GetProperty("body").GetString());
|
|
|
|
// peek again — expects 0
|
|
var peek2 = await frontend.GetFromJsonAsync<JsonElement>("/v1/peek?name=frontend");
|
|
Assert.Equal(0, peek2.GetProperty("pending").GetInt32());
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Check_Inbox_Rejects_Mismatched_Identity()
|
|
{
|
|
await using var host = await TestHost.StartAsync();
|
|
using var backend = host.NewClientFor("backend");
|
|
using var frontend = host.NewClientFor("frontend");
|
|
|
|
await backend.PostAsJsonAsync("/v1/send", new { to = "frontend", body = "hello" });
|
|
|
|
// backend tries to consume frontend's inbox — must be rejected
|
|
var bad = await backend.PostAsync("/v1/check-inbox?name=frontend", null);
|
|
Assert.Equal(HttpStatusCode.Forbidden, bad.StatusCode);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task List_Returns_Known_Mailboxes()
|
|
{
|
|
await using var host = await TestHost.StartAsync();
|
|
using var a = host.NewClientFor("alpha");
|
|
using var b = host.NewClientFor("beta");
|
|
|
|
// Touch both mailboxes by having each peek its own inbox
|
|
await a.GetAsync("/v1/peek?name=alpha");
|
|
await b.GetAsync("/v1/peek?name=beta");
|
|
|
|
// /v1/list is the only endpoint that works without X-Mailbox
|
|
var list = await host.Client.GetFromJsonAsync<JsonElement>("/v1/list");
|
|
var names = new List<string>();
|
|
foreach (var elem in list.EnumerateArray())
|
|
names.Add(elem.GetProperty("name").GetString()!);
|
|
|
|
Assert.Contains("alpha", names);
|
|
Assert.Contains("beta", names);
|
|
}
|
|
}
|