using MijnBesluit.Application.Models; using MijnBesluit.Application.Services; using MijnBesluit.Domain.Entities; using MijnBesluit.Domain.Enums; namespace MijnBesluit.SelfCheck; /// /// De soorten kluisitems uit de database: wat de beheerder kan instellen en welke regels daarbij /// vastliggen. /// /// Het hart is één afspraak: wat in gebruik is, verdwijnt nooit. Een soort waar een item mee is /// gemaakt kan niet worden verwijderd, en niet-actief zetten haalt hem alleen weg bij wie hem nog /// nooit gebruikte. De rest hier is daar de omlijsting van: wie het mag instellen, hoe de velden /// van een eigen soort worden gecontroleerd, en dat "Bespreken met" een instelling per soort is. /// public static class SoortenChecks { private static async Task BeheerderAsync(World w, string email = "beheer@example.nl") { var u = await w.MaakGebruikerAsync(email, "Beheer", "Er"); w.Store.Users.Single(x => x.Id == u.Id).IsBeheerder = true; return u; } private static async Task MaakAsync(World w, User beheerder, string naam, bool bespreken = false) { var r = await w.Soorten.MaakAsync(beheerder.Id, naam, null, bespreken); if (!r.Succeeded) throw new AssertionException($"soort maken mislukte: {r.Error}"); return r.Value; } public static void Register(Runner runner) { runner.TestAsync("Soorten: de startlijst is precies wat er voorheen vast in de code stond", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var lijst = await w.Soorten.ZichtbaarVoorAsync(jan.PersonId); Assert.True(lijst.Count == 12, "twaalf soorten: elf ingebouwde en Overig"); Assert.True(lijst.First().Naam == "Wachtwoord" && lijst.Last().Naam == "Overig", "de volgorde is die van de oude keuzelijst"); var bespreekbaar = lijst.Where(s => s.BesprekenMet).Select(s => s.Naam).OrderBy(n => n).ToArray(); Assert.True(bespreekbaar.SequenceEqual(new[] { "Donorcodicil", "Uitvaartwens" }), "alleen uitvaartwens en donorcodicil kennen Bespreken met, zoals voorheen"); Assert.True(lijst.All(s => s.Ingebouwd && s.Velden.Count == 0), "ingebouwde soorten hebben geen eigen velden"); }); runner.TestAsync("Soorten: alleen een beheerder maakt of wijzigt soorten", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); Assert.True(!(await w.Soorten.MaakAsync(jan.Id, "Dementie", null, false)).Succeeded, "een gewone gebruiker maakt geen soort"); Assert.True(!(await w.Soorten.OverzichtAsync(jan.Id)).Succeeded, "en ziet het beheeroverzicht niet"); Assert.True(!(await w.Soorten.WijzigAsync(jan.Id, 3, "Wachtwoord", null, false, 10, false)).Succeeded, "en zet geen soort uit"); var id = await MaakAsync(w, beheer, "Dementie"); Assert.True(id >= VaultCategoryDefinition.EersteEigenNummer, "een eigen soort begint bij 100"); Assert.True(!(await w.Soorten.VerwijderAsync(jan.Id, id)).Succeeded, "een gewone gebruiker verwijdert er geen"); }); runner.TestAsync("Soorten: een naam is verplicht en kan niet dubbel", async () => { var w = new World(); var beheer = await BeheerderAsync(w); Assert.True(!(await w.Soorten.MaakAsync(beheer.Id, " ", null, false)).Succeeded, "zonder naam kan het niet"); Assert.True(!(await w.Soorten.MaakAsync(beheer.Id, "polis", null, false)).Succeeded, "Polis bestaat al, ook in kleine letters"); await MaakAsync(w, beheer, "Dementie"); Assert.True(!(await w.Soorten.MaakAsync(beheer.Id, "DEMENTIE", null, false)).Succeeded, "een tweede Dementie kan niet"); }); runner.TestAsync("Soorten: een nieuwe soort staat meteen in de lijst van iedereen", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Niet reanimeren"); var lijst = await w.Soorten.ZichtbaarVoorAsync(jan.PersonId); Assert.True(lijst.Any(s => s.Id == id && s.Naam == "Niet reanimeren" && !s.Ingebouwd), "de nieuwe soort staat erbij"); Assert.True(lijst.Last().Naam == "Niet reanimeren", "hij staat onderaan"); }); runner.TestAsync("Soorten: het beheeroverzicht telt items en eigenaren, niet meer", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var piet = await w.MaakGebruikerAsync("piet@example.nl", "Piet"); var beheer = await BeheerderAsync(w); await w.Vault.CreateAsync(jan.Id, VaultCategory.Polis, "A", new VaultPayload()); await w.Vault.CreateAsync(jan.Id, VaultCategory.Polis, "B", new VaultPayload()); await w.Vault.CreateAsync(piet.Id, VaultCategory.Polis, "C", new VaultPayload()); var weg = (await w.Vault.CreateAsync(piet.Id, VaultCategory.Polis, "D", new VaultPayload())).Value!; await w.Vault.DeleteAsync(weg.Id, piet.Id); var overzicht = (await w.Soorten.OverzichtAsync(beheer.Id)).Value!; var polis = overzicht.Single(s => s.Naam == "Polis"); Assert.True(polis.Items == 3, "drie items: het verwijderde telt niet mee"); Assert.True(polis.Eigenaren == 2, "van twee mensen"); Assert.True(!polis.KanVerwijderen, "een ingebouwde soort in gebruik is niet te verwijderen"); Assert.True(overzicht.Single(s => s.Naam == "Paspoort").Items == 0, "wat niemand gebruikt staat op nul"); }); runner.TestAsync("Soorten: wat in gebruik is kan niet worden verwijderd, wat ongebruikt is wel", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var gebruikt = await MaakAsync(w, beheer, "Dementie"); var ongebruikt = await MaakAsync(w, beheer, "Proef"); var item = (await w.Vault.CreateAsync(jan.Id, (VaultCategory)gebruikt, "Mijn wens", new VaultPayload { Velden = new() })).Value!; Assert.True(item.Id != 0, "Jan maakt een item in de nieuwe soort"); var geweigerd = await w.Soorten.VerwijderAsync(beheer.Id, gebruikt); Assert.True(!geweigerd.Succeeded && geweigerd.Error!.Contains("niet-actief"), "een soort in gebruik wordt geweigerd, met de uitleg wat wel kan"); Assert.True(await w.Soorten.VindAsync(gebruikt) is not null, "hij staat er nog"); Assert.True((await w.Soorten.VerwijderAsync(beheer.Id, ongebruikt)).Succeeded, "een ongebruikte kan weg"); Assert.True(await w.Soorten.VindAsync(ongebruikt) is null, "en is weg"); Assert.True(!(await w.Soorten.VerwijderAsync(beheer.Id, 3)).Succeeded, "een ingebouwde soort verwijder je nooit, ook niet zonder items"); // En zodra het laatste item weg is, mag het weer. await w.Vault.DeleteAsync(item.Id, jan.Id); Assert.True((await w.Soorten.VerwijderAsync(beheer.Id, gebruikt)).Succeeded, "zonder items is hij weer te verwijderen"); }); runner.TestAsync("Soorten: niet-actief verdwijnt alleen bij wie hem nooit gebruikte", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var piet = await w.MaakGebruikerAsync("piet@example.nl", "Piet"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Dementie"); var item = (await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "Mijn wens", new VaultPayload { Velden = new() })).Value!; Assert.True((await w.Soorten.WijzigAsync(beheer.Id, id, "Dementie", null, false, 1000, false)).Succeeded, "de beheerder zet hem op niet-actief"); Assert.True((await w.Soorten.ZichtbaarVoorAsync(jan.PersonId)).Any(s => s.Id == id), "Jan heeft er een item van en blijft de soort zien"); Assert.True(!(await w.Soorten.ZichtbaarVoorAsync(piet.PersonId)).Any(s => s.Id == id), "Piet heeft hem nooit gebruikt en ziet hem niet meer"); Assert.True(!(await w.Vault.CreateAsync(piet.Id, (VaultCategory)id, "Nieuw", new VaultPayload { Velden = new() })).Succeeded, "Piet kan er ook geen nieuw item meer in maken"); var tweede = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "Nog een", new VaultPayload { Velden = new() }); Assert.True(tweede.Succeeded, "Jan kan er nog wel nieuwe items in maken: het is een soort die hij kent"); var wijzigen = await w.Vault.UpdateAsync(item.Id, jan.Id, (VaultCategory)id, "Mijn wens (nieuw)", new VaultPayload { Velden = new() }, ReleasePolicy.AlleenIkzelf); Assert.True(wijzigen.Succeeded, "en zijn bestaande item kan hij gewoon wijzigen"); Assert.True((await w.Vault.OpenAsync(item.Id, jan.Id)).Succeeded, "en openen"); // Weer aanzetten: iedereen ziet hem weer. await w.Soorten.WijzigAsync(beheer.Id, id, "Dementie", null, true, 1000, false); Assert.True((await w.Soorten.ZichtbaarVoorAsync(piet.PersonId)).Any(s => s.Id == id), "na weer aanzetten ziet Piet hem weer"); }); runner.TestAsync("Soorten: ook een ingebouwde soort kan op niet-actief, met dezelfde regel", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var piet = await w.MaakGebruikerAsync("piet@example.nl", "Piet"); var beheer = await BeheerderAsync(w); await w.Vault.CreateAsync(jan.Id, VaultCategory.Paspoort, "Mijn paspoort", new VaultPayload()); await w.Soorten.WijzigAsync(beheer.Id, (int)VaultCategory.Paspoort, "Paspoort", null, false, 90, false); Assert.True((await w.Soorten.ZichtbaarVoorAsync(jan.PersonId)).Any(s => s.Naam == "Paspoort"), "Jan houdt Paspoort"); Assert.True(!(await w.Soorten.ZichtbaarVoorAsync(piet.PersonId)).Any(s => s.Naam == "Paspoort"), "Piet ziet het niet meer"); }); runner.TestAsync("Soorten: Bespreken met is een instelling per soort", async () => { var w = new World(); var opa = await w.MaakGebruikerAsync("opa@example.nl", "Klaas", "de Vries"); var zoon = await w.MaakFamilielidAsync(opa, "Peter", "de Vries", "zoon@example.nl"); await w.BeheerderAsync(opa, zoon); var beheer = await BeheerderAsync(w); // Standaard: een uitvaartwens kan het, een polis niet - zoals voorheen. var wens = (await w.Vault.CreateAsync(opa.Id, VaultCategory.Uitvaartwens, "Uitvaart", new VaultPayload(), ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; Assert.True((await w.Vault.OpenAsync(wens.Id, zoon.Id)).Succeeded, "de gekozen beheerder leest de uitvaartwens mee"); var polis = (await w.Vault.CreateAsync(opa.Id, VaultCategory.Polis, "Polis", new VaultPayload(), ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; Assert.True(polis.SharedManagerPersonId is null, "bij een polis wordt de keuze genegeerd"); Assert.True(!(await w.Vault.OpenAsync(polis.Id, zoon.Id)).Succeeded, "en de beheerder ziet hem niet"); // De beheerder zet het bij Polis aan: nu werkt het ook daar. await w.Soorten.WijzigAsync(beheer.Id, (int)VaultCategory.Polis, "Polis", null, true, 50, true); var polis2 = (await w.Vault.CreateAsync(opa.Id, VaultCategory.Polis, "Polis 2", new VaultPayload(), ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; Assert.True(polis2.SharedManagerPersonId == zoon.PersonId, "bij Polis wordt de keuze nu bewaard"); Assert.True((await w.Vault.OpenAsync(polis2.Id, zoon.Id)).Succeeded, "en de beheerder leest hem mee"); // En bij Uitvaartwens uit: dan niet meer. await w.Soorten.WijzigAsync(beheer.Id, (int)VaultCategory.Uitvaartwens, "Uitvaartwens", null, true, 60, false); var wens2 = (await w.Vault.CreateAsync(opa.Id, VaultCategory.Uitvaartwens, "Uitvaart 2", new VaultPayload(), ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; Assert.True(wens2.SharedManagerPersonId is null, "met de schakelaar uit wordt de keuze genegeerd"); }); runner.TestAsync("Soorten: Bespreken met werkt ook bij een soort die de beheerder zelf maakte", async () => { var w = new World(); var opa = await w.MaakGebruikerAsync("opa@example.nl", "Klaas", "de Vries"); var zoon = await w.MaakFamilielidAsync(opa, "Peter", "de Vries", "zoon@example.nl"); await w.BeheerderAsync(opa, zoon); var beheer = await BeheerderAsync(w); var met = await MaakAsync(w, beheer, "Niet reanimeren", bespreken: true); var zonder = await MaakAsync(w, beheer, "Dementie", bespreken: false); var a = (await w.Vault.CreateAsync(opa.Id, (VaultCategory)met, "NR", new VaultPayload { Velden = new() }, ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; var b = (await w.Vault.CreateAsync(opa.Id, (VaultCategory)zonder, "DM", new VaultPayload { Velden = new() }, ReleasePolicy.AlleenIkzelf, null, zoon.PersonId)).Value!; Assert.True((await w.Vault.OpenAsync(a.Id, zoon.Id)).Succeeded, "met de schakelaar aan leest hij mee"); Assert.True(!(await w.Vault.OpenAsync(b.Id, zoon.Id)).Succeeded, "met de schakelaar uit niet"); }); runner.TestAsync("Soorten: een soort die niet bestaat is geen soort", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var r = await w.Vault.CreateAsync(jan.Id, (VaultCategory)4242, "Onzin", new VaultPayload()); Assert.True(!r.Succeeded, "een onbekend soortnummer wordt geweigerd"); }); runner.TestAsync("Soorten: de sleutel van een veld komt uit het label en is uniek", () => { Assert.True(VaultCategoryService.NieuweSleutel("Wil je gereanimeerd worden?", Array.Empty()) == "wil_je_gereanimeerd_worden", "een vraag wordt een leesbare sleutel"); Assert.True(VaultCategoryService.NieuweSleutel("Café — één", Array.Empty()) == "cafe_een", "accenten en streepjes verdwijnen"); Assert.True(VaultCategoryService.NieuweSleutel("???", Array.Empty()) == "veld", "zonder bruikbare tekens blijft 'veld' over"); Assert.True(VaultCategoryService.NieuweSleutel("Arts", new[] { "arts" }) == "arts_2", "een bestaande sleutel krijgt een nummer"); Assert.True(VaultCategoryService.NieuweSleutel(new string('x', 80), Array.Empty()).Length <= 30, "en een lang label wordt bijgesneden"); return Task.CompletedTask; }); runner.TestAsync("Velden: een eigen soort bewaart zijn velden versleuteld en geeft ze terug", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Niet reanimeren"); Assert.True((await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Wil je gereanimeerd worden?", VeldSoort.Keuze, "Ja\nNee\nAlleen na overleg", null, true)).Succeeded, "keuzeveld toevoegen"); Assert.True((await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Datum verklaring", VeldSoort.Datum, null, null, false)).Succeeded, "datumveld toevoegen"); Assert.True((await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Toelichting voor de arts", VeldSoort.Lang, null, "Zo precies mogelijk.", false)).Succeeded, "lang veld toevoegen"); var soort = (await w.Soorten.ZichtbaarVoorAsync(jan.PersonId)).Single(s => s.Id == id); Assert.True(soort.Velden.Select(v => v.Sleutel).SequenceEqual( new[] { "wil_je_gereanimeerd_worden", "datum_verklaring", "toelichting_voor_de_arts" }), "de velden staan in de volgorde van toevoegen"); Assert.True(soort.Velden[0].Opties.SequenceEqual(new[] { "Ja", "Nee", "Alleen na overleg" }), "de opties kloppen"); var item = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "Mijn verklaring", new VaultPayload { Velden = new() { ["wil_je_gereanimeerd_worden"] = "Nee", ["datum_verklaring"] = "2026-10-12", ["onbekend_veld"] = "hoort er niet" } }); Assert.True(item.Succeeded, "het item wordt bewaard"); var open = (await w.Vault.OpenAsync(item.Value!.Id, jan.Id)).Value!; Assert.True(open.Velden is not null && open.Velden["wil_je_gereanimeerd_worden"] == "Nee", "de waarde komt terug"); Assert.True(open.Velden!["datum_verklaring"] == "2026-10-12", "ook de datum"); Assert.True(!open.Velden.ContainsKey("onbekend_veld"), "een veld dat niet bestaat wordt weggelaten"); // En het staat echt versleuteld in de opslag, niet leesbaar. var opgeslagen = w.Store.VaultItems.Single(v => v.Id == item.Value.Id); Assert.True(!System.Text.Encoding.UTF8.GetString(opgeslagen.Ciphertext).Contains("Nee"), "in de opslag staat niets leesbaars"); }); runner.TestAsync("Velden: verplicht, datum en lengte worden op de server gecontroleerd", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Niet reanimeren"); await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Keuze", VeldSoort.Keuze, "Ja\nNee", null, true); await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Datum", VeldSoort.Datum, null, null, false); var leeg = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "X", new VaultPayload { Velden = new() }); Assert.True(!leeg.Succeeded && leeg.Error!.Contains("Keuze"), "een leeg verplicht veld wordt geweigerd, met de naam erbij"); var slechteDatum = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "X", new VaultPayload { Velden = new() { ["keuze"] = "Ja", ["datum"] = "morgen" } }); Assert.True(!slechteDatum.Succeeded && slechteDatum.Error!.Contains("datum"), "een datum die geen datum is wordt geweigerd"); var teLang = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "X", new VaultPayload { Velden = new() { ["keuze"] = new string('a', VaultCategoryService.MaxWaardelengte + 1) } }); Assert.True(!teLang.Succeeded, "een te lange waarde wordt geweigerd"); var goed = await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "X", new VaultPayload { Velden = new() { ["keuze"] = "Ja", ["datum"] = "2026-02-28" } }); Assert.True(goed.Succeeded, "met alles goed ingevuld lukt het"); }); runner.TestAsync("Velden: een app die de soort niet kent kan geen gegevens overschrijven met niets", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Dementie"); await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Wens", VeldSoort.Lang, null, null, false); var item = (await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "Mijn wens", new VaultPayload { Velden = new() { ["wens"] = "Thuis blijven wonen." } })).Value!; // Een oudere app stuurt de inhoud zonder het onderdeel Velden mee. var oud = await w.Vault.UpdateAsync(item.Id, jan.Id, (VaultCategory)id, "Mijn wens", new VaultPayload { Notes = "alleen een notitie" }, ReleasePolicy.AlleenIkzelf); Assert.True(!oud.Succeeded && oud.Error!.Contains("app"), "het wijzigen wordt geweigerd met het advies de app bij te werken"); var open = (await w.Vault.OpenAsync(item.Id, jan.Id)).Value!; Assert.True(open.Velden!["wens"] == "Thuis blijven wonen.", "wat er stond is niet overschreven"); }); runner.TestAsync("Velden: een ingebouwde soort bewaart geen eigen velden", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var item = (await w.Vault.CreateAsync(jan.Id, VaultCategory.Polis, "Polis", new VaultPayload { Insurer = "Zilveren Kruis", Velden = new() { ["iets"] = "weg ermee" } })).Value!; var open = (await w.Vault.OpenAsync(item.Id, jan.Id)).Value!; Assert.True(open.Velden is null, "bij een ingebouwde soort wordt Velden leeggemaakt"); Assert.True(open.Insurer == "Zilveren Kruis", "de eigen velden van de soort blijven gewoon"); }); runner.TestAsync("Velden: ingebouwde soorten hebben geen velden om te wijzigen", async () => { var w = new World(); var beheer = await BeheerderAsync(w); var r = await w.Soorten.VeldToevoegenAsync(beheer.Id, (int)VaultCategory.Polis, "Extra", VeldSoort.Tekst, null, null, false); Assert.True(!r.Succeeded, "een veld toevoegen aan een ingebouwde soort kan niet"); }); runner.TestAsync("Velden: een veld met ingevulde gegevens wordt niet verwijderd maar niet-actief", async () => { var w = new World(); var jan = await w.MaakGebruikerAsync("jan@example.nl", "Jan"); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Dementie"); await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Wens", VeldSoort.Lang, null, null, false); await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Arts", VeldSoort.Tekst, null, null, false); var velden = (await w.Soorten.OverzichtAsync(beheer.Id)).Value!.Single(s => s.Id == id).Velden; var wens = velden.Single(v => v.Sleutel == "wens"); var arts = velden.Single(v => v.Sleutel == "arts"); // Zonder items mag een veld gewoon weg. Assert.True((await w.Soorten.VeldVerwijderenAsync(beheer.Id, arts.Id)).Succeeded, "zonder items kan een veld weg"); await w.Vault.CreateAsync(jan.Id, (VaultCategory)id, "Mijn wens", new VaultPayload { Velden = new() { ["wens"] = "Thuis blijven wonen." } }); var geweigerd = await w.Soorten.VeldVerwijderenAsync(beheer.Id, wens.Id); Assert.True(!geweigerd.Succeeded && geweigerd.Error!.Contains("niet-actief"), "met items erbij wordt verwijderen geweigerd, met de uitleg"); // Niet-actief mag. De waarde blijft bewaard en bij het wijzigen nog bruikbaar. Assert.True((await w.Soorten.VeldWijzigenAsync(beheer.Id, wens.Id, "Wens", null, null, false, false, 10)).Succeeded, "op niet-actief zetten kan"); var item = w.Store.VaultItems.Single(v => v.Title == "Mijn wens"); var wijzig = await w.Vault.UpdateAsync(item.Id, jan.Id, (VaultCategory)id, "Mijn wens", new VaultPayload { Velden = new() { ["wens"] = "Thuis blijven wonen, met hulp." } }, ReleasePolicy.AlleenIkzelf); Assert.True(wijzig.Succeeded, "het item is nog te wijzigen"); var open = (await w.Vault.OpenAsync(item.Id, jan.Id)).Value!; Assert.True(open.Velden!["wens"] == "Thuis blijven wonen, met hulp.", "en de waarde van het niet-actieve veld blijft bewaard"); }); runner.TestAsync("Velden: een keuzelijst heeft minstens twee opties, een uitleg heeft tekst", async () => { var w = new World(); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Dementie"); Assert.True(!(await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Keuze", VeldSoort.Keuze, "Alleen deze", null, false)).Succeeded, "één optie is geen keuze"); Assert.True(!(await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Uitleg", VeldSoort.Uitleg, null, null, false)).Succeeded, "een uitleg zonder tekst kan niet"); Assert.True((await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Uitleg", VeldSoort.Uitleg, null, "Een papieren verklaring is leidend.", true)).Succeeded, "met tekst kan het wel"); var uitleg = (await w.Soorten.OverzichtAsync(beheer.Id)).Value!.Single(s => s.Id == id).Velden.Single(); Assert.True(!uitleg.Verplicht, "een uitlegtekst kan nooit verplicht zijn"); Assert.True(!(await w.Soorten.VeldToevoegenAsync(beheer.Id, id, "Raar", "zweef", null, null, false)).Succeeded, "een soort veld die we niet kennen wordt geweigerd"); }); runner.TestAsync("Soorten: wijzigingen door de beheerder staan in het logboek", async () => { var w = new World(); var beheer = await BeheerderAsync(w); var id = await MaakAsync(w, beheer, "Dementie"); await w.Soorten.WijzigAsync(beheer.Id, id, "Dementie", null, false, 1000, false); await w.Soorten.VerwijderAsync(beheer.Id, id); var regels = w.Store.Audit.Where(a => a.Action == AuditAction.KluisSoortBeheerd).ToList(); Assert.True(regels.Count == 3, "gemaakt, gewijzigd en verwijderd staan er alle drie in"); Assert.True(regels.All(a => a.UserId == beheer.Id), "met de beheerder erbij"); }); } }