821 lines
45 KiB
C#
821 lines
45 KiB
C#
using System.Net;
|
|
using MijnBesluit.Client;
|
|
using MijnBesluit.Protocol;
|
|
using MijnBesluit.Server;
|
|
|
|
namespace MijnBesluit.SelfCheck;
|
|
|
|
/// <summary>
|
|
/// Controleert de laag waar de Android- en iOS-app op draait: MijnBesluitClient, over een echte
|
|
/// socketverbinding naar een echte dispatcher. Alleen de database is vervangen door geheugen.
|
|
///
|
|
/// Dit is bewust geen test met een nagebootste server: juist de vertaalslag van JSON naar de
|
|
/// modellen van de app is waar het misgaat, en die wordt hier echt gedaan.
|
|
/// </summary>
|
|
public static class ClientChecks
|
|
{
|
|
/// <summary>Een draaiende SocketServer met opslag in het geheugen, zoals de app hem ziet.</summary>
|
|
private sealed class Proef : IAsyncDisposable
|
|
{
|
|
public World Wereld { get; } = new();
|
|
public SocketListener Server { get; }
|
|
|
|
/// <summary>De sessies van de server, om een herstart mee na te bootsen.</summary>
|
|
public SessionStore Sessies { get; }
|
|
|
|
public Proef()
|
|
{
|
|
var sessies = Sessies = new SessionStore(Wereld.Clock);
|
|
var dispatcher = new SocketDispatcher(sessies, work => work(new RequestScope
|
|
{
|
|
Accounts = Wereld.Accounts,
|
|
Families = Wereld.Families,
|
|
Vault = Wereld.Vault,
|
|
Messages = Wereld.Messages,
|
|
Legacy = Wereld.Legacy,
|
|
Overzicht = Wereld.Overzicht,
|
|
Samenvoegen = Wereld.Samenvoegen
|
|
}), new Bestandsoverdracht(Wereld.Clock));
|
|
|
|
Server = new SocketListener(
|
|
new SocketListenerOptions { Address = IPAddress.Loopback, Port = 0 },
|
|
dispatcher.HandleAsync);
|
|
Server.Start();
|
|
}
|
|
|
|
public MijnBesluitClient App(ITokenopslag? opslag = null) =>
|
|
new("127.0.0.1", Server.Port, tls: false, opslag);
|
|
|
|
/// <summary>Registreert een verse gebruiker en geeft een aangemelde app terug.</summary>
|
|
public async Task<MijnBesluitClient> AangemeldeAppAsync(
|
|
string email, string voornaam = "Jan", string achternaam = "Jansen", ITokenopslag? opslag = null)
|
|
{
|
|
var app = App(opslag);
|
|
var aanvraag = await app.VraagRegistratiecodeAanAsync(email, voornaam, achternaam);
|
|
Assert.True(aanvraag.Gelukt, $"registratiecode aanvragen lukt ({aanvraag.Melding})");
|
|
|
|
var registratie = await app.RegistreerAsync(email, Wereld.LaatsteCodeUitMail(email));
|
|
Assert.True(registratie.Gelukt, $"registreren lukt ({registratie.Melding})");
|
|
return app;
|
|
}
|
|
|
|
public async ValueTask DisposeAsync() => await Server.DisposeAsync();
|
|
}
|
|
|
|
public static void Register(Runner runner)
|
|
{
|
|
runner.TestAsync("App: registreren met een code en de sessie bewaren", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
var opslag = new GeheugenTokenopslag();
|
|
await using var app = proef.App(opslag);
|
|
|
|
var aanvraag = await app.VraagRegistratiecodeAanAsync("jan@example.nl", "Jan", "Jansen");
|
|
Assert.True(aanvraag.Gelukt, "de code wordt verstuurd");
|
|
Assert.True(!aanvraag.Waarde!.VerstuurdNaar.Contains("jan@example.nl"),
|
|
"het volledige adres komt niet terug naar de app");
|
|
Assert.True(aanvraag.Waarde.GeldigTot > proef.Wereld.Clock.UtcNow,
|
|
"er komt een geldigheidsduur mee");
|
|
|
|
var registratie = await app.RegistreerAsync("jan@example.nl",
|
|
proef.Wereld.LaatsteCodeUitMail("jan@example.nl"));
|
|
Assert.True(registratie.Gelukt, "registreren lukt met de code uit de e-mail");
|
|
Assert.True(app.IsAangemeld, "de app is daarna aangemeld");
|
|
Assert.True(app.PersoonId > 0, "de app kent zijn eigen persoonId");
|
|
Assert.True(!string.IsNullOrEmpty(await opslag.LeesAsync()),
|
|
"het token is bewaard, zodat de app niet elke start opnieuw hoeft in te loggen");
|
|
});
|
|
|
|
runner.TestAsync("App: een verkeerde code geeft een melding, geen uitzondering", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await proef.Wereld.MaakGebruikerAsync("piet@example.nl", "Piet");
|
|
await using var app = proef.App();
|
|
|
|
Assert.True((await app.VraagInlogcodeAanAsync("piet@example.nl")).Gelukt, "de inlogcode wordt verstuurd");
|
|
|
|
var mis = await app.LogInAsync("piet@example.nl", "000000");
|
|
Assert.True(!mis.Gelukt, "een verkeerde code wordt geweigerd");
|
|
Assert.True(!string.IsNullOrWhiteSpace(mis.Melding), "er komt een melding mee die op het scherm kan");
|
|
Assert.True(!app.IsAangemeld, "de app is niet aangemeld");
|
|
|
|
var goed = await app.LogInAsync("piet@example.nl", proef.Wereld.LaatsteCodeUitMail("piet@example.nl"));
|
|
Assert.True(goed.Gelukt, "met de juiste code lukt het wel");
|
|
});
|
|
|
|
runner.TestAsync("App: de eigen familie komt binnen via family.list", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var families = await app.FamiliesAsync();
|
|
Assert.True(families.Gelukt, $"de familielijst komt terug ({families.Melding})");
|
|
Assert.True(families.Waarde!.Count == 1, "een nieuwe gebruiker heeft precies één familie");
|
|
Assert.True(families.Waarde[0].Eigenaar, "en daar is hij eigenaar van");
|
|
Assert.True(!string.IsNullOrWhiteSpace(families.Waarde[0].Name), "de familie heeft een naam");
|
|
|
|
var leden = await app.FamilieledenAsync(families.Waarde[0].Id);
|
|
Assert.True(leden.Gelukt, $"de leden komen terug ({leden.Melding})");
|
|
var ikzelf = leden.Waarde!.Single(l => l.PersonId == app.PersoonId);
|
|
Assert.True(ikzelf.State == ProfielStand.Geclaimd, "het eigen profiel staat als geclaimd");
|
|
Assert.True(ikzelf.CanEdit, "en is te bewerken");
|
|
});
|
|
|
|
runner.TestAsync("App: familielid toevoegen en uitnodigen", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
|
|
var toegevoegd = await app.VoegFamilielidToeAsync(familieId, "Marie", "Jansen",
|
|
"marie@example.nl", relatie: 1);
|
|
Assert.True(toegevoegd.Gelukt, $"een partner toevoegen lukt ({toegevoegd.Melding})");
|
|
var marieId = toegevoegd.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var leden = await app.FamilieledenAsync(familieId);
|
|
var marie = leden.Waarde!.Single(l => l.PersonId == marieId);
|
|
Assert.True(marie.State == ProfielStand.Beheerd, "het profiel is nog van de aanmaker");
|
|
Assert.True(marie.CanEdit, "en hij mag het dus wijzigen");
|
|
Assert.True(!marie.IsGeclaimd, "het is nog niet geclaimd");
|
|
|
|
var uitnodiging = await app.NodigUitAsync(familieId, marieId);
|
|
Assert.True(uitnodiging.Gelukt, $"uitnodigen lukt ({uitnodiging.Melding})");
|
|
|
|
var naUitnodiging = await app.FamilieledenAsync(familieId);
|
|
Assert.True(naUitnodiging.Waarde!.Single(l => l.PersonId == marieId).State == ProfielStand.Uitgenodigd,
|
|
"de stand staat daarna op uitgenodigd");
|
|
});
|
|
|
|
runner.TestAsync("App: een familielid wijzigen, ook na een uitnodiging", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
|
|
// Zoals het in het echt gaat: een tikfout in het adres.
|
|
var toegevoegd = await app.VoegFamilielidToeAsync(familieId, "Jarron", "Flietstra",
|
|
"jarron@gmial.com", relatie: 2);
|
|
var jarronId = toegevoegd.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var gewijzigd = await app.WijzigFamilielidAsync(familieId, jarronId, "Jarron", "Flietstra",
|
|
"jarron@gmail.com", relatie: 11);
|
|
Assert.True(gewijzigd.Gelukt, $"wijzigen lukt ({gewijzigd.Melding})");
|
|
|
|
var leden = await app.FamilieledenAsync(familieId);
|
|
var jarron = leden.Waarde!.Single(l => l.PersonId == jarronId);
|
|
Assert.True(jarron.Email == "jarron@gmail.com", "het gecorrigeerde adres komt terug");
|
|
Assert.True(jarron.Relation == 11, "en de relatie staat nu op zoon");
|
|
Assert.True(jarron.FirstName == "Jarron", "de voornaam komt mee, zodat het scherm in te vullen is");
|
|
|
|
var bezet = await app.WijzigFamilielidAsync(familieId, jarronId, "Jarron", "Flietstra",
|
|
"jan@example.nl", relatie: 11);
|
|
Assert.True(!bezet.Gelukt, "het adres van een bestaand profiel wordt geweigerd");
|
|
});
|
|
|
|
runner.TestAsync("App: kluisitem opslaan, terugzien en openen", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var opslaan = await app.KluisOpslaanAsync(
|
|
categorie: 3, titel: "Bank",
|
|
inhoud: new KluisInhoud { Website = "bank.nl", Username = "jan", Secret = "zeergeheim" },
|
|
vrijgave: 1);
|
|
Assert.True(opslaan.Gelukt, $"opslaan lukt ({opslaan.Melding})");
|
|
var itemId = opslaan.Waarde.GetProperty("itemId").GetInt64();
|
|
|
|
var lijst = await app.KluisAsync();
|
|
Assert.True(lijst.Gelukt, $"de kluislijst komt terug ({lijst.Melding})");
|
|
Assert.True(lijst.Waarde!.Single().Title == "Bank", "met de titel erbij");
|
|
Assert.True(lijst.Waarde!.Single().Category == 3, "en de categorie");
|
|
|
|
var geopend = await app.KluisOpenenAsync(itemId);
|
|
Assert.True(geopend.Gelukt, $"openen lukt ({geopend.Melding})");
|
|
Assert.True(geopend.Waarde!.Secret == "zeergeheim", "het geheim komt ongeschonden terug");
|
|
Assert.True(geopend.Waarde.Website == "bank.nl", "en de rest van de inhoud ook");
|
|
|
|
var alleenPolissen = await app.KluisAsync(categorie: 2);
|
|
Assert.True(alleenPolissen.Waarde!.Count == 0, "filteren op categorie werkt");
|
|
});
|
|
|
|
runner.TestAsync("App: kluisitem wijzigen en verwijderen over de socket", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var opslaan = await app.KluisOpslaanAsync(3, "Bank",
|
|
new KluisInhoud { Website = "bank.nl", Secret = "eerstegeheim" }, vrijgave: 1);
|
|
var itemId = opslaan.Waarde.GetProperty("itemId").GetInt64();
|
|
|
|
var gewijzigd = await app.KluisWijzigenAsync(itemId, 3, "Bank en sparen",
|
|
new KluisInhoud { Website = "bank.nl", Secret = "tweedegeheim" }, vrijgave: 1);
|
|
Assert.True(gewijzigd.Gelukt, $"wijzigen lukt ({gewijzigd.Melding})");
|
|
|
|
var geopend = await app.KluisOpenenAsync(itemId);
|
|
Assert.True(geopend.Waarde!.Secret == "tweedegeheim", "de nieuwe inhoud komt terug");
|
|
Assert.True((await app.KluisAsync()).Waarde!.Single().Title == "Bank en sparen", "en de nieuwe titel");
|
|
|
|
var verwijderd = await app.KluisVerwijderenAsync(itemId);
|
|
Assert.True(verwijderd.Gelukt, $"verwijderen lukt ({verwijderd.Melding})");
|
|
Assert.True((await app.KluisAsync()).Waarde!.Count == 0, "de kluis is weer leeg");
|
|
Assert.True(!(await app.KluisOpenenAsync(itemId)).Gelukt, "het item is niet meer te openen");
|
|
});
|
|
|
|
runner.TestAsync("App: bericht wijzigen en terugtrekken over de socket", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await app.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", null, relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var klaargezet = await app.BerichtKlaarzettenAsync(evaId, "Voor jou", "Eerste versie", null, true);
|
|
var berichtId = klaargezet.Waarde.GetProperty("berichtId").GetInt64();
|
|
|
|
var gewijzigd = await app.BerichtWijzigenAsync(berichtId, "Voor jou, Eva", "Tweede versie", null, true);
|
|
Assert.True(gewijzigd.Gelukt, $"wijzigen lukt ({gewijzigd.Melding})");
|
|
|
|
var uitgaand = await app.UitgaandAsync();
|
|
Assert.True(uitgaand.Waarde!.Single().Subject == "Voor jou, Eva", "het nieuwe onderwerp staat er");
|
|
|
|
var tekst = await app.BerichtConceptAsync(berichtId);
|
|
Assert.True(tekst.Gelukt, $"je eigen concept is terug te lezen ({tekst.Melding})");
|
|
Assert.True(tekst.Waarde == "Tweede versie", "en de nieuwe tekst staat erin");
|
|
|
|
Assert.True(!(await app.BerichtLezenAsync(berichtId)).Gelukt,
|
|
"lezen als ontvanger kan niet: het bericht is niet voor mij en nog niet bezorgd");
|
|
|
|
var ingetrokken = await app.BerichtIntrekkenAsync(berichtId);
|
|
Assert.True(ingetrokken.Gelukt, $"terugtrekken lukt ({ingetrokken.Melding})");
|
|
Assert.True((await app.UitgaandAsync()).Waarde!.Count == 0, "het staat niet meer in uitgaande post");
|
|
});
|
|
|
|
runner.TestAsync("App: familielid verwijderen over de socket", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await app.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", "eva@example.nl", relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
Assert.True((await app.FamilieledenAsync(familieId)).Waarde!.Any(l => l.PersonId == evaId),
|
|
"Eva staat erin");
|
|
|
|
var weg = await app.VerwijderFamilielidAsync(familieId, evaId);
|
|
Assert.True(weg.Gelukt, $"verwijderen lukt ({weg.Melding})");
|
|
Assert.True((await app.FamilieledenAsync(familieId)).Waarde!.All(l => l.PersonId != evaId),
|
|
"en daarna staat ze er niet meer in");
|
|
|
|
var zichzelf = await app.VerwijderFamilielidAsync(familieId, app.PersoonId);
|
|
Assert.True(!zichzelf.Gelukt, "jezelf verwijderen kan niet");
|
|
});
|
|
|
|
runner.TestAsync("App: een bijlage in stukken versturen en weer ophalen", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var itemId = (await app.KluisOpslaanAsync(2, "Uitvaartverzekering",
|
|
new KluisInhoud { Insurer = "Verzekeraar" }, vrijgave: 1)).Waarde.GetProperty("itemId").GetInt64();
|
|
|
|
// Ruim groter dan één stuk, zodat het opknippen echt gebeurt: 1,3 MB.
|
|
var inhoud = new byte[1_300_000];
|
|
Random.Shared.NextBytes(inhoud);
|
|
|
|
var voortgang = new List<long>();
|
|
var verstuurd = await app.BestandVersturenAsync("polis.pdf", "application/pdf", inhoud, itemId,
|
|
(gedaan, _) => voortgang.Add(gedaan));
|
|
Assert.True(verstuurd.Gelukt, $"versturen lukt ({verstuurd.Melding})");
|
|
Assert.True(voortgang.Count >= 3, $"het ging in stukken ({voortgang.Count} stuks)");
|
|
Assert.True(voortgang[^1] == inhoud.LongLength, "de voortgang eindigt op de volledige grootte");
|
|
|
|
var lijst = await app.BijlagenAsync(itemId);
|
|
Assert.True(lijst.Gelukt, $"de bijlagen komen terug ({lijst.Melding})");
|
|
var bijlage = lijst.Waarde!.Single();
|
|
Assert.True(bijlage.FileName == "polis.pdf", "met de juiste naam");
|
|
Assert.True(bijlage.SizeBytes == inhoud.LongLength, "en de juiste grootte");
|
|
Assert.True(bijlage.Grootte == "1,2 MB" || bijlage.Grootte.EndsWith("MB"), "leesbaar getoond");
|
|
|
|
var terug = await app.BestandOphalenAsync(verstuurd.Waarde);
|
|
Assert.True(terug.Gelukt, $"ophalen lukt ({terug.Melding})");
|
|
Assert.True(terug.Waarde!.Inhoud.SequenceEqual(inhoud), "byte voor byte hetzelfde als wat erin ging");
|
|
Assert.True(terug.Waarde.Soort == "application/pdf", "en het soort klopt");
|
|
|
|
var weg = await app.BijlageVerwijderenAsync(bijlage.Id);
|
|
Assert.True(weg.Gelukt, $"verwijderen lukt ({weg.Melding})");
|
|
Assert.True((await app.BijlagenAsync(itemId)).Waarde!.Count == 0, "de bijlage is weg");
|
|
Assert.True(!(await app.BestandOphalenAsync(bijlage.Id)).Gelukt, "en niet meer op te halen");
|
|
});
|
|
|
|
runner.TestAsync("App: een bijlage van iemand anders is niet te bereiken", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var jan = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var itemId = (await jan.KluisOpslaanAsync(3, "Bank", new KluisInhoud { Secret = "geheim" }, 1))
|
|
.Waarde.GetProperty("itemId").GetInt64();
|
|
var bestandId = (await jan.BestandVersturenAsync("geheim.txt", "text/plain",
|
|
System.Text.Encoding.UTF8.GetBytes("staat hier iets geheims"), itemId)).Waarde;
|
|
|
|
await using var piet = await proef.AangemeldeAppAsync("piet@example.nl", "Piet", "Pietersen");
|
|
|
|
Assert.True(!(await piet.BestandOphalenAsync(bestandId)).Gelukt, "Piet kan het bestand niet openen");
|
|
Assert.True(!(await piet.BijlagenAsync(itemId)).Gelukt, "en ziet de bijlagenlijst niet");
|
|
Assert.True(!(await piet.BijlageVerwijderenAsync(bestandId)).Gelukt, "en kan het niet verwijderen");
|
|
|
|
// Het bestand is er voor Jan nog gewoon.
|
|
Assert.True((await jan.BestandOphalenAsync(bestandId)).Gelukt, "voor Jan werkt het wel");
|
|
});
|
|
|
|
runner.TestAsync("App: je eigen profiel lezen en wijzigen", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var profiel = await app.EigenProfielAsync();
|
|
Assert.True(profiel.Gelukt, $"je eigen profiel komt terug ({profiel.Melding})");
|
|
Assert.True(profiel.Waarde!.Email == "jan@example.nl", "met je inlogadres erbij");
|
|
Assert.True(profiel.Waarde.PersoonId == app.PersoonId, "en het is jouw persoon");
|
|
Assert.True(profiel.Waarde.Geboortedatum is null, "nog zonder geboortedatum");
|
|
|
|
var opgeslagen = await app.EigenProfielOpslaanAsync("Johannes", "Jansen",
|
|
new DateOnly(1967, 3, 12));
|
|
Assert.True(opgeslagen.Gelukt, $"wijzigen lukt ({opgeslagen.Melding})");
|
|
|
|
profiel = await app.EigenProfielAsync();
|
|
Assert.True(profiel.Waarde!.Voornaam == "Johannes", "de nieuwe voornaam staat er");
|
|
Assert.True(profiel.Waarde.Geboortedatum == new DateOnly(1967, 3, 12), "en de geboortedatum");
|
|
Assert.True(profiel.Waarde.Naam == "Johannes Jansen", "de volledige naam klopt");
|
|
|
|
var leeg = await app.EigenProfielOpslaanAsync("", "", null);
|
|
Assert.True(!leeg.Gelukt, "zonder naam gaat het niet");
|
|
|
|
var toekomst = await app.EigenProfielOpslaanAsync(
|
|
"Jan", "Jansen", DateOnly.FromDateTime(proef.Wereld.Clock.UtcNow.AddYears(1).Date));
|
|
Assert.True(!toekomst.Gelukt, "en een geboortedatum in de toekomst ook niet");
|
|
});
|
|
|
|
runner.TestAsync("App: je e-mailadres wijzigen gaat via een code naar het nieuwe adres", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var gevraagd = await app.AdreswijzigingAanvragenAsync("jan@kwik-bit.nl");
|
|
Assert.True(gevraagd.Gelukt, $"de code wordt aangevraagd ({gevraagd.Melding})");
|
|
Assert.True(!gevraagd.Waarde!.VerstuurdNaar.Contains("jan@kwik-bit.nl"),
|
|
"het volledige adres komt niet terug naar de app");
|
|
|
|
// Zolang de code niet is ingevuld verandert er niets: dat is de hele bedoeling.
|
|
Assert.True((await app.EigenProfielAsync()).Waarde!.Email == "jan@example.nl",
|
|
"het oude adres geldt nog");
|
|
|
|
var mis = await app.AdreswijzigingBevestigenAsync("jan@kwik-bit.nl", "000000");
|
|
Assert.True(!mis.Gelukt, "een verkeerde code wordt geweigerd");
|
|
Assert.True((await app.EigenProfielAsync()).Waarde!.Email == "jan@example.nl",
|
|
"en ook dan verandert er niets");
|
|
|
|
var code = proef.Wereld.LaatsteCodeUitMail("jan@kwik-bit.nl");
|
|
var goed = await app.AdreswijzigingBevestigenAsync("jan@kwik-bit.nl", code);
|
|
Assert.True(goed.Gelukt, $"met de juiste code lukt het wel ({goed.Melding})");
|
|
Assert.True((await app.EigenProfielAsync()).Waarde!.Email == "jan@kwik-bit.nl",
|
|
"en nu staat het nieuwe adres er");
|
|
|
|
// Inloggen gaat vanaf nu op het nieuwe adres, en niet meer op het oude.
|
|
await using var opnieuw = proef.App();
|
|
Assert.True(!(await opnieuw.VraagInlogcodeAanAsync("jan@example.nl")).Gelukt,
|
|
"het oude adres kent de server niet meer");
|
|
Assert.True((await opnieuw.VraagInlogcodeAanAsync("jan@kwik-bit.nl")).Gelukt,
|
|
"en op het nieuwe adres kun je een code aanvragen");
|
|
});
|
|
|
|
runner.TestAsync("App: een e-mailadres dat al bezet is wordt geweigerd", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var jan = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
await using var piet = await proef.AangemeldeAppAsync("piet@example.nl", "Piet", "Pietersen");
|
|
|
|
var bezet = await jan.AdreswijzigingAanvragenAsync("piet@example.nl");
|
|
Assert.True(!bezet.Gelukt, "het adres van Piet is niet over te nemen");
|
|
|
|
var zelfde = await jan.AdreswijzigingAanvragenAsync("jan@example.nl");
|
|
Assert.True(!zelfde.Gelukt, "en je eigen adres opnieuw instellen heeft geen zin");
|
|
});
|
|
|
|
runner.TestAsync("App: foto's bij een persoon, met een profielfoto erbij", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await app.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", null, relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var eerste = await app.BestandVersturenAsync("eva.jpg", "image/jpeg",
|
|
System.Text.Encoding.UTF8.GetBytes("doet alsof het een foto is"),
|
|
persoonId: evaId);
|
|
Assert.True(eerste.Gelukt, $"een foto bij Eva opslaan lukt ({eerste.Melding})");
|
|
|
|
var tweede = await app.BestandVersturenAsync("eva-2.jpg", "image/jpeg",
|
|
System.Text.Encoding.UTF8.GetBytes("en dit is de tweede"),
|
|
persoonId: evaId);
|
|
Assert.True(tweede.Gelukt, $"en een tweede ook ({tweede.Melding})");
|
|
|
|
var fotos = await app.PersoonsfotosAsync(evaId);
|
|
Assert.True(fotos.Gelukt, $"de foto's komen terug ({fotos.Melding})");
|
|
Assert.True(fotos.Waarde!.Count == 2, "allebei");
|
|
Assert.True(fotos.Waarde.All(f => !f.IsProfilePhoto), "nog geen van beide is profielfoto");
|
|
|
|
Assert.True((await app.ProfielfotoAsync(eerste.Waarde)).Gelukt, "de eerste aanwijzen lukt");
|
|
fotos = await app.PersoonsfotosAsync(evaId);
|
|
Assert.True(fotos.Waarde!.Single(f => f.Id == eerste.Waarde).IsProfilePhoto, "die is het nu");
|
|
|
|
// Een andere aanwijzen laat de vorige los: er kan er maar één zijn.
|
|
Assert.True((await app.ProfielfotoAsync(tweede.Waarde)).Gelukt, "de tweede aanwijzen lukt ook");
|
|
fotos = await app.PersoonsfotosAsync(evaId);
|
|
Assert.True(fotos.Waarde!.Count(f => f.IsProfilePhoto) == 1, "er is er precies één profielfoto");
|
|
Assert.True(fotos.Waarde.Single(f => f.Id == tweede.Waarde).IsProfilePhoto, "en dat is de tweede");
|
|
|
|
// De bijlagen bij Eva horen niet in de lijst van een kluisitem thuis en andersom.
|
|
var itemId = (await app.KluisOpslaanAsync(3, "Bank", new KluisInhoud { Secret = "x" }, 1))
|
|
.Waarde.GetProperty("itemId").GetInt64();
|
|
Assert.True((await app.BijlagenAsync(itemId)).Waarde!.Count == 0,
|
|
"het kluisitem heeft zijn eigen, lege lijst");
|
|
});
|
|
|
|
runner.TestAsync("App: de profielfoto komt mee in de lijst met mensen", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await app.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", null, relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
Familielid Eva() => app.FamilieledenAsync(familieId).GetAwaiter().GetResult()
|
|
.Waarde!.Single(l => l.PersonId == evaId);
|
|
|
|
Assert.True(Eva().ProfielfotoId is null, "zonder foto komt er niets mee");
|
|
Assert.True(Eva().Profielfotobron is null, "en is er niets te tonen");
|
|
|
|
var foto = await app.BestandVersturenAsync("eva.jpg", "image/jpeg",
|
|
System.Text.Encoding.UTF8.GetBytes("doet alsof het een foto is"),
|
|
persoonId: evaId);
|
|
Assert.True(foto.Gelukt, $"een foto opslaan lukt ({foto.Melding})");
|
|
|
|
// Nog niet aangewezen: dan hoort hij ook niet bij de lijst te zitten. Anders zou de
|
|
// eerste de beste bijlage ineens het portret van iemand worden.
|
|
Assert.True(Eva().ProfielfotoId is null, "een gewone bijlage is nog geen profielfoto");
|
|
|
|
Assert.True((await app.ProfielfotoAsync(foto.Waarde)).Gelukt, "aanwijzen lukt");
|
|
Assert.True(Eva().ProfielfotoId == foto.Waarde, "en nu staat het nummer erbij");
|
|
|
|
// De kleine versie blijft hier leeg: in de zelfcontroles draait geen verkleiner, en
|
|
// "doet alsof het een foto is" is ook geen echte afbeelding. Het scherm hoort daar
|
|
// niet op te blijven hangen maar gewoon de beginletters te tonen.
|
|
Assert.True(Eva().Profielfotobron is null, "zonder kleine versie toont het scherm de letters");
|
|
});
|
|
|
|
runner.TestAsync("App: een foto bij iemand die zijn profiel zelf beheert kan niet", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var jan = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await jan.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await jan.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", "eva@example.nl", relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
// Piet hoort er helemaal niet bij: hij mag er niet bij, ook niet om te kijken.
|
|
await using var piet = await proef.AangemeldeAppAsync("piet@example.nl", "Piet", "Pietersen");
|
|
|
|
Assert.True(!(await piet.PersoonsfotosAsync(evaId)).Gelukt, "Piet ziet Eva's foto's niet");
|
|
Assert.True(!(await piet.BestandVersturenAsync("stiekem.jpg", "image/jpeg",
|
|
System.Text.Encoding.UTF8.GetBytes("nee"), persoonId: evaId)).Gelukt,
|
|
"en kan er niets bij zetten");
|
|
});
|
|
|
|
runner.TestAsync("App: bijlagen bij een bericht dat nog klaarstaat", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var evaId = (await app.VoegFamilielidToeAsync(familieId, "Eva", "Jansen", null, relatie: 12))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var berichtId = (await app.BerichtKlaarzettenAsync(evaId, "Voor jou", "Lees dit later", null, true))
|
|
.Waarde.GetProperty("berichtId").GetInt64();
|
|
|
|
var bijlage = await app.BestandVersturenAsync("kaartje.jpg", "image/jpeg",
|
|
System.Text.Encoding.UTF8.GetBytes("een foto bij de brief"),
|
|
berichtId: berichtId);
|
|
Assert.True(bijlage.Gelukt, $"een bijlage bij het bericht lukt ({bijlage.Melding})");
|
|
|
|
var lijst = await app.BerichtbijlagenAsync(berichtId);
|
|
Assert.True(lijst.Gelukt, $"de bijlagen komen terug ({lijst.Melding})");
|
|
Assert.True(lijst.Waarde!.Single().FileName == "kaartje.jpg", "met de juiste naam");
|
|
|
|
// Een bijlage hoort bij één ding; dat is geen keuze maar een regel.
|
|
Assert.True(!(await app.ProfielfotoAsync(bijlage.Waarde)).Gelukt,
|
|
"een berichtbijlage is geen profielfoto");
|
|
|
|
await using var piet = await proef.AangemeldeAppAsync("piet@example.nl", "Piet", "Pietersen");
|
|
Assert.True(!(await piet.BerichtbijlagenAsync(berichtId)).Gelukt,
|
|
"een ander ziet de bijlagen van jouw bericht niet");
|
|
});
|
|
|
|
runner.TestAsync("App: bericht klaarzetten voor na het overlijden", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var familieId = (await app.FamiliesAsync()).Waarde![0].Id;
|
|
var marieId = (await app.VoegFamilielidToeAsync(familieId, "Marie", "Jansen", null, relatie: 1))
|
|
.Waarde.GetProperty("persoonId").GetInt64();
|
|
|
|
var klaargezet = await app.BerichtKlaarzettenAsync(
|
|
marieId, "Voor jou", "Dag lieve Marie", bezorgOp: null, naOverlijden: true);
|
|
Assert.True(klaargezet.Gelukt, $"het bericht wordt klaargezet ({klaargezet.Melding})");
|
|
|
|
var uitgaand = await app.UitgaandAsync();
|
|
Assert.True(uitgaand.Gelukt, $"uitgaande post komt terug ({uitgaand.Melding})");
|
|
var bericht = uitgaand.Waarde!.Single();
|
|
Assert.True(bericht.Subject == "Voor jou", "met het onderwerp");
|
|
Assert.True(bericht.ToPersonId == marieId, "en de juiste ontvanger");
|
|
Assert.True(bericht.DeliverAfterDeath, "gemarkeerd als 'pas na mijn overlijden'");
|
|
|
|
var inkomend = await app.InkomendAsync();
|
|
Assert.True(inkomend.Waarde!.Count == 0, "bij de afzender staat het niet in de inbox");
|
|
});
|
|
|
|
runner.TestAsync("App: stand van de nalatenschap", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl");
|
|
|
|
var stand = await app.NalatenschapStandAsync();
|
|
Assert.True(stand.Gelukt, $"de stand komt terug ({stand.Melding})");
|
|
Assert.True(!stand.Waarde!.LooptEenProcedure, "er loopt niets");
|
|
Assert.True(!stand.Waarde.IsBevestigd, "en er is niets bevestigd");
|
|
Assert.True(stand.Waarde.RequiredDeclarations == 3, "standaard zijn er drie meldingen nodig");
|
|
Assert.True(stand.Waarde.Missing == 3, "er ontbreken er dus nog drie");
|
|
});
|
|
|
|
runner.TestAsync("App: sessie hervatten bij een volgende start", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
var opslag = new GeheugenTokenopslag();
|
|
|
|
await using (var eerste = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag)) { }
|
|
|
|
// Zo start de app de tweede keer: alleen het bewaarde token, geen code.
|
|
await using (var tweede = proef.App(opslag))
|
|
{
|
|
Assert.True(await tweede.HervatSessieAsync(), "met het bewaarde token hoeft niemand opnieuw in te loggen");
|
|
Assert.True((await tweede.FamiliesAsync()).Gelukt, "en de app kan meteen gegevens ophalen");
|
|
|
|
// En hij weet wie hij is. Dit werd alleen gevuld bij het inloggen met een code,
|
|
// en dan weet de app na een herstart niet welk familielid jijzelf bent: de kaart
|
|
// bovenaan Mijn mensen viel terug op initialen én je stond een tweede keer in de
|
|
// lijst, want die lijst filtert op precies dit nummer.
|
|
Assert.True(tweede.PersoonId != 0, "en weet wie hij is");
|
|
|
|
var ik = await tweede.EigenProfielAsync();
|
|
Assert.True(ik.Gelukt && ik.Waarde!.PersoonId == tweede.PersoonId,
|
|
"hetzelfde nummer als in het eigen profiel");
|
|
|
|
// Het profiel wordt onthouden, zodat elk scherm je naam en je kleine foto heeft
|
|
// zonder er zelf om te vragen. De kluis gebruikt die foto als tekentje bij
|
|
// "Alleen voor mijzelf".
|
|
Assert.True(tweede.MijnProfiel is not null, "het profiel wordt onthouden");
|
|
|
|
// De server stelt dit antwoord met de hand samen, omdat de profielfoto er los
|
|
// bij komt. Vergeet iemand daar een veld, dan is het stil weg; vandaar deze
|
|
// controle op de velden zelf en niet alleen op het nummer.
|
|
Assert.True(tweede.MijnProfiel!.Email == "jan@example.nl",
|
|
"met alle velden erin, niet alleen het nummer");
|
|
}
|
|
|
|
// En zo als het token niet meer geldig is.
|
|
await opslag.SchrijfAsync("dit-is-geen-geldig-token");
|
|
await using (var derde = proef.App(opslag))
|
|
{
|
|
Assert.True(!await derde.HervatSessieAsync(), "een verlopen token levert geen sessie op");
|
|
Assert.True(await opslag.LeesAsync() is null, "en wordt opgeruimd in plaats van eeuwig geprobeerd");
|
|
}
|
|
});
|
|
|
|
runner.TestAsync("App: een sessie die de server niet meer kent wordt meteen opgeruimd", async () =>
|
|
{
|
|
// Dit gebeurt na elke herstart van de SocketServer: die bewaart zijn sessies in het
|
|
// geheugen. Zonder dit bleef de app staan op een rode balk met "opnieuw proberen",
|
|
// en dat lukt nooit meer - het token bestaat niet meer.
|
|
await using var proef = new Proef();
|
|
var opslag = new GeheugenTokenopslag();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag);
|
|
|
|
Assert.True((await app.FamiliesAsync()).Gelukt, "eerst werkt alles gewoon");
|
|
|
|
var gemeld = 0;
|
|
app.SessieVerlopen += () => gemeld++;
|
|
|
|
// Alsof de service opnieuw is opgestart: de server is alle sessies kwijt.
|
|
await proef.Sessies.RemoveAllForAsync(proef.Wereld.Store.Users.Single().Id);
|
|
|
|
var uitkomst = await app.FamiliesAsync();
|
|
Assert.True(!uitkomst.Gelukt, "het verzoek mislukt");
|
|
Assert.True(uitkomst.Melding!.Contains("opnieuw in"), "met de melding dat je opnieuw moet inloggen");
|
|
|
|
Assert.True(gemeld == 1, "de app krijgt het één keer te horen");
|
|
Assert.True(!app.IsAangemeld, "en beschouwt zichzelf als uitgelogd");
|
|
Assert.True(await opslag.LeesAsync() is null, "het bewaarde token is weg");
|
|
|
|
// Een tweede verzoek meldt het niet nog een keer: één keer naar het inlogscherm is genoeg.
|
|
await app.FamiliesAsync();
|
|
Assert.True(gemeld == 1, "en blijft het bij één melding");
|
|
});
|
|
|
|
runner.TestAsync("App: het slot gaat op wat er op het toestel ligt, niet op wat de server zegt", async () =>
|
|
{
|
|
// De afspraak: na de eerste keer inloggen met een code kom je erin met je
|
|
// vingerafdruk, tot je zelf uitlogt. Daarvoor moet de app bij het openen kunnen
|
|
// weten dat er een sessie op dit toestel ligt - zonder de server iets te vragen.
|
|
//
|
|
// Het ging eerder mis omdat het slot pas op de app ging nadat de server het token
|
|
// had goedgekeurd. Een telefoon die net wakker wordt heeft nog geen netwerk, en na
|
|
// een herstart van de service kende de server de sessie niet meer. Je kwam dan op
|
|
// het inlogscherm terecht met een vraag om je e-mailadres, terwijl je telefoon
|
|
// prima wist wie je was.
|
|
var opslag = new GeheugenTokenopslag();
|
|
|
|
await using (var proef = new Proef())
|
|
{
|
|
await using var eerst = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag);
|
|
}
|
|
// De server is nu weg - net als een telefoon zonder bereik, of een service die
|
|
// net opnieuw start.
|
|
|
|
await using var app = new MijnBesluitClient("127.0.0.1", VrijePoort(), tls: false, opslag);
|
|
|
|
Assert.True(await app.HeeftBewaardeSessieAsync(),
|
|
"de app weet zonder server dat hier iemand is aangemeld");
|
|
Assert.True(app.IsAangemeld, "en beschouwt zichzelf als aangemeld");
|
|
|
|
// En het omgekeerde: op een toestel waar niets ligt, valt er niets te vergrendelen.
|
|
await using var vers = new MijnBesluitClient("127.0.0.1", VrijePoort(), tls: false,
|
|
new GeheugenTokenopslag());
|
|
Assert.True(!await vers.HeeftBewaardeSessieAsync(),
|
|
"een schoon toestel gaat gewoon naar het inlogscherm");
|
|
});
|
|
|
|
runner.TestAsync("App: uitloggen wist het bewaarde token", async () =>
|
|
{
|
|
await using var proef = new Proef();
|
|
var opslag = new GeheugenTokenopslag();
|
|
await using var app = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag);
|
|
|
|
await app.UitloggenAsync();
|
|
|
|
Assert.True(!app.IsAangemeld, "de app is niet meer aangemeld");
|
|
Assert.True(await opslag.LeesAsync() is null, "het token is van het toestel verdwenen");
|
|
Assert.True(!(await app.FamiliesAsync()).Gelukt, "en gegevens ophalen lukt niet meer");
|
|
});
|
|
|
|
runner.TestAsync("App: uitloggen lukt ook als de server onbereikbaar is", async () =>
|
|
{
|
|
// Anders blijft iemand met een dood scherm zitten terwijl hij juist weg wil:
|
|
// de knop wacht dan op een verbinding die er niet is.
|
|
var opslag = new GeheugenTokenopslag();
|
|
MijnBesluitClient app;
|
|
|
|
await using (var proef = new Proef())
|
|
{
|
|
app = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag);
|
|
Assert.True(!string.IsNullOrEmpty(await opslag.LeesAsync()), "er is een sessie");
|
|
}
|
|
// De server is nu weg - net als een telefoon zonder bereik.
|
|
|
|
var klaar = app.UitloggenAsync();
|
|
Assert.True(await Task.WhenAny(klaar, Task.Delay(5000)) == klaar, "uitloggen blijft niet hangen");
|
|
|
|
Assert.True(!app.IsAangemeld, "de app is uitgelogd");
|
|
Assert.True(await opslag.LeesAsync() is null, "en het token staat niet meer op het toestel");
|
|
await app.DisposeAsync();
|
|
});
|
|
|
|
runner.TestAsync("App: de melding 'geen verbinding' verdwijnt weer zodra het lukt", async () =>
|
|
{
|
|
// Precies wat er op een telefoon gebeurt: de app gaat naar de achtergrond terwijl
|
|
// iemand zijn e-mail leest, Android verbreekt de verbinding, en daarna moet de app
|
|
// gewoon weer verder kunnen zonder dat de melding blijft staan.
|
|
var poort = VrijePoort();
|
|
var standen = new List<bool>();
|
|
|
|
await using var app = new MijnBesluitClient("127.0.0.1", poort, tls: false);
|
|
app.VerbindingVeranderd += nu => standen.Add(nu);
|
|
|
|
Assert.True(!(await app.FamiliesAsync()).Gelukt, "zonder server mislukt het verzoek");
|
|
Assert.True(!app.IsVerbonden, "de app weet dat er geen verbinding is");
|
|
|
|
// Nu komt de server (of het netwerk) terug.
|
|
var wereld = new World();
|
|
var sessies = new SessionStore(wereld.Clock);
|
|
var dispatcher = new SocketDispatcher(sessies, work => work(new RequestScope
|
|
{
|
|
Accounts = wereld.Accounts, Families = wereld.Families, Vault = wereld.Vault,
|
|
Messages = wereld.Messages, Legacy = wereld.Legacy, Overzicht = wereld.Overzicht
|
|
}));
|
|
|
|
await using var server = new SocketListener(
|
|
new SocketListenerOptions { Address = IPAddress.Loopback, Port = poort },
|
|
dispatcher.HandleAsync);
|
|
server.Start();
|
|
|
|
// Een verzoek zonder sessie wordt geweigerd, maar de verbinding staat er wel weer.
|
|
await app.FamiliesAsync();
|
|
Assert.True(app.IsVerbonden, "na een geslaagde verbinding staat de melding weer uit");
|
|
Assert.True(standen.Contains(false) && standen.Last(), "de app is over beide veranderingen bericht");
|
|
});
|
|
|
|
runner.TestAsync("App: een actie die de server niet kent wordt als zodanig gemeld", async () =>
|
|
{
|
|
// Dit is precies het geval "app is nieuwer dan de server". Zonder deze volgorde
|
|
// krijg je "log opnieuw in" te zien, en zoek je het in de verkeerde hoek.
|
|
await using var proef = new Proef();
|
|
await using var rauw = new MijnBesluitSocketClient("127.0.0.1", proef.Server.Port, useTls: false);
|
|
|
|
var onbekend = await rauw.SendAsync("vault.ditbestaatniet");
|
|
Assert.True(onbekend.Status == "Error", "een onbekende actie wordt geweigerd");
|
|
Assert.True(onbekend.Message!.Contains("Onbekende actie"),
|
|
$"met de juiste melding, ook zonder sessie ({onbekend.Message})");
|
|
|
|
// Een actie die hij wél kent maar waarvoor je moet inloggen, geeft de sessiemelding.
|
|
var welBekend = await rauw.SendAsync(SocketActions.VaultList);
|
|
Assert.True(welBekend.Message!.Contains("Log opnieuw in"), "en een bekende actie vraagt om inloggen");
|
|
});
|
|
|
|
runner.TestAsync("App: zonder bereikbare server komt er een melding in plaats van een crash", async () =>
|
|
{
|
|
// Een poort waar niets luistert: precies wat er gebeurt in een lift of trein.
|
|
await using var app = new MijnBesluitClient("127.0.0.1", VrijePoort(), tls: false);
|
|
|
|
var uitkomst = await app.FamiliesAsync();
|
|
Assert.True(!uitkomst.Gelukt, "de aanroep mislukt netjes");
|
|
Assert.True(!string.IsNullOrWhiteSpace(uitkomst.Melding), "met een melding die op het scherm kan");
|
|
Assert.True(!await app.HervatSessieAsync(), "sessie hervatten loopt ook niet stuk");
|
|
});
|
|
|
|
runner.TestAsync("App: geen verbinding gooit het bewaarde token niet weg", async () =>
|
|
{
|
|
// Het verschil tussen "de server zegt nee" en "ik kan de server niet bereiken".
|
|
// Alleen het eerste is een reden om iemand opnieuw te laten inloggen.
|
|
//
|
|
// Ging dit mis, dan moest je een code per e-mail aanvragen terwijl er niets mis was
|
|
// met je sessie - en juist op het vervelendste moment: een app die op slot stond is
|
|
// vaak door Android afgesloten, dus start hij koud op, en dan is het netwerk van de
|
|
// telefoon nog niet wakker.
|
|
var opslag = new GeheugenTokenopslag();
|
|
|
|
// Eerst een echte sessie, zodat er een geldig token op het toestel staat.
|
|
string token;
|
|
await using (var proef = new Proef())
|
|
{
|
|
await using var eerste = await proef.AangemeldeAppAsync("jan@example.nl", opslag: opslag);
|
|
token = (await opslag.LeesAsync())!;
|
|
Assert.True(!string.IsNullOrEmpty(token), "er staat een token op het toestel");
|
|
}
|
|
|
|
// En nu starten terwijl de server onbereikbaar is.
|
|
await using (var koudeStart = new MijnBesluitClient("127.0.0.1", VrijePoort(), tls: false, opslag: opslag))
|
|
{
|
|
Assert.True(!await koudeStart.HervatSessieAsync(), "de sessie komt er niet doorheen");
|
|
Assert.True(await opslag.LeesAsync() == token,
|
|
"maar het token blijft staan: dit is geen reden om opnieuw te laten inloggen");
|
|
}
|
|
|
|
// Zegt de server wél dat hij de sessie niet kent, dan hoort het token juist weg.
|
|
await using (var proef = new Proef())
|
|
{
|
|
await opslag.SchrijfAsync("dit-is-geen-geldig-token");
|
|
await using var app = proef.App(opslag);
|
|
|
|
Assert.True(!await app.HervatSessieAsync(), "een geweigerde sessie levert niets op");
|
|
Assert.True(await opslag.LeesAsync() is null, "en dan wordt het token wel opgeruimd");
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>Een poortnummer waar gegarandeerd niets luistert.</summary>
|
|
private static int VrijePoort()
|
|
{
|
|
var luisteraar = new System.Net.Sockets.TcpListener(IPAddress.Loopback, 0);
|
|
luisteraar.Start();
|
|
var poort = ((IPEndPoint)luisteraar.LocalEndpoint).Port;
|
|
luisteraar.Stop();
|
|
return poort;
|
|
}
|
|
}
|