text:
using Newtonsoft.Json;
using NUnit.Framework;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.game;

public class GameEventControllerTest
{
    private AccountRegistrationResponse userOne;
    private AccountRegistrationResponse userTwo;
    private AccountRegistrationResponse playerNotInGame;

    private CreateRoomResponse gameRoom;

    [SetUp]
    public async Task Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();

        playerNotInGame = await AccountUtils.AssertRegisterAccountAndAuthorized("PlayerNotInGame");
        userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("UserTwo");
        userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("UserOne");

        gameRoom = (await TestUtils.GetClient().LobbyClient.CreateNewRoom(getCreateRoomRequest())).GetOrThrow();

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinResponse = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), gameRoom.GameConfiguration.Id);
        Assert.IsTrue(joinResponse.IsSuccess());
        // Game has begun.
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
    }

    [Test]
    public async Task PlayerInAGameCanSubmitAnEvent()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));
    }

    [Test]
    public async Task CanSubmitToggleShieldEvent()
    {
        var serializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" });

        var toggleSheildResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = serializedEventData,
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, toggleSheildResponse.IsSuccess());
        Assert.AreEqual(EventDataType.ToggleShieldEventData, toggleSheildResponse.GetOrThrow().GameRoomEvent.GameEventData.EventDataType);
        Assert.AreEqual(serializedEventData, toggleSheildResponse.GetOrThrow().GameRoomEvent.GameEventData.SerializedEventData);
        Assert.IsTrue(toggleSheildResponse.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task CanSubmitPlayerLeaveGameEvent()
    {
        var serializedEventData = JsonConvert.SerializeObject(new PlayerLeaveGameEventData() { Player = null });

        var playerLeaveResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.PlayerLeaveGameEventData,
                SerializedEventData = serializedEventData,
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, playerLeaveResponse.IsSuccess());
        Assert.AreEqual(EventDataType.PlayerLeaveGameEventData, playerLeaveResponse.GetOrThrow().GameRoomEvent.GameEventData.EventDataType);
        Assert.AreEqual(serializedEventData, playerLeaveResponse.GetOrThrow().GameRoomEvent.GameEventData.SerializedEventData);
        Assert.IsTrue(playerLeaveResponse.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task CanSubmitDrillMineEvent()
    {
        var serializedEventData = JsonConvert.SerializeObject(new DrillMineEventData() { SourceId = "someOutpostId" });

        var drillMineResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.DrillMineEventData,
                SerializedEventData = serializedEventData,
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, drillMineResponse.IsSuccess());
        Assert.AreEqual(EventDataType.DrillMineEventData, drillMineResponse.GetOrThrow().GameRoomEvent.GameEventData.EventDataType);
        Assert.AreEqual(serializedEventData, drillMineResponse.GetOrThrow().GameRoomEvent.GameEventData.SerializedEventData);
        Assert.IsTrue(drillMineResponse.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task CanSubmitLaunchEvent()
    {
        var serializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
        {
            SourceId = "someOutpostId",
            DestinationId = "SomeDestination",
            DrillerCount = 10,
            SpecialistIds = new List<string>(),
        });

        var launchEventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                SerializedEventData = serializedEventData,
                EventDataType = EventDataType.LaunchEventData,
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, launchEventResponse.IsSuccess());
        Assert.AreEqual(EventDataType.LaunchEventData, launchEventResponse.GetOrThrow().GameRoomEvent.GameEventData.EventDataType);
        Assert.AreEqual(serializedEventData, launchEventResponse.GetOrThrow().GameRoomEvent.GameEventData.SerializedEventData);
        Assert.IsTrue(launchEventResponse.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task PlayerCanViewTheirOwnFutureEvents()
    {
        var serializedEventData = JsonConvert.SerializeObject(new LaunchEventData()
        {
            SourceId = "someOutpostId",
            DestinationId = "SomeDestination",
            DrillerCount = 10,
            SpecialistIds = new List<string>(),
        });

        var launchEventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                SerializedEventData = serializedEventData,
                EventDataType = EventDataType.LaunchEventData,
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, launchEventResponse.IsSuccess());
        Assert.AreEqual(EventDataType.LaunchEventData, launchEventResponse.GetOrThrow().GameRoomEvent.GameEventData.EventDataType);
        Assert.AreEqual(serializedEventData, launchEventResponse.GetOrThrow().GameRoomEvent.GameEventData.SerializedEventData);
        Assert.IsTrue(launchEventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
    }

    [Test]
    public async Task PlayerCannotSubmitEventsToAGameThatDoesNotExist()
    {
        var error = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = 42,
                },
            }, "InvalidGameRoomId");
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.NOT_FOUND, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotSubmitEventsToAGameTheyAreNotIn()
    {
        TestUtils.GetClient().UserApi.SetToken(playerNotInGame.Token);

        var error = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = 42,
                },
            }, gameRoom.GameConfiguration.Id);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotSubmitAnEventThatOccursInThePast()
    {
        var error = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = -20,
                },
            }, gameRoom.GameConfiguration.Id);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.VALIDATION_ERROR, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCanDeleteAnEventThatTheySubmitted()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        var deleteResponse = await TestUtils.GetClient().GameEventClient.DeleteGameEvent(gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);
        Assert.AreEqual(true, deleteResponse.ResponseDetail.IsSuccess);

        var gameEventsAfterDelete = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEventsAfterDelete.ResponseDetail.IsSuccess);
        Assert.AreEqual(0, gameEventsAfterDelete.GetOrThrow().GameEvents.Count);
    }

    [Test]
    public async Task PlayerCannotDeleteAnotherPlayersEvent()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        var error = await TestUtils.GetClient().GameEventClient.DeleteGameEvent(
                gameRoom.GameConfiguration.Id,
                eventResponse.GetOrThrow().EventId);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotDeleteEventsThatHaveAlreadyHappened()
    {
        // The game is configured at 1 tick per second.
        // Event at tick two is two seconds into the game, and we can sleep for 2+ seconds then try to delete.
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 2,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        // Sleep and wait until the event has passed.
        Thread.Sleep(4000);

        var error = await TestUtils.GetClient().GameEventClient
            .DeleteGameEvent(gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.VALIDATION_ERROR, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCanUpdateAGameEvent()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        var update = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            }
        }, gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);
        Assert.AreEqual(true, update.ResponseDetail.IsSuccess);
        Assert.IsTrue(update.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task PlayerCannotUpdateAGameEventWithInvalidEventId()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        var error = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = 42,
                }
            }, gameRoom.GameConfiguration.Id, "InvalidEventId");
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.NOT_FOUND, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotUpdateAGameEventWithInvalidRoomId()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        var error = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = 42,
                }
            }, "InvalidRoomId", eventResponse.GetOrThrow().EventId);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.NOT_FOUND, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotUpdateAGameEventThatHasAlreadyOccurred()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 2,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        Thread.Sleep(3000);

        var error = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
            {
                GameEventData = new GameEventData()
                {
                    EventDataType = EventDataType.ToggleShieldEventData,
                    SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                    OccursAtTick = 2,
                }
            }, gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);
        Assert.IsFalse(error.ResponseDetail.IsSuccess);
        Assert.AreEqual(ResponseType.VALIDATION_ERROR, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotUpdateAGameToOccurInThePast()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        Thread.Sleep(3000);

        var update = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 2,
            }
        }, gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);
        Assert.AreEqual(true, update.ResponseDetail.IsSuccess);
        Assert.IsTrue(update.GetOrThrow().EventId != null);
    }

    [Test]
    public async Task PlayerCannotUpdateAnotherPlayersEvent()
    {
        var eventResponse = await TestUtils.GetClient().GameEventClient.SubmitGameEvent(new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 42,
            },
        }, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, eventResponse.IsSuccess());
        Assert.IsTrue(eventResponse.GetOrThrow().EventId != null);

        // Submitting player can see their own events
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, gameEvents.GetOrThrow().GameEvents.Count);
        Assert.IsTrue(gameEvents.GetOrThrow().GameEvents.Any(it => it.Id == eventResponse.GetOrThrow().EventId));

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        var response = await TestUtils.GetClient().GameEventClient.UpdateGameEvent(new UpdateGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 2,
            }
        }, gameRoom.GameConfiguration.Id, eventResponse.GetOrThrow().EventId);;
        Assert.IsFalse(response.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, response.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayersCanViewPastEventsButOnlyTheirOwnFutureEvents()
    {
        var request = new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 3,
            },
        };
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);

        request.GameEventData.OccursAtTick = 1323;

        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);

        // Submitting player can see their own events in the future
        var gameEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, gameEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(5, gameEvents.GetOrThrow().GameEvents.Count);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        Thread.Sleep(5000);

        // Other user can see the ones in the past
        var playerTwoEvents = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.AreEqual(true, playerTwoEvents.ResponseDetail.IsSuccess);
        Assert.AreEqual(3, playerTwoEvents.GetOrThrow().GameEvents.Count);
    }

    [Test]
    public async Task AdminsCanSeeAllGameEvents()
    {
        var request = new SubmitGameEventRequest()
        {
            GameEventData = new GameEventData()
            {
                EventDataType = EventDataType.ToggleShieldEventData,
                SerializedEventData = JsonConvert.SerializeObject(new ToggleShieldEventData() { SourceId = "someOutpostId" }),
                OccursAtTick = 3,
            },
        };

        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);

        request.GameEventData.OccursAtTick = 1323;

        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);
        await TestUtils.GetClient().GameEventClient.SubmitGameEvent(request, gameRoom.GameConfiguration.Id);

        var roomResponse = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.IsTrue(roomResponse.ResponseDetail.IsSuccess);
        Assert.AreEqual(5, roomResponse.GetOrThrow().GameEvents.Count);

        Thread.Sleep(5000);

        await TestUtils.CreateSuperUserAndLogin();
        var adminRoomResponse = await TestUtils.GetClient().GameEventClient.GetGameRoomEvents(gameRoom.GameConfiguration.Id);
        Assert.IsTrue(adminRoomResponse.ResponseDetail.IsSuccess);
        Assert.AreEqual(5, adminRoomResponse.GetOrThrow().GameEvents.Count);
    }

    private CreateRoomRequest getCreateRoomRequest()
    {
        return new CreateRoomRequest()
        {
            GameSettings = new GameSettings()
            {
                IsAnonymous = false,
                Goal = Goal.Domination,
                IsRanked = false,
                MaxPlayers = 2,
                MinutesPerTick = (1.0 / 60.0), // One second per tick
            },
            RoomName = "TestRoom",
            MapConfiguration = new MapConfiguration()
            {
                Seed = 123123,
                OutpostsPerPlayer = 3,
                MinimumOutpostDistance = 100,
                MaximumOutpostDistance = 1200,
                DormantsPerPlayer = 3,
                OutpostDistribution = new OutpostDistribution()
                {
                    FactoryWeight = 0.33f,
                    GeneratorWeight = 0.33f,
                    WatchtowerWeight = 0.33f,
                }
            },
            CreatorSpecialistDeck = new List<SpecialistTypeId>()
            {
                SpecialistTypeId.Advisor,
                SpecialistTypeId.Amnesiac,
                SpecialistTypeId.Assasin,
                SpecialistTypeId.Automation,
                SpecialistTypeId.Dispatcher,
                SpecialistTypeId.Economist,
                SpecialistTypeId.Enforcer,
                SpecialistTypeId.Engineer,
                SpecialistTypeId.Escort,
                SpecialistTypeId.Foreman,
                SpecialistTypeId.Helmsman,
                SpecialistTypeId.Hypnotist,
                SpecialistTypeId.Icicle,
                SpecialistTypeId.Industrialist,
                SpecialistTypeId.Infiltrator
            }
        };
    }
}


