Merge branch 'review/slice-8-session'
This commit is contained in:
@@ -111,6 +111,26 @@ public class SessionApiTests(AppHostFixture fixture)
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Login_SetsHttpOnlyLaxSessionCookie()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
using var response = await client.PostAsJsonAsync(
|
||||
"/api/session",
|
||||
new { password = SchoolApiTests.TestPassword, userName = $"Cookie-{Guid.NewGuid():N}"[..14] },
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
Assert.True(response.Headers.TryGetValues("Set-Cookie", out var values));
|
||||
var cookie = Assert.Single(values, value =>
|
||||
value.StartsWith("hschool.session=", StringComparison.OrdinalIgnoreCase));
|
||||
var parts = cookie.Split(';', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries);
|
||||
Assert.Contains(parts, part => part.Equals("httponly", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(parts, part => part.Equals("samesite=lax", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(parts, part => part.Equals("path=/", StringComparison.OrdinalIgnoreCase));
|
||||
Assert.Contains(parts, part => part.Equals("max-age=1209600", StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WebSocket_WithoutSession_ClosesWithoutWelcome()
|
||||
{
|
||||
@@ -123,6 +143,40 @@ public class SessionApiTests(AppHostFixture fixture)
|
||||
Assert.Equal(WebSocketCloseStatus.PolicyViolation, socket.CloseStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SecondWebSocket_ForAnOnlineName_ClosesWithoutWelcome()
|
||||
{
|
||||
using var client = fixture.App.CreateHttpClient("server");
|
||||
await SchoolApiTests.ResetAsync(client);
|
||||
|
||||
var name = $"DupWs-{Guid.NewGuid():N}"[..14];
|
||||
var cookie = await SchoolApiTests.LoginAndGetCookieAsync(client, name);
|
||||
|
||||
var first = new ClientWebSocket();
|
||||
first.Options.SetRequestHeader("Cookie", cookie);
|
||||
var http = fixture.App.GetEndpoint("server", "http");
|
||||
var uri = new UriBuilder(http) { Scheme = "ws", Path = "/ws/game" }.Uri;
|
||||
await first.ConnectAsync(uri, TestContext.Current.CancellationToken).WaitAsync(DefaultTimeout);
|
||||
try
|
||||
{
|
||||
await SendHelloAsync(first);
|
||||
await ReceiveWelcomeAsync(first);
|
||||
|
||||
using var second = new ClientWebSocket();
|
||||
second.Options.SetRequestHeader("Cookie", cookie);
|
||||
await second.ConnectAsync(uri, TestContext.Current.CancellationToken).WaitAsync(DefaultTimeout);
|
||||
await SendHelloAsync(second);
|
||||
|
||||
var frame = await ReceiveOneFrameAsync(second, TimeSpan.FromSeconds(5));
|
||||
Assert.Equal(WebSocketMessageType.Close, frame.MessageType);
|
||||
Assert.Equal(WebSocketCloseStatus.PolicyViolation, second.CloseStatus);
|
||||
}
|
||||
finally
|
||||
{
|
||||
first.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private HttpClient CreateAnonymousClient()
|
||||
{
|
||||
var http = fixture.App.GetEndpoint("server", "http").ToString();
|
||||
|
||||
@@ -34,9 +34,26 @@ public class ClockTempoTests
|
||||
school.Tick(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(Start.AddMinutes(1), school.Clock.Time);
|
||||
Assert.Equal(20, school.HeavySystemsInvocations);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AtX5_TwentyImpulses_RunHeavyFiveTimesAndAdvanceFiveGameMinutes()
|
||||
{
|
||||
using var school = School.Create(1, "Страйд ×5", Start);
|
||||
school.Clock.SpeedIndex = 3;
|
||||
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
school.Tick(OneTwentiethOfASecond, GameMinutesPerRealSecond);
|
||||
}
|
||||
|
||||
Assert.Equal(Start.AddMinutes(5), school.Clock.Time);
|
||||
Assert.Equal(5, school.HeavySystemsInvocations);
|
||||
Assert.Equal(1d, school.LastHeavyGameMinutes);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(3, 5d)]
|
||||
[InlineData(4, 10d)]
|
||||
|
||||
Reference in New Issue
Block a user