mirror of
https://github.com/JogmansonReal/Radicade.git
synced 2026-10-25 23:18:56 -07:00
124 lines
4.2 KiB
C#
124 lines
4.2 KiB
C#
using System.Reflection;
|
|
using System.Security.Claims;
|
|
using Microsoft.AspNetCore.Http;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using RadicadeServer.API.Messages;
|
|
using RadicadeServer.API.Notifications;
|
|
using RadicadeServer.DB;
|
|
using RadicadeServer.RecNet.Enums.Messages;
|
|
using RadicadeServer.RecNet.Messages;
|
|
using RadicadeServer.RecNet.Responses;
|
|
using Xunit;
|
|
|
|
namespace RadicadeServer.Tests;
|
|
|
|
/// <summary>
|
|
/// The message fan-out the September client posts as `POST /api/messages/v1/sendMultiple` when
|
|
/// one message goes to several people. The 2026-10-03 client run showed the other account's
|
|
/// client reading a 404 here while an invite was being sorted out - which is what a missing
|
|
/// route looks like from the client side - so the route is pinned by shape and behaviour now.
|
|
/// </summary>
|
|
public class MessagesFanoutTests
|
|
{
|
|
private const long SenderId = 2;
|
|
private const long FriendId = 5;
|
|
|
|
private sealed class TestDbContextFactory : IDbContextFactory<RecDBContext>
|
|
{
|
|
private readonly DbContextOptions<RecDBContext> options = TestDbOptions.Create()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options;
|
|
|
|
public RecDBContext CreateDbContext() => new(options);
|
|
}
|
|
|
|
private static void SetUser(Controller controller, long userId)
|
|
{
|
|
var identity = new ClaimsIdentity("TestAuth");
|
|
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userId.ToString()));
|
|
controller.ControllerContext = new ControllerContext
|
|
{
|
|
HttpContext = new DefaultHttpContext { User = new ClaimsPrincipal(identity) }
|
|
};
|
|
}
|
|
|
|
[Fact]
|
|
public void SendMultipleIsServedUnderItsClientSpelling()
|
|
{
|
|
var routes = typeof(MessagesAPI).GetMethod(nameof(MessagesAPI.SendMultipleMessages))!
|
|
.GetCustomAttributes<HttpPostAttribute>()
|
|
.Select(attribute => attribute.Template!)
|
|
.ToArray();
|
|
|
|
Assert.Contains("v1/sendMultiple", routes);
|
|
}
|
|
|
|
/// <summary>
|
|
/// One stored row per unique recipient - the same MessageReceived push and v2/get inbox row
|
|
/// the single send produces - with the sender from the token, the type passed through
|
|
/// unmapped and the data carried as sent.
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task SendMultipleStoresOneRowPerUniqueRecipient()
|
|
{
|
|
var factory = new TestDbContextFactory();
|
|
var previous = Notify.DbFactory;
|
|
Notify.DbFactory = factory;
|
|
try
|
|
{
|
|
using var db = factory.CreateDbContext();
|
|
var api = new MessagesAPI(db);
|
|
SetUser(api, SenderId);
|
|
|
|
var result = await api.SendMultipleMessages(new SendMultipleMessagesRequestDTO
|
|
{
|
|
ToPlayerIds = new List<long> { FriendId, FriendId, 0, -3 },
|
|
Type = MessageType.FriendStatusOnline,
|
|
Data = "hello"
|
|
});
|
|
|
|
Assert.True(result.success);
|
|
var stored = Assert.Single(await db.Messages.ToListAsync());
|
|
Assert.Equal(FriendId, stored.ToPlayerId);
|
|
Assert.Equal(SenderId, stored.FromPlayerId);
|
|
Assert.Equal(MessageType.FriendStatusOnline, stored.Type);
|
|
Assert.Equal("hello", stored.Data);
|
|
}
|
|
finally
|
|
{
|
|
Notify.DbFactory = previous;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// A body with no usable id is refused by the name the reference uses for that case, and
|
|
/// nothing is stored or pushed.
|
|
/// </summary>
|
|
[Fact]
|
|
public async Task SendMultipleWithoutAUsableRecipientStoresNothing()
|
|
{
|
|
var factory = new TestDbContextFactory();
|
|
var previous = Notify.DbFactory;
|
|
Notify.DbFactory = factory;
|
|
try
|
|
{
|
|
using var db = factory.CreateDbContext();
|
|
var api = new MessagesAPI(db);
|
|
SetUser(api, SenderId);
|
|
|
|
var result = await api.SendMultipleMessages(new SendMultipleMessagesRequestDTO
|
|
{
|
|
ToPlayerIds = new List<long> { 0, -1 }
|
|
});
|
|
|
|
Assert.False(result.success);
|
|
Assert.Empty(await db.Messages.ToListAsync());
|
|
}
|
|
finally
|
|
{
|
|
Notify.DbFactory = previous;
|
|
}
|
|
}
|
|
}
|