text:
using NUnit.Framework;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.game;

public class GameAnnouncementControllerTest
{
    [SetUp]
    public void Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();
    }

    [Test]
    public async Task CanCreateAnAnnouncement()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();

        var announcement = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = "global",
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = "Sample title"
        });

        Assert.IsTrue(announcement.IsSuccess());
        Assert.NotNull(announcement.GetOrThrow().AnnouncementId);
    }

    [Test]
    public async Task CanViewAnAnnouncementAfterItIsCreated()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = "global",
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(1, announcementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(announcementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == title));
    }

    [Test]
    public async Task GlobalAnnouncementsAreVisibleToEveryone()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = "global",
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(1, announcementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(announcementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == title));
    }

    [Test]
    public async Task CanUpdateAnAnnouncementAfterPostingIt()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = "global",
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(1, announcementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(announcementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == title));

        TestUtils.GetClient().UserApi.SetToken(adminUser.Token);

        var updatedTitle = "This is an updated title!";
        var updateResponse = await TestUtils.GetClient().AnnouncementClient.UpdateAnnouncement(createResponse.GetOrThrow().AnnouncementId, new CreateAnnouncementRequest()
        {
            BroadcastTo = "global",
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = updatedTitle
        });
        Assert.IsTrue(updateResponse.IsSuccess());
        Assert.NotNull(updateResponse.GetOrThrow().AnnouncementId);

        TestUtils.GetClient().UserApi.SetToken(userOne.Token);

        var updatedAnnouncementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(updatedAnnouncementResponse.IsSuccess());
        Assert.AreEqual(1, updatedAnnouncementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(updatedAnnouncementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == updatedTitle));
    }

    [Test]
    public async Task CanBroadcastAnnouncementsToSpecificUsers()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");

        TestUtils.GetClient().UserApi.SetToken(adminUser.Token);

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = userOne.User.Id,
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        TestUtils.GetClient().UserApi.SetToken(userOne.Token);

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(1, announcementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(announcementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == title));
    }

    [Test]
    public async Task UsersNotInTheBroadcastListCannotSeeAnAnnouncement()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");
        var userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("userTwo");

        TestUtils.GetClient().UserApi.SetToken(adminUser.Token);

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = userOne.User.Id,
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(0, announcementResponse.GetOrThrow().Announcements.Count);
    }

    [Test]
    public async Task AdminsCanSeeAllAnnouncementsEvenIfTheyAreNotInTheBroadcastList()
    {
        var adminUser = await TestUtils.CreateSuperUserAndLogin();
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");

        TestUtils.GetClient().UserApi.SetToken(adminUser.Token);

        var title = "Sample title";
        var createResponse = await TestUtils.GetClient().AnnouncementClient.CreateAnnouncement(new CreateAnnouncementRequest()
        {
            BroadcastTo = userOne.User.Id,
            StartsAt = DateTime.UtcNow.AddDays(-2),
            ExpiresAt = DateTime.UtcNow.AddDays(3),
            Message = "This is an announcement! Welcome to the game!",
            Title = title
        });

        Assert.IsTrue(createResponse.IsSuccess());
        Assert.NotNull(createResponse.GetOrThrow().AnnouncementId);

        var announcementResponse = await TestUtils.GetClient().AnnouncementClient.GetAnnouncements();
        Assert.IsTrue(announcementResponse.IsSuccess());
        Assert.AreEqual(1, announcementResponse.GetOrThrow().Announcements.Count);
        Assert.IsTrue(announcementResponse.GetOrThrow().Announcements.Any(announcement => announcement.Title == title));
    }
}

