diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b84df5..fca0e8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,6 +14,11 @@ jobs: packages: write steps: - uses: actions/checkout@v4 + - uses: actions/setup-dotnet@v4 + with: + dotnet-version: 10.0.x + - name: Run unit tests + run: dotnet test Kemkas.slnx -c Release - uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin diff --git a/.gitignore b/.gitignore index 476d627..8ad02fa 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ yarn-error.log* /local obj/ -bin/ \ No newline at end of file +bin/ +.idea/ \ No newline at end of file diff --git a/Kemkas.Web.Tests/Db/Enums/FajExtensionsTests.cs b/Kemkas.Web.Tests/Db/Enums/FajExtensionsTests.cs new file mode 100644 index 0000000..8dad123 --- /dev/null +++ b/Kemkas.Web.Tests/Db/Enums/FajExtensionsTests.cs @@ -0,0 +1,63 @@ +using Kemkas.Web.Db.Enums; + +namespace Kemkas.Web.Tests.Db.Enums; + +public class FajExtensionsTests +{ + [Theory] + [InlineData("f_ember", Faj1E.Ember)] + [InlineData("f_etuniai", Faj1E.Etuniai)] + [InlineData("f_felszerzet", Faj1E.Felszerzet)] + public void Convert1E_StringToEnum_MapsCorrectly(string input, Faj1E expected) + { + var result = FajExtensions.Convert1E(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Faj1E.Ember, "f_ember")] + [InlineData(Faj1E.Etuniai, "f_etuniai")] + [InlineData(Faj1E.Felszerzet, "f_felszerzet")] + public void Convert1E_EnumToString_MapsCorrectly(Faj1E input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData("f_2e_ember", Faj2E.Ember)] + [InlineData("f_2e_nomad", Faj2E.Nomad)] + [InlineData("f_2e_felszerzet", Faj2E.Felszerzet)] + public void Convert2E_StringToEnum_MapsCorrectly(string input, Faj2E expected) + { + var result = FajExtensions.Convert2E(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Faj2E.Ember, "f_2e_ember")] + [InlineData(Faj2E.Nomad, "f_2e_nomad")] + [InlineData(Faj2E.Felszerzet, "f_2e_felszerzet")] + public void Convert2E_EnumToString_MapsCorrectly(Faj2E input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Fact] + public void Convert1E_StringToEnum_InvalidValue_ThrowsException() + { + Assert.Throws(() => FajExtensions.Convert1E("invalid")); + } + + [Fact] + public void Convert2E_StringToEnum_InvalidValue_ThrowsException() + { + Assert.Throws(() => FajExtensions.Convert2E("invalid")); + } +} + diff --git a/Kemkas.Web.Tests/Db/Enums/JellemExtensionsTests.cs b/Kemkas.Web.Tests/Db/Enums/JellemExtensionsTests.cs new file mode 100644 index 0000000..36ff17c --- /dev/null +++ b/Kemkas.Web.Tests/Db/Enums/JellemExtensionsTests.cs @@ -0,0 +1,48 @@ +using System.ComponentModel.DataAnnotations; +using Kemkas.Web.Db.Enums; + +namespace Kemkas.Web.Tests.Db.Enums; + +public class JellemExtensionsTests +{ + [Theory] + [InlineData("TJ", Jellem.TorvenyesJo)] + [InlineData("SJ", Jellem.Jo)] + [InlineData("KJ", Jellem.KaotikusJo)] + [InlineData("TS", Jellem.Torvenyes)] + [InlineData("S", Jellem.Semleges)] + [InlineData("KS", Jellem.Kaotikus)] + [InlineData("TG", Jellem.TorvenyesGonosz)] + [InlineData("SG", Jellem.Gonosz)] + [InlineData("KG", Jellem.KaotikusGonosz)] + public void Convert_StringToEnum_MapsCorrectly(string input, Jellem expected) + { + var result = JellemExtensions.Convert(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Jellem.TorvenyesJo, "TJ")] + [InlineData(Jellem.Jo, "SJ")] + [InlineData(Jellem.KaotikusJo, "KJ")] + [InlineData(Jellem.Torvenyes, "TS")] + [InlineData(Jellem.Semleges, "S")] + [InlineData(Jellem.Kaotikus, "KS")] + [InlineData(Jellem.TorvenyesGonosz, "TG")] + [InlineData(Jellem.Gonosz, "SG")] + [InlineData(Jellem.KaotikusGonosz, "KG")] + public void Convert_EnumToString_MapsCorrectly(Jellem input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Fact] + public void Convert_StringToEnum_InvalidValue_ThrowsValidationException() + { + Assert.Throws(() => JellemExtensions.Convert("invalid")); + } +} + diff --git a/Kemkas.Web.Tests/Db/Enums/OsztalyExtensionsTests.cs b/Kemkas.Web.Tests/Db/Enums/OsztalyExtensionsTests.cs new file mode 100644 index 0000000..7e10b76 --- /dev/null +++ b/Kemkas.Web.Tests/Db/Enums/OsztalyExtensionsTests.cs @@ -0,0 +1,64 @@ +using System.ComponentModel.DataAnnotations; +using Kemkas.Web.Db.Enums; + +namespace Kemkas.Web.Tests.Db.Enums; + +public class OsztalyExtensionsTests +{ + [Theory] + [InlineData("o_harcos", Osztaly1E.Harcos)] + [InlineData("o_kaloz", Osztaly1E.Kaloz)] + [InlineData("o_illuzionista", Osztaly1E.Illuzionista)] + public void Convert1E_StringToEnum_MapsCorrectly(string input, Osztaly1E expected) + { + var result = OsztalyExtensions.Convert1E(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Osztaly1E.Harcos, "o_harcos")] + [InlineData(Osztaly1E.Kaloz, "o_kaloz")] + [InlineData(Osztaly1E.Illuzionista, "o_illuzionista")] + public void Convert1E_EnumToString_MapsCorrectly(Osztaly1E input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData("o_2e_harcos", Osztaly2E.Harcos)] + [InlineData("o_2e_tengeresz", Osztaly2E.Tengeresz)] + [InlineData("o_2e_vandor", Osztaly2E.Vandor)] + public void Convert2E_StringToEnum_MapsCorrectly(string input, Osztaly2E expected) + { + var result = OsztalyExtensions.Convert2E(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Osztaly2E.Harcos, "o_2e_harcos")] + [InlineData(Osztaly2E.Tengeresz, "o_2e_tengeresz")] + [InlineData(Osztaly2E.Vandor, "o_2e_vandor")] + public void Convert2E_EnumToString_MapsCorrectly(Osztaly2E input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Fact] + public void Convert1E_StringToEnum_InvalidValue_ThrowsValidationException() + { + Assert.Throws(() => OsztalyExtensions.Convert1E("invalid")); + } + + [Fact] + public void Convert2E_StringToEnum_InvalidValue_ThrowsValidationException() + { + Assert.Throws(() => OsztalyExtensions.Convert2E("invalid")); + } +} + diff --git a/Kemkas.Web.Tests/Db/Enums/TulajdonsagExtensionsTests.cs b/Kemkas.Web.Tests/Db/Enums/TulajdonsagExtensionsTests.cs new file mode 100644 index 0000000..88acef5 --- /dev/null +++ b/Kemkas.Web.Tests/Db/Enums/TulajdonsagExtensionsTests.cs @@ -0,0 +1,48 @@ +using System.ComponentModel.DataAnnotations; +using Kemkas.Web.Db.Enums; + +namespace Kemkas.Web.Tests.Db.Enums; + +public class TulajdonsagExtensionsTests +{ + [Theory] + [InlineData("t_ero", Tulajdonsag.Ero)] + [InlineData("t_ugy", Tulajdonsag.Ugyesseg)] + [InlineData("t_egs", Tulajdonsag.Egeszseg)] + [InlineData("t_int", Tulajdonsag.Intelligencia)] + [InlineData("t_bol", Tulajdonsag.Bolcsesseg)] + [InlineData("t_kar", Tulajdonsag.Karizma)] + public void Convert_StringToEnum_MapsCorrectly(string input, Tulajdonsag expected) + { + var result = TulajdonsagExtensions.Convert(input); + + Assert.Equal(expected, result); + } + + [Theory] + [InlineData(Tulajdonsag.Ero, "t_ero")] + [InlineData(Tulajdonsag.Ugyesseg, "t_ugy")] + [InlineData(Tulajdonsag.Egeszseg, "t_egs")] + [InlineData(Tulajdonsag.Intelligencia, "t_int")] + [InlineData(Tulajdonsag.Bolcsesseg, "t_bol")] + [InlineData(Tulajdonsag.Karizma, "t_kar")] + public void Convert_EnumToString_MapsCorrectly(Tulajdonsag input, string expected) + { + var result = input.Convert(); + + Assert.Equal(expected, result); + } + + [Fact] + public void Convert_StringToEnum_InvalidValue_ThrowsValidationException() + { + Assert.Throws(() => TulajdonsagExtensions.Convert("invalid")); + } + + [Fact] + public void Convert_EnumToString_InvalidValue_ThrowsValidationException() + { + Assert.Throws(() => ((Tulajdonsag)0).Convert()); + } +} + diff --git a/Kemkas.Web.Tests/Kemkas.Web.Tests.csproj b/Kemkas.Web.Tests/Kemkas.Web.Tests.csproj new file mode 100644 index 0000000..a11cecb --- /dev/null +++ b/Kemkas.Web.Tests/Kemkas.Web.Tests.csproj @@ -0,0 +1,26 @@ + + + + net10.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kemkas.Web.Tests/Services/FirstEdition/Character/Character1EDtoToDbModelServiceTests.cs b/Kemkas.Web.Tests/Services/FirstEdition/Character/Character1EDtoToDbModelServiceTests.cs new file mode 100644 index 0000000..d321a3e --- /dev/null +++ b/Kemkas.Web.Tests/Services/FirstEdition/Character/Character1EDtoToDbModelServiceTests.cs @@ -0,0 +1,78 @@ +using System.ComponentModel.DataAnnotations; +using Kemkas.Web.Db.Enums; +using Kemkas.Web.Db.Models; +using Kemkas.Web.Services.FirstEdition.Character; +using Kemkas.Web.Tests.Services.TestData; + +namespace Kemkas.Web.Tests.Services.FirstEdition.Character; + +public class Character1EDtoToDbModelServiceTests +{ + private readonly Character1EDtoToDbModelService _sut = new(); + + [Fact] + public void Convert_MapsDtoToEntity() + { + var dto = CharacterMapperTestData.Create1EDto(); + + var result = _sut.Convert(dto); + + Assert.Equal("Aron", result.Nev); + Assert.Equal(Jellem.TorvenyesJo, result.Jellem); + Assert.Equal(Faj1E.Ember, result.Faj); + Assert.Equal(Osztaly1E.Harcos, result.Osztaly); + Assert.Equal(3, result.KarakterKepzettsegek.Count()); + Assert.Equal(1, result.KarakterKepzettsegek.Count(x => x.IsTolvajKepzettseg)); + Assert.Equal(2, result.Felszereles.Count()); + Assert.All(result.Felszereles, x => Assert.True(x.IsFegyver)); + Assert.Equal(4, result.Szintlepesek.Count()); + Assert.Equal(10, result.Szintlepesek.Single(x => x.KarakterSzint == 1).HpRoll); + Assert.Equal("ij", result.Szintlepesek.Single(x => x.KarakterSzint == 3).FegyverSpecializacio); + Assert.Equal(Tulajdonsag.Ero, result.Szintlepesek.Single(x => x.KarakterSzint == 4).TulajdonsagNoveles); + } + + [Fact] + public void Convert_WithNotEnoughHpRolls_ThrowsValidationException() + { + var dto = CharacterMapperTestData.Create1EDto(); + dto.HpRolls = new List { 7 }; + + Assert.Throws(() => _sut.Convert(dto)); + } + + [Fact] + public void Update_ReplacesMutableCollectionsAndScalarFields() + { + var dto = CharacterMapperTestData.Create1EDto(); + var original = new V1Karakter + { + Nev = "old", + Jellem = Jellem.Semleges, + Faj = Faj1E.Elf, + Osztaly = Osztaly1E.Pap, + KarakterKepzettsegek = new List + { + new() { Kepzettseg = Kepzettseg1E.Tudas, Karakter = null! } + }, + Felszereles = new List + { + new() { Name = "old_weapon", IsFegyver = true, Karakter = null! } + }, + Szintlepesek = new List + { + new() { KarakterSzint = 1, HpRoll = 4, Karakter = null! } + } + }; + + _sut.Update(original, dto); + + Assert.Equal("Aron", original.Nev); + Assert.Equal(Jellem.TorvenyesJo, original.Jellem); + Assert.Equal(Faj1E.Ember, original.Faj); + Assert.Equal(Osztaly1E.Harcos, original.Osztaly); + Assert.Equal(3, original.KarakterKepzettsegek.Count()); + Assert.DoesNotContain(original.Felszereles, x => x.Name == "old_weapon"); + Assert.Equal(4, original.Szintlepesek.Count()); + } +} + diff --git a/Kemkas.Web.Tests/Services/FirstEdition/Character/CharacterDbModelToDto1EServiceTests.cs b/Kemkas.Web.Tests/Services/FirstEdition/Character/CharacterDbModelToDto1EServiceTests.cs new file mode 100644 index 0000000..bf687c9 --- /dev/null +++ b/Kemkas.Web.Tests/Services/FirstEdition/Character/CharacterDbModelToDto1EServiceTests.cs @@ -0,0 +1,31 @@ +using Kemkas.Web.Services.FirstEdition.Character; +using Kemkas.Web.Tests.Services.TestData; + +namespace Kemkas.Web.Tests.Services.FirstEdition.Character; + +public class CharacterDbModelToDto1EServiceTests +{ + private readonly CharacterDbModelToDto1EService _sut = new(); + + [Fact] + public void Convert_MapsEntityToDtoWithExpectedOrderingAndSplits() + { + var entity = CharacterMapperTestData.Create1EEntity(); + + var result = _sut.Convert(entity); + + Assert.Equal("Aron", result.Name); + Assert.Equal("TJ", result.Jellem); + Assert.Equal("f_ember", result.Faj); + Assert.Equal("o_harcos", result.Osztaly); + Assert.Equal(new List { "k_alkimia" }, result.Kepzettsegek); + Assert.Equal(new List { "k_osonas" }, result.Tolvajkepzettsegek); + Assert.Equal(new List { 7, 5 }, result.HpRolls); + Assert.Equal(new List { "t_ero" }, result.TulajdonsagNovelesek); + Assert.Equal(new List { "kard", "ij" }, result.HarcosSpecializaciok); + Assert.Empty(result.KalozKritikus); + Assert.Equal(new List { "kard" }, result.Felszereles1E.FegyverIds); + Assert.True(result.IsPublic); + } +} + diff --git a/Kemkas.Web.Tests/Services/SecondEdition/Character/Character2EDtoToDbModelServiceTests.cs b/Kemkas.Web.Tests/Services/SecondEdition/Character/Character2EDtoToDbModelServiceTests.cs new file mode 100644 index 0000000..58f7ad0 --- /dev/null +++ b/Kemkas.Web.Tests/Services/SecondEdition/Character/Character2EDtoToDbModelServiceTests.cs @@ -0,0 +1,84 @@ +using Kemkas.Web.Db.Enums; +using Kemkas.Web.Db.Models; +using Kemkas.Web.Services.SecondEdition.Character; +using Kemkas.Web.Tests.Services.TestData; + +namespace Kemkas.Web.Tests.Services.SecondEdition.Character; + +public class Character2EDtoToDbModelServiceTests +{ + private readonly Character2EDtoToDbModelService _sut = new(); + + [Fact] + public void Convert_MapsDtoToEntity() + { + var dto = CharacterMapperTestData.Create2EDto(); + + var result = _sut.Convert(dto); + + Assert.Equal("Belia", result.Nev); + Assert.Equal(Jellem.Torvenyes, result.Jellem); + Assert.Equal(Faj2E.Ember, result.Faj); + Assert.Equal(3, result.KarakterKepzettsegek.Count()); + Assert.Equal(1, result.KarakterKepzettsegek.Count(x => x.IsTolvajKepzettseg)); + Assert.Equal(4, result.Felszereles.Count()); + Assert.Single(result.Felszereles, x => x.IsFegyver); + Assert.Single(result.Felszereles, x => x.IsViselt); + Assert.Single(result.Felszereles, x => x.IsCipelt); + Assert.Single(result.Felszereles, x => x.IsAprosag); + Assert.Equal(2, result.Szintlepesek.Count()); + Assert.Equal("kard", result.Szintlepesek.Single(x => x.KarakterSzint == 1).FegyverSpecializacio); + Assert.Equal("szuras", result.Szintlepesek.Single(x => x.KarakterSzint == 2).FegyverSpecializacio); + Assert.Equal(Tulajdonsag.Karizma, result.Szintlepesek.Single(x => x.KarakterSzint == 2).TulajdonsagNoveles); + Assert.Single(result.Varazslatok); + Assert.Equal("v_tuz", result.Varazslatok.Single().VarazslatId); + } + + [Fact] + public void Update_WhenDtoVarazslatokIsNull_ClearsSpells() + { + var dto = CharacterMapperTestData.Create2EDto(); + dto.Varazslatok = null; + var original = CharacterMapperTestData.Create2EEntity(); + + _sut.Update(original, dto); + + Assert.Empty(original.Varazslatok); + } + + [Fact] + public void Update_ReplacesScalarFieldsAndCollections() + { + var dto = CharacterMapperTestData.Create2EDto(); + var original = new V2Karakter + { + Nev = "old", + Jellem = Jellem.Semleges, + Faj = Faj2E.Torpe, + KarakterKepzettsegek = new List + { + new() { Kepzettseg = Kepzettseg2E.Historia, Karakter = null! } + }, + Felszereles = new List + { + new() { TargyId = "old", Count = 1, IsFegyver = true, Karakter = null! } + }, + Szintlepesek = new List + { + new() { KarakterSzint = 1, Osztaly = Osztaly2E.Pap, HpRoll = 5, Karakter = null! } + }, + Varazslatok = new HashSet() + }; + + _sut.Update(original, dto); + + Assert.Equal("Belia", original.Nev); + Assert.Equal(Jellem.Torvenyes, original.Jellem); + Assert.Equal(Faj2E.Ember, original.Faj); + Assert.Equal(3, original.KarakterKepzettsegek.Count()); + Assert.DoesNotContain(original.Felszereles, x => x.TargyId == "old"); + Assert.Equal(2, original.Szintlepesek.Count()); + } +} + + diff --git a/Kemkas.Web.Tests/Services/SecondEdition/Character/CharacterDbModelToDto2EServiceTests.cs b/Kemkas.Web.Tests/Services/SecondEdition/Character/CharacterDbModelToDto2EServiceTests.cs new file mode 100644 index 0000000..36730fb --- /dev/null +++ b/Kemkas.Web.Tests/Services/SecondEdition/Character/CharacterDbModelToDto2EServiceTests.cs @@ -0,0 +1,42 @@ +using Kemkas.Web.Services.SecondEdition.Character; +using Kemkas.Web.Tests.Services.TestData; + +namespace Kemkas.Web.Tests.Services.SecondEdition.Character; + +public class CharacterDbModelToDto2EServiceTests +{ + private readonly CharacterDbModelToDto2EService _sut = new(); + + [Fact] + public void Convert_MapsEntityToDto() + { + var entity = CharacterMapperTestData.Create2EEntity(); + + var result = _sut.Convert(entity); + + Assert.Equal("Belia", result.Nev); + Assert.Equal("TS", result.Jellem); + Assert.Equal("f_2e_ember", result.Faj); + Assert.Equal(new List { "k_alkimia" }, result.Kepzettsegek); + Assert.Equal(new List { "k_osonas" }, result.Tolvajkepzettsegek); + Assert.Equal("kard", result.Felszereles.Fegyverek.Single().Id); + Assert.Equal("sisak", result.Felszereles.Viselt.Single().Id); + Assert.Equal("kotel", result.Felszereles.Cipelt.Single().Id); + Assert.Equal("gyertya", result.Felszereles.Aprosagok.Single().Id); + Assert.Equal(2, result.Szintlepesek.Count); + Assert.Equal("o_2e_harcos", result.Szintlepesek[0].Osztaly); + Assert.Equal("kard", result.Szintlepesek[0].HarcosFegyver); + Assert.Null(result.Szintlepesek[0].KalozKritikus); + Assert.Equal("o_2e_tengeresz", result.Szintlepesek[1].Osztaly); + Assert.Equal("szuras", result.Szintlepesek[1].KalozKritikus); + Assert.Null(result.Szintlepesek[1].HarcosFegyver); + Assert.Equal("t_kar", result.Szintlepesek[1].TulajdonsagNoveles); + Assert.Equal("k_zarnyitas", result.Szintlepesek[1].TolvajExtraKepzettseg); + Assert.NotNull(result.Varazslatok); + Assert.Single(result.Varazslatok); + Assert.Equal("v_tuz", result.Varazslatok[0].VarazslatId); + Assert.False(result.IsPublic ?? true); + } +} + + diff --git a/Kemkas.Web.Tests/Services/Shared/CharacterPersistenceServiceTests.cs b/Kemkas.Web.Tests/Services/Shared/CharacterPersistenceServiceTests.cs new file mode 100644 index 0000000..c11ae4d --- /dev/null +++ b/Kemkas.Web.Tests/Services/Shared/CharacterPersistenceServiceTests.cs @@ -0,0 +1,205 @@ +using Kemkas.Web.Db; +using Kemkas.Web.Db.Enums; +using Kemkas.Web.Db.Models; +using Kemkas.Web.Services.Identity; +using Kemkas.Web.Services.Shared; +using Microsoft.EntityFrameworkCore; + +namespace Kemkas.Web.Tests.Services.Shared; + +public class CharacterPersistenceServiceTests +{ + [Fact] + public async Task StoreNewCharacter1E_SetsOwnerAndPublicFlag() + { + await using var dbContext = CreateDbContext(); + var currentUserService = new FakeCurrentUserService(new ApplicationUser { Id = 42 }); + var sut = new CharacterPersistenceService(dbContext, currentUserService); + + var id = await sut.StoreNewCharacter1E(CreateV1Character(id: Guid.NewGuid()), isPublic: true); + + var saved = await dbContext.Karakterek.SingleAsync(x => x.Id == id); + Assert.Equal(42, saved.OwnerUserId); + Assert.True(saved.IsPublic); + } + + [Fact] + public async Task StoreNewCharacter2E_SetsOwnerAndPublicFlag() + { + await using var dbContext = CreateDbContext(); + var currentUserService = new FakeCurrentUserService(new ApplicationUser { Id = 99 }); + var sut = new CharacterPersistenceService(dbContext, currentUserService); + + var id = await sut.StoreNewCharacter2E(CreateV2Character(id: Guid.NewGuid()), isPublic: true); + + var saved = await dbContext.Karakterek2E.SingleAsync(x => x.Id == id); + Assert.Equal(99, saved.OwnerUserId); + Assert.True(saved.IsPublic); + } + + [Fact] + public async Task GetCharacter1EById_PrivateCharacterFromDifferentOwner_ReturnsNull() + { + await using var dbContext = CreateDbContext(); + var id = Guid.NewGuid(); + dbContext.Karakterek.Add(CreateV1Character(id, ownerUserId: 10, isPublic: false)); + await dbContext.SaveChangesAsync(); + + var sut = new CharacterPersistenceService(dbContext, new FakeCurrentUserService(new ApplicationUser { Id = 20 })); + + var result = await sut.GetCharacter1EById(id); + + Assert.Null(result); + } + + [Fact] + public async Task GetCharacter2EById_PrivateCharacterFromOwner_ReturnsEntity() + { + await using var dbContext = CreateDbContext(); + var id = Guid.NewGuid(); + dbContext.Karakterek2E.Add(CreateV2Character(id, ownerUserId: 10, isPublic: false)); + await dbContext.SaveChangesAsync(); + + var sut = new CharacterPersistenceService(dbContext, new FakeCurrentUserService(new ApplicationUser { Id = 10 })); + + var result = await sut.GetCharacter2EById(id); + + Assert.NotNull(result); + Assert.Equal(id, result.Id); + } + + [Fact] + public async Task GetCharacter2EById_PublicCharacter_ReturnsEntityForAnonymousUser() + { + await using var dbContext = CreateDbContext(); + var id = Guid.NewGuid(); + dbContext.Karakterek2E.Add(CreateV2Character(id, ownerUserId: 10, isPublic: true)); + await dbContext.SaveChangesAsync(); + + var sut = new CharacterPersistenceService(dbContext, new FakeCurrentUserService(null)); + + var result = await sut.GetCharacter2EById(id); + + Assert.NotNull(result); + Assert.Equal(id, result.Id); + } + + [Fact] + public async Task GetAllCharactersOfUser_NoCurrentUser_ReturnsEmptyList() + { + await using var dbContext = CreateDbContext(); + var sut = new CharacterPersistenceService(dbContext, new FakeCurrentUserService(null)); + + var result = await sut.GetAllCharactersOfUser(); + + Assert.Empty(result); + } + + [Fact] + public async Task GetAllCharactersOfUser_ReturnsOnlyCurrentUsersCharactersFromBothEditions() + { + await using var dbContext = CreateDbContext(); + const int userId = 7; + + dbContext.Karakterek.Add(CreateV1Character(Guid.NewGuid(), ownerUserId: userId, name: "V1 Hero")); + dbContext.Karakterek.Add(CreateV1Character(Guid.NewGuid(), ownerUserId: 999, name: "Other V1")); + + var v2Id = Guid.NewGuid(); + dbContext.Karakterek2E.Add(CreateV2Character(v2Id, ownerUserId: userId, name: "V2 Hero")); + dbContext.Szintlepesek2E.Add(new V2Szintlepes + { + Id = Guid.NewGuid(), + KarakterId = v2Id, + KarakterSzint = 1, + Osztaly = Osztaly2E.Varazslo, + HpRoll = 4, + Karakter = null! + }); + dbContext.Karakterek2E.Add(CreateV2Character(Guid.NewGuid(), ownerUserId: 999, name: "Other V2")); + + await dbContext.SaveChangesAsync(); + + var sut = new CharacterPersistenceService(dbContext, new FakeCurrentUserService(new ApplicationUser { Id = userId })); + + var result = await sut.GetAllCharactersOfUser(); + + Assert.Equal(2, result.Count); + Assert.Contains(result, x => x.Name == "V1 Hero" && x.Edition == "1e"); + Assert.Contains(result, x => x.Name == "V2 Hero" && x.Edition == "2e" && x.Osztaly == "o_2e_varazslo"); + Assert.DoesNotContain(result, x => x.Name.StartsWith("Other")); + } + + private static ApplicationDbContext CreateDbContext() + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase($"kemkas-tests-{Guid.NewGuid()}") + .Options; + + return new ApplicationDbContext(options); + } + + private static V1Karakter CreateV1Character( + Guid? id = null, + int? ownerUserId = null, + bool isPublic = false, + string name = "V1") + { + return new V1Karakter + { + Id = id ?? Guid.Empty, + OwnerUserId = ownerUserId, + IsPublic = isPublic, + Nev = name, + Faj = Faj1E.Ember, + Osztaly = Osztaly1E.Harcos, + Jellem = Jellem.Semleges, + Ero = 10, + Ugyesseg = 10, + Egeszseg = 10, + Intelligencia = 10, + Bolcsesseg = 10, + Karizma = 10, + KarakterKepzettsegek = new List(), + Szintlepesek = new List(), + Felszereles = new List() + }; + } + + private static V2Karakter CreateV2Character( + Guid? id = null, + int? ownerUserId = null, + bool isPublic = false, + string name = "V2") + { + return new V2Karakter + { + Id = id ?? Guid.Empty, + OwnerUserId = ownerUserId, + IsPublic = isPublic, + Nev = name, + Faj = Faj2E.Ember, + Jellem = Jellem.Semleges, + Ero = 10, + Ugyesseg = 10, + Egeszseg = 10, + Intelligencia = 10, + Bolcsesseg = 10, + Karizma = 10, + KarakterKepzettsegek = new List(), + Szintlepesek = new List(), + Felszereles = new List(), + Varazslatok = new HashSet() + }; + } + + private sealed class FakeCurrentUserService(ApplicationUser? user) : ICurrentUserService + { + public Task GetCurrentUser() => Task.FromResult(user); + + public Task GetCurrentUserOrThrow() => + user is null + ? throw new InvalidOperationException("no current user") + : Task.FromResult(user); + } +} + diff --git a/Kemkas.Web.Tests/Services/TestData/CharacterMapperTestData.cs b/Kemkas.Web.Tests/Services/TestData/CharacterMapperTestData.cs new file mode 100644 index 0000000..7e2bab5 --- /dev/null +++ b/Kemkas.Web.Tests/Services/TestData/CharacterMapperTestData.cs @@ -0,0 +1,184 @@ +using Kemkas.Web.Db.Enums; +using Kemkas.Web.Db.Models; +using Kemkas.Web.ViewModels; + +namespace Kemkas.Web.Tests.Services.TestData; + +internal static class CharacterMapperTestData +{ + internal static Karakter1eDto Create1EDto() => new() + { + Name = "Aron", + Nem = "fi", + Kor = 22, + Jellem = "TJ", + Isten = "Darton", + Faj = "f_ember", + Osztaly = "o_harcos", + Tulajdonsagok = new KarakterTulajdonsagokDto + { + Ero = 16, + Ugy = 14, + Egs = 13, + Int = 12, + Bol = 11, + Kar = 10 + }, + Kepzettsegek = new List { "k_alkimia", "k_hajozas" }, + Tolvajkepzettsegek = new List { "k_osonas" }, + Szint = 4, + HpRolls = new List { 7, 6, 5 }, + TulajdonsagNovelesek = new List { "t_ero" }, + HarcosSpecializaciok = new List { "hosszukard", "ij" }, + KalozKritikus = new List(), + Felszereles1E = new KarakterFelszereles1eDto + { + PancelId = "lancruha", + PajzsId = "fa_pajzs", + FegyverIds = new List { "hosszukard", "tor" } + }, + IsPublic = true + }; + + internal static Karakter2eDto Create2EDto() => new() + { + Nev = "Belia", + Nem = "no", + Kor = 25, + Jellem = "TS", + Isten = "Krad", + Faj = "f_2e_ember", + Tulajdonsagok = new KarakterTulajdonsagokDto + { + Ero = 11, + Ugy = 12, + Egs = 13, + Int = 14, + Bol = 15, + Kar = 16 + }, + Kepzettsegek = new List { "k_alkimia", "k_hamisitas" }, + Tolvajkepzettsegek = new List { "k_osonas" }, + Szint = 2, + Szintlepesek = new List + { + new() + { + Osztaly = "o_2e_harcos", + HProll = 10, + HarcosFegyver = "kard", + KalozKritikus = null, + TulajdonsagNoveles = null, + TolvajExtraKepzettseg = null + }, + new() + { + Osztaly = "o_2e_tengeresz", + HProll = 6, + HarcosFegyver = null, + KalozKritikus = "szuras", + TulajdonsagNoveles = "t_kar", + TolvajExtraKepzettseg = "k_zarnyitas" + } + }, + Felszereles = new KarakterFelszereles2eDto + { + PancelId = "bor", + PajzsId = "kis_pajzs", + AranyTaller = 10, + ElektrumTaller = 20, + EzustTaller = 30, + Fegyverek = new List { new() { Id = "kard", Count = 1 } }, + Viselt = new List { new() { Id = "sisak", Count = 1 } }, + Cipelt = new List { new() { Id = "kotel", Count = 2 } }, + Aprosagok = new List { new() { Id = "gyertya", Count = 5 } } + }, + Varazslatok = new List + { + new() { VarazslatId = "v_tuz", Bekeszitve = true, Osztaly = "o_2e_varazslo" } + }, + IsPublic = false + }; + + internal static V1Karakter Create1EEntity() => new() + { + Nev = "Aron", + Nem = "fi", + Kor = 22, + Jellem = Jellem.TorvenyesJo, + Isten = "Darton", + Faj = Faj1E.Ember, + Osztaly = Osztaly1E.Harcos, + Ero = 16, + Ugyesseg = 14, + Egeszseg = 13, + Intelligencia = 12, + Bolcsesseg = 11, + Karizma = 10, + Szint = 3, + Pajzs = "fa_pajzs", + Pancel = "lancruha", + IsPublic = true, + KarakterKepzettsegek = new List + { + new() { Kepzettseg = Kepzettseg1E.Alkimia, IsTolvajKepzettseg = false, Karakter = null! }, + new() { Kepzettseg = Kepzettseg1E.Osonas, IsTolvajKepzettseg = true, Karakter = null! } + }, + Felszereles = new List + { + new() { Name = "kard", IsFegyver = true, Karakter = null! }, + new() { Name = "kotel", IsFegyver = false, Karakter = null! } + }, + Szintlepesek = new List + { + new() { KarakterSzint = 3, HpRoll = 5, FegyverSpecializacio = "ij", Karakter = null! }, + new() { KarakterSzint = 1, HpRoll = 10, FegyverSpecializacio = "kard", Karakter = null! }, + new() { KarakterSzint = 2, HpRoll = 7, TulajdonsagNoveles = Tulajdonsag.Ero, Karakter = null! } + } + }; + + internal static V2Karakter Create2EEntity() => new() + { + Nev = "Belia", + Nem = "no", + Kor = 25, + Jellem = Jellem.Torvenyes, + Isten = "Krad", + Faj = Faj2E.Ember, + Ero = 11, + Ugyesseg = 12, + Egeszseg = 13, + Intelligencia = 14, + Bolcsesseg = 15, + Karizma = 16, + Szint = 2, + Pajzs = "kis_pajzs", + Pancel = "bor", + AranyTaller = 10, + ElektrumTaller = 20, + EzustTaller = 30, + IsPublic = false, + KarakterKepzettsegek = new List + { + new() { Kepzettseg = Kepzettseg2E.Alkimia, IsTolvajKepzettseg = false, Karakter = null! }, + new() { Kepzettseg = Kepzettseg2E.Osonas, IsTolvajKepzettseg = true, Karakter = null! } + }, + Felszereles = new List + { + new() { TargyId = "kard", Count = 1, IsFegyver = true, Karakter = null! }, + new() { TargyId = "sisak", Count = 1, IsViselt = true, Karakter = null! }, + new() { TargyId = "kotel", Count = 2, IsCipelt = true, Karakter = null! }, + new() { TargyId = "gyertya", Count = 5, IsAprosag = true, Karakter = null! } + }, + Szintlepesek = new List + { + new() { KarakterSzint = 2, Osztaly = Osztaly2E.Tengeresz, HpRoll = 6, FegyverSpecializacio = "szuras", TulajdonsagNoveles = Tulajdonsag.Karizma, TolvajExtraKepzettseg = Kepzettseg2E.Zarnyitas, Karakter = null! }, + new() { KarakterSzint = 1, Osztaly = Osztaly2E.Harcos, HpRoll = 10, FegyverSpecializacio = "kard", Karakter = null! } + }, + Varazslatok = new HashSet + { + new() { VarazslatId = "v_tuz", Bekeszitve = true, Osztaly = Osztaly2E.Varazslo, Karakter = null! } + } + }; +} + diff --git a/Kemkas.slnx b/Kemkas.slnx index 13c0714..db56216 100644 --- a/Kemkas.slnx +++ b/Kemkas.slnx @@ -9,5 +9,6 @@ + diff --git a/README.md b/README.md index cc6a08b..2d6066f 100644 --- a/README.md +++ b/README.md @@ -25,3 +25,12 @@ dotnet dev-certs https --format PEM --no-password -ep ~/.aspnet/https/kemkas.pem ``` Later start the docker compose first and the project launch settings after the DB is up and running. + +## Unit tests + +Run backend unit tests from the repository root: + +```shell +dotnet test Kemkas.slnx -c Release +``` +