using MijnBesluit.Application.Abstractions; using MijnBesluit.Application.Services; namespace MijnBesluit.SelfCheck; /// Alles wat één testscenario nodig heeft, klaargezet in het geheugen. public class World { public Store Store { get; } = new(); public TestClock Clock { get; } = new(); public TestEmail Email { get; } = new(); public TestPush Push { get; } = new(); /// Standaard uit; zet hem aan in een test die het verkleinen wil nakijken. public TestVerkleiner Verkleiner { get; } = new(); public AccountService Accounts { get; } public FamilyService Families { get; } public VaultService Vault { get; } public MessageService Messages { get; } public LegacyService Legacy { get; } public MeldingService Meldingen { get; } public OverzichtService Overzicht { get; } public SamenvoegService Samenvoegen { get; } public BeheerService Beheer { get; } public AdvertentieService Adverteren { get; } public AccountOpheffenService Opheffen { get; } /// Maakt in één stap een account aan; scheelt in de scenario's het hele codegedoe. public async Task MaakGebruikerAsync(string email, string voornaam, string achternaam = "") { var resultaat = await Accounts.MaakAccountAsync(email, voornaam, achternaam); if (!resultaat.Succeeded) throw new AssertionException($"account aanmaken mislukte: {resultaat.Error}"); return resultaat.Value!; } /// /// Maakt iemand met een echt account die ook écht in de familie van /// staat: toevoegen, uitnodigen, aannemen. Dat laatste is nodig omdat toevoegen alleen een /// aantekening maakt; pas door de uitnodiging aan te nemen wordt het profiel van hemzelf en /// staat hij in de kring van de eigenaar. /// /// Die kring bepaalt wie er iets mag zeggen over een overlijden, dus tests die dat nabootsen /// moeten hem ook echt opbouwen. /// public async Task MaakFamilielidAsync( MijnBesluit.Domain.Entities.User eigenaar, string voornaam, string achternaam, string email, MijnBesluit.Domain.Enums.RelationType relatie = MijnBesluit.Domain.Enums.RelationType.Kind) { var familie = Store.Families.Single(f => f.OwnerPersonId == eigenaar.PersonId); var profiel = await Families.AddMemberAsync(familie.Id, eigenaar.Id, voornaam, achternaam, email, relatie); if (!profiel.Succeeded) throw new AssertionException($"toevoegen mislukte: {profiel.Error}"); var token = await Families.InviteAsync(familie.Id, profiel.Value!.Id, eigenaar.Id); if (!token.Succeeded) throw new AssertionException($"uitnodigen mislukte: {token.Error}"); var account = await Families.AcceptInvitationAsync(token.Value!, Accounts); if (!account.Succeeded) throw new AssertionException($"aannemen mislukte: {account.Error}"); return account.Value!; } /// /// Wijst een of meer mensen aan als nalatenschapsbeheerder van . /// /// Nodig in elke test die een overlijden meldt: alleen wie is aangewezen mag dat. Ze moeten /// ook echt in zijn familie staan, dus gebruik hiervoor mensen uit MaakFamilielidAsync. /// public async Task BeheerderAsync(MijnBesluit.Domain.Entities.User betrokkene, params MijnBesluit.Domain.Entities.User[] beheerders) { var volgorde = 1; foreach (var beheerder in beheerders) { var r = await Legacy.AppointManagerAsync(betrokkene.Id, beheerder.PersonId, volgorde++); if (!r.Succeeded) throw new AssertionException($"aanwijzen mislukte: {r.Error}"); } } /// Haalt de code uit de laatst verstuurde e-mail, zoals een gebruiker hem uit zijn postvak haalt. public string LaatsteCodeUitMail(string email) { var mail = Email.Sent.Last(m => m.To == email); var match = System.Text.RegularExpressions.Regex.Match(mail.Body, @"letter-spacing:5px;margin:20px 0"">(\d+)<"); if (!match.Success) throw new AssertionException("geen code gevonden in de e-mail"); return match.Groups[1].Value; } public World() { var uow = new Uow(Store); var keys = new TestKeyProtector(); var files = new TestFiles(); var audit = new Audit(Store, Clock); var users = new UserRepo(Store); var people = new PersonRepo(Store); var families = new FamilyRepo(Store); var invitations = new InvitationRepo(Store); var vault = new VaultRepo(Store); var messages = new MessageRepo(Store); var legacy = new LegacyRepo(Store); var codes = new LoginCodeRepo(Store); Accounts = new AccountService(users, people, families, codes, keys, Email, audit, uow, Clock, vault); Families = new FamilyService(families, people, users, invitations, messages, legacy, Email, audit, uow, Clock); Vault = new VaultService(vault, people, messages, users, keys, files, audit, uow, Clock, Verkleiner, families, legacy); Meldingen = new MeldingService(new ToestelRepo(Store), users, Push, uow, Clock); Messages = new MessageService(messages, people, users, vault, keys, files, Email, audit, uow, Clock, Meldingen); Legacy = new LegacyService(legacy, people, users, vault, messages, Email, audit, uow, Clock, Vault, families); Overzicht = new OverzichtService(users, people, families, vault, messages, legacy, uow, Clock); Samenvoegen = new SamenvoegService(people, families, invitations, messages, vault, legacy, audit, uow, Clock, new SamenvoegRepo(Store)); Beheer = new BeheerService(users, people, legacy, audit, Clock, Legacy, Samenvoegen); Adverteren = new AdvertentieService(new AdvertentieRepo(Store), users, Email, audit, uow, Clock, Verkleiner); Opheffen = new AccountOpheffenService(users, people, families, invitations, vault, messages, legacy, codes, new ToestelRepo(Store), files, Email, audit, uow, Clock); } } public static class Assert { public static void True(bool condition, string what) { if (!condition) throw new AssertionException(what); } public static void Throws(Action action, string what) where TException : Exception { try { action(); } catch (TException) { return; } catch (Exception ex) { throw new AssertionException($"{what} (kreeg {ex.GetType().Name})"); } throw new AssertionException($"{what} (er werd geen fout gegooid)"); } } public class AssertionException : Exception { public AssertionException(string message) : base(message) { } } /// Draait de scenario's en vat de uitkomst samen. public class Runner { private int _passed, _failed; public void Test(string name, Action body) => Run(name, () => { body(); return Task.CompletedTask; }); public void TestAsync(string name, Func body) => Run(name, body); private void Run(string name, Func body) { try { body().GetAwaiter().GetResult(); _passed++; Console.WriteLine($" OK {name}"); } catch (AssertionException ex) { _failed++; Console.WriteLine($" FOUT {name}"); Console.WriteLine($" verwacht: {ex.Message}"); } catch (Exception ex) { _failed++; Console.WriteLine($" FOUT {name}"); Console.WriteLine($" {ex.GetType().Name}: {ex.Message}"); } } public int Summary() { Console.WriteLine(); Console.WriteLine(_failed == 0 ? $"Alle {_passed} controles geslaagd." : $"{_passed} geslaagd, {_failed} mislukt."); return _failed == 0 ? 0 : 1; } }