repo_name: Subterfuge-Revived/Remake-Core

repo_language: C#

mime_type: text/plain


text:
using NUnit.Framework;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.game;

public class LobbyControllerTest
{
    private AccountRegistrationResponse userOne;
    private AccountRegistrationResponse userTwo;
    private AccountRegistrationResponse userThree;

    [SetUp]
    public async Task Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();

        userThree = await AccountUtils.AssertRegisterAccountAndAuthorized("UserThree");
        userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("UserTwo");
        userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("UserOne");

    }

    [Test]
    public async Task PlayerCanCreateAGameRoom()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby();
    }

    [Test]
    public async Task PlayerCanJoinAGameRoom()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby();

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinResponse = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsTrue(joinResponse.ResponseDetail.IsSuccess);

        // View open rooms.
        var openLobbiesResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(openLobbiesResponse.IsSuccess(), true);

        var openLobbiesResponseData = openLobbiesResponse.GetOrThrow();

        Assert.AreEqual(1,openLobbiesResponseData.Lobbies.Length);
        Assert.AreEqual(userOne.User.Id,openLobbiesResponseData.Lobbies[0].Creator.Id);
        Assert.AreEqual(userOne.User.Username,openLobbiesResponseData.Lobbies[0].Creator.Username);
        Assert.AreEqual("My room!",openLobbiesResponseData.Lobbies[0].RoomName);
        Assert.AreEqual(RoomStatus.Open,openLobbiesResponseData.Lobbies[0].RoomStatus);
        Assert.AreEqual(false,openLobbiesResponseData.Lobbies[0].GameSettings.IsAnonymous);
        Assert.AreEqual(Goal.Domination,openLobbiesResponseData.Lobbies[0].GameSettings.Goal);
        Assert.AreEqual(2,openLobbiesResponseData.Lobbies[0].PlayersInLobby.Count);
        Assert.IsTrue(openLobbiesResponseData.Lobbies[0].PlayersInLobby.Any(it => it.Id == userTwo.User.Id));
    }

    [Test]
    public async Task PlayerCannotJoinTheSameGameTwice()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby();

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinResponseOne = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsTrue(joinResponseOne.ResponseDetail.IsSuccess);

        var exception = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsFalse(exception.IsSuccess());
        Assert.AreEqual(ResponseType.DUPLICATE, exception.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCannotJoinAGameThatHasAlreadyStarted()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby(maxPlayers: 2);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinTwoResponse = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsTrue(joinTwoResponse.ResponseDetail.IsSuccess);

        TestUtils.GetClient().UserApi.SetToken(userThree.Token);
        var exception = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsFalse(exception.IsSuccess());
        Assert.AreEqual(ResponseType.ROOM_IS_FULL, exception.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task BeingTheLastPlayerToJoinAGameWillStartTheGame()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby(maxPlayers: 2);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinTwoResponse = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsTrue(joinTwoResponse.ResponseDetail.IsSuccess);

        // Check to see that the game room is ONGOING
        var openLobbiesResponseAfterJoin = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest() { RoomStatus = RoomStatus.Ongoing });
        Assert.AreEqual(openLobbiesResponseAfterJoin.IsSuccess(), true);
        Assert.AreEqual(1, openLobbiesResponseAfterJoin.GetOrThrow().Lobbies.Length);
    }

    [Test]
    public async Task PlayerCanLeaveAGameRoom()
    {
        var lobbyResponse = await LobbyUtils.CreateLobby();

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var joinTwoResponse = await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), lobbyResponse.GameConfiguration.Id);
        Assert.IsTrue(joinTwoResponse.ResponseDetail.IsSuccess);

        // Check to see the player has joined
        await LobbyUtils.AssertPlayerInLobby(userTwo.User.Id);

        var leaveResponse = await TestUtils.GetClient().LobbyClient.LeaveRoom(lobbyResponse.GameConfiguration.Id);
        Assert.AreEqual(leaveResponse.IsSuccess(), true);

        // Check to see the player has left
        await LobbyUtils.AssertPlayerInLobby(userTwo.User.Id, isInLobby: false);
    }

    [Test]
    public async Task PlayerCanSeeAListOfAvaliableRooms()
    {
        await LobbyUtils.CreateLobby("Room 1");
        await LobbyUtils.CreateLobby("Room 2");
        await LobbyUtils.CreateLobby("Room 3");
        await LobbyUtils.CreateLobby("Room 4");

        // All rooms are listed in the lobby view.
        var openLobbiesResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(openLobbiesResponse.IsSuccess(), true);
        Assert.AreEqual(4,openLobbiesResponse.GetOrThrow().Lobbies.Length);
    }

    private async Task<CreateRoomResponse[]> InitLobbiesForQueryParams()
    {
        var roomOne = await LobbyUtils.CreateLobby(
            "Room 1",
            maxPlayers: 7,
            isRanked: false,
            goal: Goal.Domination
        );

        // Login to a different account to test searching for players in a room.
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        var roomTwo = await LobbyUtils.CreateLobby(
            "Room 2",
            maxPlayers: 5,
            isRanked: true,
            goal: Goal.Domination
        );
        var roomThree = await LobbyUtils.CreateLobby(
            "Room 3",
            maxPlayers: 100,
            isRanked: false,
            goal: Goal.Mining
        );
        var roomFour = await LobbyUtils.CreateLobby(
            "Room 4",
            maxPlayers: 10,
            isRanked: true,
            goal: Goal.Mining
        );

        return new CreateRoomResponse[] { roomOne, roomTwo, roomThree, roomFour };
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByRoomStatus()
    {
        await InitLobbiesForQueryParams();

        // All rooms are listed in the default lobby view.
        var allOpenLobbyResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Open });
        Assert.AreEqual(allOpenLobbyResponse.IsSuccess(), true);
        Assert.AreEqual(4,allOpenLobbyResponse.GetOrThrow().Lobbies.Length);
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByCreatorId()
    {
        await InitLobbiesForQueryParams();

        // Check filter by creator
        var createdByResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ CreatedByUserId = userOne.User.Id, RoomStatus = RoomStatus.Open });
        Assert.AreEqual(1,createdByResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(createdByResponse.GetOrThrow().Lobbies.All(lobby => lobby.Creator.Id == userOne.User.Id));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByRoomId()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by roomId
        var roomIdResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomId = rooms[1].GameConfiguration.Id});
        Assert.AreEqual(1,roomIdResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(roomIdResponse.GetOrThrow().Lobbies.All(lobby => lobby.Id == rooms[1].GameConfiguration.Id));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByGameMode()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by game mode
        var goalFilterResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ Goal = Goal.Mining});
        Assert.AreEqual(2,goalFilterResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(goalFilterResponse.GetOrThrow().Lobbies.All(lobby => lobby.GameSettings.Goal == Goal.Mining));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByRankedStatus()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by ranked
        var rankedResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ IsRanked = false, RoomStatus = RoomStatus.Open});
        Assert.AreEqual(2,rankedResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(rankedResponse.GetOrThrow().Lobbies.All(lobby => lobby.GameSettings.IsRanked == false));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByWithMultipleFilters()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by ranked and Game Mode
        var rankedGameModeResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ IsRanked = true, Goal = Goal.Mining});
        Assert.AreEqual(1,rankedGameModeResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(rankedGameModeResponse.GetOrThrow().Lobbies.All(lobby => lobby.GameSettings.IsRanked && lobby.GameSettings.Goal == Goal.Mining));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByMinPlayers()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by minPlayers
        var minPlayersResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ MinPlayers = 9});
        Assert.AreEqual(2,minPlayersResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(minPlayersResponse.GetOrThrow().Lobbies.All(lobby => lobby.GameSettings.MaxPlayers > 9));
    }

    [Test]
    public async Task PlayerCanQueryLobbiesByMaxPlayers()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Check filter by maxPlayers
        var maxPlayersResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ MaxPlayers = 9, RoomStatus = RoomStatus.Open });
        Assert.AreEqual(2,maxPlayersResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(maxPlayersResponse.GetOrThrow().Lobbies.All(lobby => lobby.GameSettings.MaxPlayers < 9));
    }

    [Test]
    public async Task PlayerCannotQueryLobbiesThatAnotherPlayerIsIn()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Ensure normal user cannot search for lobbies another player is in.
        var exception = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ UserIdInRoom = userOne.User.Id});
        Assert.IsFalse(exception.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, exception.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayerCanQueryLobbiesTheyHaveJoined()
    {
        var rooms = await InitLobbiesForQueryParams();

        // Normal user can search for lobbies they have already joined.
        var lobbyUserIsIn = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ UserIdInRoom = userTwo.User.Id});
        Assert.AreEqual(3,lobbyUserIsIn.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(lobbyUserIsIn.GetOrThrow().Lobbies.All(lobby => lobby.PlayersInLobby.Any(it => it.Id == userTwo.User.Id)));
    }

    [Test]
    public async Task AdminCanViewAllLobbies()
    {
        var rooms = await InitLobbiesForQueryParams();

        await TestUtils.CreateSuperUserAndLogin();
        // Ensure admin can view all lobbies.
        var adminAllOpenLobbyResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(4,adminAllOpenLobbyResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(adminAllOpenLobbyResponse.GetOrThrow().Lobbies.All(lobby => lobby.RoomStatus == RoomStatus.Open));
    }

    [Test]
    public async Task AdminCanSearchLobbiesOtherPlayersAreIn()
    {
        var rooms = await InitLobbiesForQueryParams();

        await TestUtils.CreateSuperUserAndLogin();
        // Ensure admin can view all lobbies for other players.
        var adminPlayerLobbyResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ UserIdInRoom = userTwo.User.Id});
        Assert.AreEqual(3,adminPlayerLobbyResponse.GetOrThrow().Lobbies.Length);
        Assert.IsTrue(adminPlayerLobbyResponse.GetOrThrow().Lobbies.All(lobby => lobby.PlayersInLobby.Any(player => player.Id == userTwo.User.Id)));
    }

    [Test]
    public async Task PlayerWhoCreatesALobbyIsAMemberOfThatLobby()
    {
        await LobbyUtils.CreateLobby();

        // View open rooms.
        var openLobbiesResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());

        // Ensure the creator is a member
        Assert.IsTrue(openLobbiesResponse.GetOrThrow().Lobbies[0].PlayersInLobby.Any(it => it.Username == userOne.User.Username));
    }

    [Test]
    public async Task WhenALobbyIsCreatedTheGameConfigurationsAreCorrect()
    {
        await LobbyUtils.CreateLobby();

        // View open rooms.
        var openLobbiesResponse = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(openLobbiesResponse.IsSuccess(), true);

        var openLobbiesResponseData = openLobbiesResponse.GetOrThrow();
        Assert.AreEqual(1,openLobbiesResponseData.Lobbies.Length);
        Assert.AreEqual(userOne.User.Id,openLobbiesResponseData.Lobbies[0].Creator.Id);
        Assert.AreEqual(userOne.User.Username,openLobbiesResponseData.Lobbies[0].Creator.Username);
        Assert.AreEqual("My room!",openLobbiesResponseData.Lobbies[0].RoomName);
        Assert.AreEqual(RoomStatus.Open,openLobbiesResponseData.Lobbies[0].RoomStatus);
        Assert.AreEqual(false,openLobbiesResponseData.Lobbies[0].GameSettings.IsAnonymous);
        Assert.AreEqual(Goal.Domination,openLobbiesResponseData.Lobbies[0].GameSettings.Goal);
        Assert.AreEqual(1,openLobbiesResponseData.Lobbies[0].PlayersInLobby.Count);
        Assert.AreEqual(userOne.User.Username,openLobbiesResponseData.Lobbies[0].PlayersInLobby[0].Username);
    }

    [Test]
    public async Task IfTheCreatorOfALobbyLeavesTheGameIsDestroyed()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Leave the lobby right away
        await TestUtils.GetClient().LobbyClient.LeaveRoom(response.GameConfiguration.Id);

        // View open rooms.
        var lobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(lobbies.IsSuccess(), true);
        Assert.AreEqual(0,lobbies.GetOrThrow().Lobbies.Length);
    }

    [Test]
    public async Task IfTheCreatorOfALobbyLeavesTheGameNoPlayersAreStuckInTheLobby()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Login as another player and join the created lobby
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), response.GameConfiguration.Id);

        // Leave the room as the creator
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
        await TestUtils.GetClient().LobbyClient.LeaveRoom(response.GameConfiguration.Id);

        // View open rooms.
        var lobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest());
        Assert.AreEqual(lobbies.IsSuccess(), true);
        Assert.AreEqual(0,lobbies.GetOrThrow().Lobbies.Length);

        // Login as player two and try to get a list of lobbies you are in
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        var userTwoLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest() { UserIdInRoom = userTwo.User.Id });
        Assert.AreEqual(userTwoLobbies.IsSuccess(), true);
        Assert.AreEqual(0,userTwoLobbies.GetOrThrow().Lobbies.Length);
    }

    [Test]
    public async Task PlayerCanStartAGameEarlyIfTwoPlayersAreInTheLobby()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Login as another player and join the created lobby
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), response.GameConfiguration.Id);

        // Start the room as the creator
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
        var timeBeforeStart = DateTime.UtcNow;
        await TestUtils.GetClient().LobbyClient.StartGameEarly(response.GameConfiguration.Id);

        // View open rooms should not show any lobbies.
        var openLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Open});
        Assert.AreEqual(openLobbies.IsSuccess(), true);
        Assert.AreEqual(0,openLobbies.GetOrThrow().Lobbies.Length);

        // Ongoing rooms will show the game as started
        var ongoingLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(ongoingLobbies.IsSuccess(), true);
        Assert.AreEqual(1,ongoingLobbies.GetOrThrow().Lobbies.Length);
        Assert.Less(timeBeforeStart, ongoingLobbies.GetOrThrow().Lobbies[0].TimeStarted);
    }

    [Test]
    public async Task PlayerCannotSeeOngoingLobbiesTheyAreNotIn()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Login as another player and join the created lobby
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), response.GameConfiguration.Id);

        // Start the room as the creator
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
        var timeBeforeStart = DateTime.UtcNow;
        await TestUtils.GetClient().LobbyClient.StartGameEarly(response.GameConfiguration.Id);

        // View open rooms should not show any lobbies.
        var openLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Open});
        Assert.AreEqual(openLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(0,openLobbies.GetOrThrow().Lobbies.Length);

        // Ongoing rooms will show the game as started
        var ongoingLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(ongoingLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(1,ongoingLobbies.GetOrThrow().Lobbies.Length);
        Assert.Less(timeBeforeStart, ongoingLobbies.GetOrThrow().Lobbies[0].TimeStarted);

        // Player three cannot see the game.
        TestUtils.GetClient().UserApi.SetToken(userThree.Token);
        var playerThreeLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(playerThreeLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(0,playerThreeLobbies.GetOrThrow().Lobbies.Length);
    }

    [Test]
    public async Task PlayerCannotStartAGameEarlyWithNobodyInTheLobby()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Start the room as the creator
        var timeBeforeStart = DateTime.UtcNow;
        var exception = await TestUtils.GetClient().LobbyClient.StartGameEarly(response.GameConfiguration.Id);
        Assert.IsFalse(exception.IsSuccess());
        Assert.AreEqual(ResponseType.VALIDATION_ERROR, exception.ResponseDetail.ResponseType);
    }

    [Ignore("Not implemented")]
    [Test]
    public void PlayerCannotSeeALobbyThatABlockedPlayerIsIn()
    {
        throw new NotImplementedException();
    }

    [Ignore("Not implemented")]
    [Test]
    public void PrivateGameRoomsCannotBeSeen()
    {
        throw new NotImplementedException();
    }

    [Ignore("Not implemented")]
    [Test]
    public void PlayersCanCreatePrivateGameRooms()
    {
        throw new NotImplementedException();
    }

    [Ignore("Not implemented")]
    [Test]
    public void PlayersCanJoinAPrivateLobbyIfTheyKnowTheLobbyId()
    {
        throw new NotImplementedException();
    }

    [Test]
    public async Task AdminsCanViewAnyOngoingGameTheyAreNotIn()
    {
        // Create a lobby
        var response = await LobbyUtils.CreateLobby();

        // Login as another player and join the created lobby
        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), response.GameConfiguration.Id);

        // Start the room as the creator
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
        var timeBeforeStart = DateTime.UtcNow;
        await TestUtils.GetClient().LobbyClient.StartGameEarly(response.GameConfiguration.Id);

        // View open rooms should not show any lobbies.
        var openLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Open});
        Assert.AreEqual(openLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(0,openLobbies.GetOrThrow().Lobbies.Length);

        // Ongoing rooms will show the game as started
        var ongoingLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(ongoingLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(1,ongoingLobbies.GetOrThrow().Lobbies.Length);
        Assert.Less(timeBeforeStart, ongoingLobbies.GetOrThrow().Lobbies[0].TimeStarted);

        // Player three cannot see the game.
        TestUtils.GetClient().UserApi.SetToken(userThree.Token);
        var playerThreeLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(playerThreeLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(0,playerThreeLobbies.GetOrThrow().Lobbies.Length);

        // Admin can see the game.
        await TestUtils.CreateSuperUserAndLogin();
        var adminLobbies = await TestUtils.GetClient().LobbyClient.GetLobbies(new GetLobbyRequest(){ RoomStatus = RoomStatus.Ongoing});
        Assert.AreEqual(adminLobbies.ResponseDetail.IsSuccess, true);
        Assert.AreEqual(1,adminLobbies.GetOrThrow().Lobbies.Length);
    }
}


text:
using NUnit.Framework;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.game;

public class GroupControllerTest
{
    private AccountRegistrationResponse userOne;
    private AccountRegistrationResponse userTwo;
    private AccountRegistrationResponse userThree;
    private AccountRegistrationResponse userNotInGame;

    private CreateRoomResponse gameRoom;

    [SetUp]
    public async Task Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();

        userNotInGame = await AccountUtils.AssertRegisterAccountAndAuthorized("UserOutOfGame");
        userThree = await AccountUtils.AssertRegisterAccountAndAuthorized("UserThree");
        userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("UserTwo");
        userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("UserOne");

        gameRoom = (await TestUtils.GetClient().LobbyClient.CreateNewRoom(getCreateRoomRequest())).GetOrThrow();

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), gameRoom.GameConfiguration.Id);

        TestUtils.GetClient().UserApi.SetToken(userThree.Token);
        await TestUtils.GetClient().LobbyClient.JoinRoom(TestUtils.CreateJoinRequest(), gameRoom.GameConfiguration.Id);
        // Game has begun.
        TestUtils.GetClient().UserApi.SetToken(userOne.Token);
    }

    [Test]
    public async Task PlayersCanStartAChatWithAnotherPlayer()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);
    }

    [Test]
    public async Task PlayersCanStartAGroupChatWithMultipleOtherPlayers()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id, userThree.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);
    }

    [Test]
    public async Task PlayersCannotStartAChatWithPlayersWhoAreNotInTheGame()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id, userNotInGame.User.Id }
        };

        var error = await TestUtils.GetClient().GroupClient.CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.VALIDATION_ERROR, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayersCannotStartAChatWithTheSamePeople()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var error = await TestUtils.GetClient().GroupClient.CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.DUPLICATE, error.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task PlayersCanSendMessagesToAGroup()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var sendResponse = await TestUtils.GetClient().GroupClient.SendMessage(
            new SendMessageRequest() { Message = "Hello World!" },
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(sendResponse.ResponseDetail.IsSuccess);
    }

    [Test]
    public async Task PlayerCanViewTheirOwnMessageAfterSendingInAGroupChat()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var sendResponse = await TestUtils.GetClient().GroupClient.SendMessage(
            new SendMessageRequest() { Message = "Hello World!" },
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(sendResponse.ResponseDetail.IsSuccess);

        var messagesInGroup = await TestUtils.GetClient().GroupClient.GetMessages(new GetGroupMessagesRequest(),
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(messagesInGroup.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, messagesInGroup.GetOrThrow().Messages.Count);
    }

    [Test]
    public async Task GettingGroupDataReturnsTheLatestMessagesInTheGroupByDefault()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var message = "Hello World!";
        var sendResponse = await TestUtils.GetClient().GroupClient.SendMessage(
            new SendMessageRequest() { Message = message },
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(sendResponse.ResponseDetail.IsSuccess);

        var messageGroups = await TestUtils.GetClient().GroupClient.GetMessageGroups(gameRoom.GameConfiguration.Id);
        Assert.IsTrue(messageGroups.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, messageGroups.GetOrThrow().MessageGroups.Count);
        Assert.AreEqual(1, messageGroups.GetOrThrow().MessageGroups[0].Messages.Count);
        Assert.IsTrue(messageGroups.GetOrThrow().MessageGroups[0].Messages.Any(groupMessage => groupMessage.Message == message));
    }

    [Test]
    public async Task PlayerCanViewAnotherUsersMessageInAChat()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var sendResponse = await TestUtils.GetClient().GroupClient.SendMessage(
            new SendMessageRequest() { Message = "Hello World!" },
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(sendResponse.ResponseDetail.IsSuccess);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);

        var messagesInGroup = await TestUtils.GetClient().GroupClient.GetMessages(new GetGroupMessagesRequest(),
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(messagesInGroup.ResponseDetail.IsSuccess);
        Assert.AreEqual(1, messagesInGroup.GetOrThrow().Messages.Count);
        Assert.IsTrue(messagesInGroup.GetOrThrow().Messages.Any(it => it.SentBy.Id == userOne.User.Id));
    }

    [Test]
    public async Task AllPlayersCanChatInAGroupChatAndMessagesAreOrderedByDate()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id, userThree.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        var messageToSend = new SendMessageRequest() { Message = "Hello World!" };
        await TestUtils.GetClient().GroupClient.SendMessage(messageToSend, gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);

        TestUtils.GetClient().UserApi.SetToken(userTwo.Token);
        await TestUtils.GetClient().GroupClient.SendMessage(messageToSend, gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);

        TestUtils.GetClient().UserApi.SetToken(userThree.Token);
        await TestUtils.GetClient().GroupClient.SendMessage(messageToSend, gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);

        var messagesInGroup = await TestUtils.GetClient().GroupClient.GetMessages(new GetGroupMessagesRequest(),
            gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsTrue(messagesInGroup.ResponseDetail.IsSuccess);
        Assert.AreEqual(3, messagesInGroup.GetOrThrow().Messages.Count);

        // Ensure messages are ordered by the most recently recieved ;)
        Assert.AreEqual(messagesInGroup.GetOrThrow().Messages[0].SentBy.Id, userThree.User.Id);
        Assert.AreEqual(messagesInGroup.GetOrThrow().Messages[1].SentBy.Id, userTwo.User.Id);
        Assert.AreEqual(messagesInGroup.GetOrThrow().Messages[2].SentBy.Id, userOne.User.Id);
    }

    [Test]
    public async Task CannotSendMessageToGroupYouAreNotIn()
    {
        var request = new CreateMessageGroupRequest()
        {
            UserIdsInGroup = new List<string>() { userOne.User.Id, userTwo.User.Id, userThree.User.Id }
        };

        var response = await TestUtils.GetClient().GroupClient
            .CreateMessageGroup(request, gameRoom.GameConfiguration.Id);
        Assert.AreEqual(response.ResponseDetail.IsSuccess, true);
        Assert.IsTrue(response.GetOrThrow().GroupId != null);

        TestUtils.GetClient().UserApi.SetToken(userNotInGame.Token);

        var messageToSend = new SendMessageRequest() { Message = "Hello World!" };
        var error = await TestUtils.GetClient().GroupClient
                .SendMessage(messageToSend, gameRoom.GameConfiguration.Id, response.GetOrThrow().GroupId);
        Assert.IsFalse(error.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, error.ResponseDetail.ResponseType);
    }

    [Ignore("Not implemented")]
    [Test]
    public void PlayersCannotSeeMessagesFromPlayersTheyHaveBlocked()
    {
        throw new NotImplementedException();
    }

    private CreateRoomRequest getCreateRoomRequest()
    {
        return new CreateRoomRequest()
        {
            GameSettings = new GameSettings()
            {
                IsAnonymous = false,
                Goal = Goal.Domination,
                IsRanked = false,
                MaxPlayers = 3,
                MinutesPerTick = (1.0 / 60.0), // One second per tick
            },
            RoomName = "TestRoom",
            MapConfiguration = new MapConfiguration()
            {
                Seed = 123123,
                OutpostsPerPlayer = 3,
                MinimumOutpostDistance = 100,
                MaximumOutpostDistance = 1200,
                DormantsPerPlayer = 3,
                OutpostDistribution = new OutpostDistribution()
                {
                    FactoryWeight = 0.33f,
                    GeneratorWeight = 0.33f,
                    WatchtowerWeight = 0.33f,
                }
            },
            CreatorSpecialistDeck = new List<SpecialistTypeId>()
            {
                SpecialistTypeId.Advisor,
                SpecialistTypeId.Amnesiac,
                SpecialistTypeId.Assasin,
                SpecialistTypeId.Automation,
                SpecialistTypeId.Dispatcher,
                SpecialistTypeId.Economist,
                SpecialistTypeId.Enforcer,
                SpecialistTypeId.Engineer,
                SpecialistTypeId.Escort,
                SpecialistTypeId.Foreman,
                SpecialistTypeId.Helmsman,
                SpecialistTypeId.Hypnotist,
                SpecialistTypeId.Icicle,
                SpecialistTypeId.Industrialist,
                SpecialistTypeId.Infiltrator
            }
        };
    }
}


