Refactor project structure and update documentation. Replace PixiJS with plain DOM for UI rendering, enhance README with game features, and revise protocol documentation for HTTP API. Remove unused files and streamline client code for better maintainability.
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
namespace HSchool.Simulation.Tests;
|
||||
|
||||
public class SchoolRegistryTests
|
||||
{
|
||||
private static readonly DateTime Start = new(2012, 4, 3, 6, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private static SchoolRegistry NewRegistry(int maxSchools = 6) =>
|
||||
new(new SimulationOptions { MaxSchools = maxSchools, TickRate = 20, GameMinutesPerRealSecond = 5 });
|
||||
|
||||
[Fact]
|
||||
public void NewRegistry_IsEmpty()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
Assert.Equal(0, registry.Count);
|
||||
Assert.Equal(6, registry.MaxSchools);
|
||||
Assert.False(registry.IsFull);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_AddsASchoolAtTheGivenStartDate()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
var result = registry.Create("Гимназия №1", Start);
|
||||
|
||||
Assert.True(result.Succeeded);
|
||||
Assert.Equal("Гимназия №1", result.School!.Name);
|
||||
Assert.Equal(Start, result.School.Clock.Time);
|
||||
|
||||
// A new school starts living straight away; only the pause button stops it.
|
||||
Assert.True(result.School.Clock.IsRunning);
|
||||
Assert.Equal(1, registry.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_BeyondTheLimit_Fails()
|
||||
{
|
||||
using var registry = NewRegistry(maxSchools: 2);
|
||||
registry.Create("Первая", Start);
|
||||
registry.Create("Вторая", Start);
|
||||
|
||||
var result = registry.Create("Третья", Start);
|
||||
|
||||
Assert.False(result.Succeeded);
|
||||
Assert.Equal(SchoolCreationError.LimitReached, result.Error);
|
||||
Assert.True(registry.IsFull);
|
||||
Assert.Equal(2, registry.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_FreesASlot()
|
||||
{
|
||||
using var registry = NewRegistry(maxSchools: 1);
|
||||
var first = registry.Create("Первая", Start).School!;
|
||||
|
||||
Assert.False(registry.Create("Вторая", Start).Succeeded);
|
||||
Assert.True(registry.Delete(first.Id));
|
||||
|
||||
Assert.True(registry.Create("Вторая", Start).Succeeded);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Delete_UnknownId_ReportsFailure()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
Assert.False(registry.Delete(42));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Ids_AreNotReusedAfterDeletion()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
var first = registry.Create("Первая", Start).School!;
|
||||
registry.Delete(first.Id);
|
||||
|
||||
var second = registry.Create("Вторая", Start).School!;
|
||||
|
||||
Assert.NotEqual(first.Id, second.Id);
|
||||
Assert.Null(registry.Find(first.Id));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(" ")]
|
||||
[InlineData("\t\n")]
|
||||
public void Create_RejectsBlankNames(string name)
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
Assert.Equal(SchoolCreationError.InvalidName, registry.Create(name, Start).Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_RejectsOverlongNames()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
var result = registry.Create(new string('ш', School.MaxNameLength + 1), Start);
|
||||
|
||||
Assert.Equal(SchoolCreationError.InvalidName, result.Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_TrimsAndStripsControlCharacters()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
var result = registry.Create(" Лицей ", Start);
|
||||
|
||||
Assert.Equal("Лицей", result.School!.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Create_RejectsStartDatesOutsideTheSupportedRange()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
|
||||
var result = registry.Create("Школа", new DateTime(1500, 1, 1, 0, 0, 0, DateTimeKind.Utc));
|
||||
|
||||
Assert.Equal(SchoolCreationError.InvalidStartDate, result.Error);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tick_AdvancesOnlyRunningSchools()
|
||||
{
|
||||
using var registry = NewRegistry();
|
||||
var running = registry.Create("Идёт", Start).School!;
|
||||
var paused = registry.Create("Стоит", Start).School!;
|
||||
paused.Clock.IsRunning = false;
|
||||
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
registry.Tick();
|
||||
}
|
||||
|
||||
Assert.Equal(Start.AddMinutes(5), running.Clock.Time);
|
||||
Assert.Equal(Start, paused.Clock.Time);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SuggestName_NeverRepeatsAnExistingName()
|
||||
{
|
||||
using var registry = NewRegistry(maxSchools: 20);
|
||||
|
||||
for (var i = 0; i < 20; i++)
|
||||
{
|
||||
var suggestion = registry.SuggestName();
|
||||
Assert.True(registry.Create(suggestion, Start).Succeeded, $"\"{suggestion}\" was rejected.");
|
||||
}
|
||||
|
||||
var names = registry.Schools.Select(school => school.Name).ToArray();
|
||||
Assert.Equal(names.Length, names.Distinct(StringComparer.OrdinalIgnoreCase).Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SuggestedNames_FitTheNameLimit()
|
||||
{
|
||||
var generator = new SchoolNameGenerator(new Random(1234));
|
||||
|
||||
for (var i = 0; i < 200; i++)
|
||||
{
|
||||
var name = generator.Next([]);
|
||||
Assert.InRange(name.Length, 1, School.MaxNameLength);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dispose_DropsEverySchool()
|
||||
{
|
||||
var registry = NewRegistry();
|
||||
registry.Create("Школа", Start);
|
||||
|
||||
registry.Dispose();
|
||||
|
||||
Assert.Equal(0, registry.Count);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user