text:
using NUnit.Framework;
using Subterfuge.Remake.Server.Test.util;

namespace Subterfuge.Remake.Server.Test.test.admin;

public class AdminControllerTest
{

    [SetUp]
    public void Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();
    }

    [Test]
    public async Task AdministratorCanBanAPlayer(){}

    [Test]
    public async Task AdministratorCanViewAPlayersBanHistory(){}

    [Test]
    public async Task AdministratorCanBanAnIp(){}

    [Test]
    public async Task AdministratorCanBanAnIpByRegex(){}

    [Test]
    public async Task AdministratorCanViewTheServerExceptionLog(){}

    [Test]
    public async Task AdministratorCanSearchTheServerExceptionLogCaseInsensitive(){}

    [Test]
    public async Task AdministratorCanViewAListOfPlayerActions(){}

    [Test]
    public async Task AdministratorCanSearchTheListOfPlayerActionsCaseInsensitive(){}
}


text:
using NUnit.Framework;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.account;

public class UserRoleControllerTest
{
    [SetUp]
    public void Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();
    }

    [Test]
    public async Task NonAdministratorCanGetTheirOwnRoles()
    {
        var registerResponse = await AccountUtils.AssertRegisterAccountAndAuthorized("user");
        var response = await TestUtils.GetClient().UserRoles.GetRoles(registerResponse.User.Id);
        Assert.IsTrue(response.ResponseDetail.IsSuccess);
        Assert.AreEqual(response.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, response.GetOrThrow().Claims);
    }

    [Test]
    public async Task AdministratorsCanGetRolesForAnyone()
    {
        var registerResponse = await AccountUtils.AssertRegisterAccountAndAuthorized("user");

        var adminResponse = await TestUtils.CreateSuperUserAndLogin();
        var response = await TestUtils.GetClient().UserRoles.GetRoles(registerResponse.User.Id);
        Assert.IsTrue(response.ResponseDetail.IsSuccess);
        Assert.AreEqual(response.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, response.GetOrThrow().Claims);
    }

    [Test]
    public async Task NonAdministratorsCannotGetRolesForAnotherPlayer()
    {
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");
        var userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("userTwo");

        var response =  await TestUtils.GetClient().UserRoles.GetRoles(userOne.User.Id);
        Assert.IsFalse(response.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, response.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task AdministratorsCanUpdateOtherUserRoles()
    {
        var registerResponse = await AccountUtils.AssertRegisterAccountAndAuthorized("user");

        var adminResponse = await TestUtils.CreateSuperUserAndLogin();
        var roleResponse = await TestUtils.GetClient().UserRoles.GetRoles(registerResponse.User.Id);
        Assert.IsTrue(roleResponse.ResponseDetail.IsSuccess);
        Assert.AreEqual(roleResponse.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, roleResponse.GetOrThrow().Claims);
        Assert.IsFalse(roleResponse.GetOrThrow().Claims.Any(claim => claim == UserClaim.Administrator));

        var newRoleList = roleResponse.GetOrThrow().Claims.ToList();
        newRoleList.Add(UserClaim.Administrator);
        var updateRole = await TestUtils.GetClient().UserRoles.SetRoles(registerResponse.User.Id,
            new UpdateRolesRequest()
            {
                Claims = newRoleList.ToArray(),
            });
        Assert.IsTrue(updateRole.ResponseDetail.IsSuccess);

        var updatedRoleResponse = await TestUtils.GetClient().UserRoles.GetRoles(registerResponse.User.Id);
        Assert.IsTrue(updatedRoleResponse.ResponseDetail.IsSuccess);
        Assert.AreEqual(updatedRoleResponse.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, updatedRoleResponse.GetOrThrow().Claims);
        Assert.Contains(UserClaim.Administrator, updatedRoleResponse.GetOrThrow().Claims);
    }

    [Test]
    public async Task NonAdministratorsCannotUpdateOtherUserRoles()
    {
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized("userOne");
        var userTwo = await AccountUtils.AssertRegisterAccountAndAuthorized("userTwo");

        var updateRole = await TestUtils.GetClient().UserRoles.SetRoles(userOne.User.Id,
                new UpdateRolesRequest()
                {
                    Claims = new[] { UserClaim.Administrator, UserClaim.User },
                });
        Assert.IsFalse(updateRole.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, updateRole.ResponseDetail.ResponseType);
    }
}


text:
using NUnit.Framework;
using Subterfuge.Remake.Api.Client;
using Subterfuge.Remake.Api.Network;
using Subterfuge.Remake.Server.Test.util;
using Subterfuge.Remake.Server.Test.util.account;

namespace Subterfuge.Remake.Server.Test.test.account;

public class UserControllerTest
{
    private SubterfugeClient client = TestUtils.GetClient();

    [SetUp]
    public void Setup()
    {
        TestUtils.Mongo.FlushAll();
        TestUtils.GetClient().UserApi.Logout();
    }

    [Test]
    public async Task CanLoginAsAdmin()
    {
        var account = await TestUtils.Mongo.CreateSuperUser();
        var response = await client.UserApi.Login(new AuthorizationRequest() { Username = "admin", Password = "admin" });
        Assert.True(response.IsSuccess());
        Assert.IsNotNull(response.GetOrThrow().Token);
        Assert.IsNotNull(response.GetOrThrow().User);
    }

    [Test]
    public async Task UserCanRegisterNewAccount()
    {
        var response = await client.UserApi.RegisterAccount(new AccountRegistrationRequest()
        {
            DeviceIdentifier = "MyDevice",
            Password = "test",
            PhoneNumber = "1231231231",
            Username = "test"
        });
        Assert.True(response.IsSuccess());
        Assert.IsNotNull(response.GetOrThrow().Token);
        Assert.IsNotNull(response.GetOrThrow().User);
    }

    [Test]
    public async Task UserIsLoggedInAfterRegistering()
    {
        await AccountUtils.AssertRegisterAccountAndAuthorized("SomeUsername");
    }

    [Test]
    public async Task PlayerCanLoginAfterRegisteringNewAccount()
    {
        string username = "OtherUsername";
        await AccountUtils.AssertRegisterAccountAndAuthorized(username);
        TestUtils.GetClient().UserApi.Logout();
        await AccountUtils.AssertLogin(username);
        await AccountUtils.AssertUserAuthorized();
    }

    [Test]
    public async Task PlayerCannotRegisterWithTheSameUsername()
    {
        string username = "OtherUsername";
        await AccountUtils.AssertRegisterAccountAndAuthorized(username);

        var accountRegistrationResponse = await TestUtils.GetClient().UserApi.RegisterAccount(new AccountRegistrationRequest()
        {
            DeviceIdentifier = Guid.NewGuid().ToString(),
            Password = username,
            PhoneNumber = Guid.NewGuid().ToString(),
            Username = username
        });
        Assert.IsFalse(accountRegistrationResponse.IsSuccess());
        Assert.AreEqual(ResponseType.DUPLICATE, accountRegistrationResponse.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task SuperUserAccountHasAdminClaims()
    {
        var account = await TestUtils.Mongo.CreateSuperUser();
        var loginResponse = await TestUtils.GetClient().UserApi.Login(new AuthorizationRequest() { Username = "admin", Password = "admin" });
        var response = await TestUtils.GetClient().UserRoles.GetRoles(loginResponse.GetOrThrow().User.Id);
        Assert.IsTrue(response.IsSuccess());
        Assert.AreEqual(response.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, response.GetOrThrow().Claims);
        Assert.Contains(UserClaim.Administrator, response.GetOrThrow().Claims);
    }

    [Test]
    public async Task NewAccountRegistrationsHaveNormalUserClaims()
    {
        var registerResponse = await AccountUtils.AssertRegisterAccountAndAuthorized("user");
        var response = await TestUtils.GetClient().UserRoles.GetRoles(registerResponse.User.Id);
        Assert.IsTrue(response.ResponseDetail.IsSuccess);
        Assert.AreEqual(response.ResponseDetail.ResponseType, ResponseType.SUCCESS);
        Assert.Contains(UserClaim.User, response.GetOrThrow().Claims);
    }

    [Test]
    public async Task AdministratorsCanListAllUsers()
    {
        // Make some dummy accounts
        await AccountUtils.AssertRegisterAccountAndAuthorized("UserOne");
        await AccountUtils.AssertRegisterAccountAndAuthorized("UserTwo");

        var loginResponse = await TestUtils.CreateSuperUserAndLogin();
        var response = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest());
        Assert.AreEqual(3, response.GetOrThrow().users.Count);
    }

    [Test]
    public async Task NonAdministratorsCannotListAllUsers()
    {
        // Make some dummy accounts
        await AccountUtils.AssertRegisterAccountAndAuthorized("UserOne");
        await AccountUtils.AssertRegisterAccountAndAuthorized("UserTwo");
        await AccountUtils.AssertRegisterAccountAndAuthorized("UserThree");

        var exception = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest());
        Assert.IsFalse(exception.IsSuccess());
        Assert.AreEqual(ResponseType.PERMISSION_DENIED, exception.ResponseDetail.ResponseType);
    }

    [Test]
    public async Task AdminsCanGetUsersByUsername()
    {
        await SeedUsersInDatabase();

        // Can search by username
        var usernameResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest() { UsernameSearch = "UserOne"});
        Assert.IsTrue(usernameResponse.IsSuccess());
        Assert.AreEqual(1, usernameResponse.GetOrThrow().users.Count);
        Assert.IsTrue(usernameResponse.GetOrThrow().users.All(user => user.Username.Contains("UserOne")));
    }

    [Test]
    public async Task AdminsCanGetUsersByUsernameCaseInsensitive()
    {
        await SeedUsersInDatabase();

        // Can search by username
        var usernameResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest() { UsernameSearch = "userone"});
        Assert.AreEqual(1, usernameResponse.GetOrThrow().users.Count);
        Assert.IsTrue(usernameResponse.GetOrThrow().users.All(user => user.Username.Contains("UserOne")));
    }

    [Test]
    public async Task AdminsCanGetUsersByEmailAndUsername()
    {
        await SeedUsersInDatabase();

        // Can search by email AND username
        var emailAndUsernameResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest() { RequireUserClaim = UserClaim.User, UsernameSearch = "userTwo"});
        Assert.AreEqual(1, emailAndUsernameResponse.GetOrThrow().users.Count);
        Assert.IsTrue(emailAndUsernameResponse.GetOrThrow().users.All(user => user.Claims.Contains(UserClaim.User) && user.Username.Contains("UserTwo")));
    }

    [Test]
    public async Task AdminsCanGetUsersByDeviceId()
    {
        await SeedUsersInDatabase();

        // Can search by deviceId
        var deviceIdResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest(){ DeviceIdentifierSearch = "FakeDeviceId"});
        Assert.AreEqual(1, deviceIdResponse.GetOrThrow().users.Count);
        // Cannot ensure the returned user has the device ID because we hash them when they get returned.
    }

    [Test]
    public async Task AdminsCanGetUsersHavingSpecificRoles()
    {
        await SeedUsersInDatabase();

        // Can search by Claims
        var claimsResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest(){ RequireUserClaim = UserClaim.User});
        // There is 4! The super user is also considered a normal user!
        Assert.AreEqual(4, claimsResponse.GetOrThrow().users.Count);
        Assert.IsTrue(claimsResponse.GetOrThrow().users.All(user => user.Claims.Contains(UserClaim.User)));
    }

    [Test]
    public async Task AdminsCanGetUsersByUserId()
    {
        var userOne = await AccountUtils.AssertRegisterAccountAndAuthorized(
            username: "UserOne",
            email: "MyFakeEmail@someEmail.com",
            deviceId: "FakeDeviceId",
            phone: "9999999999"
        );

        await TestUtils.CreateSuperUserAndLogin();

        var userIdResponse = await TestUtils.GetClient().UserApi.GetUsers(new GetUserRequest(){ UserIdSearch = userOne.User.Id });
        Assert.AreEqual(1, userIdResponse.GetOrThrow().users.Count);
        Assert.IsTrue(userIdResponse.GetOrThrow().users.All(user => user.Id == userOne.User.Id));
    }

    private async Task SeedUsersInDatabase()
    {
        // Make some dummy accounts with different data to filter on
        await AccountUtils.AssertRegisterAccountAndAuthorized(
            username: "UserOne",
            email: "MyFakeEmail@someEmail.com",
            deviceId: "FakeDeviceId",
            phone: "9999999999"
        );

        await AccountUtils.AssertRegisterAccountAndAuthorized(
            username: "UserTwo",
            email: "RealEmail@realEmail.com",
            deviceId: "RealDeviceId",
            phone: "0000000000"
        );

        await AccountUtils.AssertRegisterAccountAndAuthorized(
            username: "UserThree",
            email: "RealEmailAsWell@realEmail.com",
            deviceId: "DifferentDeviceId",
            phone: "1231231231"
        );

        await TestUtils.CreateSuperUserAndLogin();
    }
}