Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions backend/InTheKnow.Tests/AccountEmailTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public partial class AccountEmailTests
_ => [],
};

static Message Account(string kind, string language, IReadOnlyDictionary<string, string>? args = null) =>
internal static Message Account(string kind, string language, IReadOnlyDictionary<string, string>? args = null) =>
new(MessageKind.Account, language, Amsterdam, null, null, null, null, [], 0, kind,
LinkKinds.Contains(kind) ? $"{EmailChannelTests.Frontend}/account/x?token=TOKEN" : null, args ?? Args(kind));

Expand All @@ -48,9 +48,21 @@ public void EveryKindRendersInBothLanguages()
Assert.Equal(Texts.Get(language, $"account.{kind}.subject"), mail.Subject);
var footer = Texts.Get(language, "account.footer");
Assert.Contains(footer, text);
Assert.Contains(footer, html);
EmailChannelTests.AssertFooterBelowCard(html, footer);
if (LinkKinds.Contains(kind))
{
var link = $"{EmailChannelTests.Frontend}/account/x?token=TOKEN";
foreach (var part in new[] { text, html }) Assert.Contains("/account/x?token=TOKEN", part);
// One button with the action, then a muted line with the full link as selectable text.
Assert.Equal(1, EmailChannelTests.Count(html, "mso-padding-alt"));
Assert.Contains($"<a href=\"{link}\" style=\"display:inline-block;padding:12px 24px;line-height:20px;color:#ffffff;font-weight:700;text-decoration:none\">{Texts.Get(language, $"account.{kind}.action")}</a>", html);
Assert.Contains($"{Texts.Get(language, "account.linkFallback")}<br><a href=\"{link}\" style=\"color:#c70b70;text-decoration:underline\">{link}</a>", html);
}
else
{
Assert.DoesNotContain("mso-padding-alt", html);
Assert.DoesNotContain(Texts.Get(language, "account.linkFallback"), html);
}
Assert.DoesNotContain("{0}", text);
}
Assert.Contains("You have 9 recovery codes left.", EmailChannelTests.Render(Account("recoveryCodeUsed", "en")).Text);
Expand All @@ -67,6 +79,16 @@ public void ArgsAreEncoded()
Assert.Contains("<b>x</b>", text);
Assert.DoesNotContain("<b>x</b>", html);
Assert.Contains("&lt;b&gt;x&lt;/b&gt;", html);

// SC-005: the other inserted values, and the link.
foreach (var (kind, key) in new[] { ("recoveryCodeUsed", "remaining"), ("invite", "expires") })
{
html = EmailChannelTests.Render(Account(kind, "en", new Dictionary<string, string> { [key] = "<b>x</b>" })).Html;
Assert.DoesNotContain("<b>x</b>", html);
}
html = EmailChannelTests.Render(Account("reset", "en") with { Link = "http://localhost/x?a=\"><b>x</b>" }).Html;
Assert.DoesNotContain("<b>x</b>", html);
Assert.Contains("&quot;&gt;&lt;b&gt;x&lt;/b&gt;", html);
}

// Both languages have every account key: a subject and a body (or its variants) per kind, and an action per link kind.
Expand Down
234 changes: 221 additions & 13 deletions backend/InTheKnow.Tests/EmailChannelTests.cs

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions backend/InTheKnow.Tests/EmailPreviewTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using Xunit;

namespace InTheKnow.Tests;

// Opt-in: sends every email shape in both languages to a local SMTP catcher (specs/007 quickstart.md).
public class EmailPreviewTests
{
[Fact]
public async Task SendEveryFixture()
{
var port = Environment.GetEnvironmentVariable("INTHEKNOW_PREVIEW_SMTP_PORT");
Assert.SkipWhen(port is null, "set INTHEKNOW_PREVIEW_SMTP_PORT (Mailpit: 1025) to send every email shape");
var email = new EmailChannel(TestDb.Offline(EmailChannelTests.EmailSettings(int.Parse(port!))));
foreach (var language in new[] { "en", "nl" })
foreach (var (name, message) in EmailChannelTests.EmailFixtures(language))
{
var result = await email.SendAsync($"{name}.{language}@example.test", message, TestContext.Current.CancellationToken);
Assert.Equal(SendStatus.Sent, result.Status);
}
}
}
13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-confirm.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Confirm your InTheKnow account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Someone signed up for InTheKnow with this email address. Open the link and enter your password to confirm the account. The link is valid for 24 hours.

Confirm my account:
http://localhost:5173/account/x?token=TOKEN

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-confirm.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Bevestig je InTheKnow-account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Iemand heeft zich met dit e-mailadres aangemeld bij InTheKnow. Open de link en vul je wachtwoord in om het account te bevestigen. De link is 24 uur geldig.

Mijn account bevestigen:
http://localhost:5173/account/x?token=TOKEN

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-deleted.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Your InTheKnow account was deleted
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Your InTheKnow account and everything in it were deleted. This is the last email about it.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-deleted.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Je InTheKnow-account is verwijderd
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Je InTheKnow-account en alles erin zijn verwijderd. Dit is de laatste e-mail erover.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-disabled.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Your InTheKnow account was disabled
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

An admin disabled your InTheKnow account. You cannot sign in and get no timetable notifications until it is enabled again.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-disabled.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Je InTheKnow-account is geblokkeerd
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Een beheerder heeft je InTheKnow-account geblokkeerd. Je kunt je niet aanmelden en krijgt geen roostermeldingen tot het weer wordt vrijgegeven.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Confirm your new email address for InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Someone asked to use this email address for their InTheKnow account. Open the link to confirm it. The link is valid for 24 hours. Until then, the account keeps its current address.

Confirm this address:
http://localhost:5173/account/x?token=TOKEN

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Bevestig je nieuwe e-mailadres voor InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Iemand wil dit e-mailadres gebruiken voor zijn of haar InTheKnow-account. Open de link om het te bevestigen. De link is 24 uur geldig. Tot dan houdt het account zijn huidige adres.

Dit adres bevestigen:
http://localhost:5173/account/x?token=TOKEN

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: The email address of your InTheKnow account is being changed
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Someone asked to change the email address of your InTheKnow account. It changes only when the new address is confirmed.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Het e-mailadres van je InTheKnow-account wordt gewijzigd
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Iemand heeft gevraagd het e-mailadres van je InTheKnow-account te wijzigen. Het verandert pas als het nieuwe adres is bevestigd.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-enabled.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Your InTheKnow account was enabled again
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

An admin enabled your InTheKnow account again. You can sign in, and new timetable changes are notified again.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

10 changes: 10 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-enabled.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Je InTheKnow-account is weer vrijgegeven
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Een beheerder heeft je InTheKnow-account weer vrijgegeven. Je kunt je aanmelden, en nieuwe roosterwijzigingen worden weer gemeld.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: You are invited to InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

You are invited to create an admin account on InTheKnow. Open the link to choose a password. The admin pages open once two-step verification is on. The invitation is valid until Tue 6 Oct 2026 08:30.

Accept the invitation:
http://localhost:5173/account/x?token=TOKEN

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Je bent uitgenodigd voor InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Je bent uitgenodigd om een beheerdersaccount te maken bij InTheKnow. Open de link om een wachtwoord te kiezen. De beheerpagina's gaan open zodra verificatie in twee stappen aanstaat. De uitnodiging is geldig tot Tue 6 Oct 2026 08:30.

Uitnodiging accepteren:
http://localhost:5173/account/x?token=TOKEN

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-invite.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: You are invited to InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

You are invited to create an account on InTheKnow, which tells you about changes in your timetable. Open the link to choose a password. The invitation is valid until Tue 6 Oct 2026 08:30.

Accept the invitation:
http://localhost:5173/account/x?token=TOKEN

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-invite.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Je bent uitgenodigd voor InTheKnow
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Je bent uitgenodigd om een account te maken bij InTheKnow, dat je laat weten wanneer je rooster verandert. Open de link om een wachtwoord te kiezen. De uitnodiging is geldig tot Tue 6 Oct 2026 08:30.

Uitnodiging accepteren:
http://localhost:5173/account/x?token=TOKEN

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: A sign-in method was added to your InTheKnow account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

The sign-in method "password" was added to your InTheKnow account.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Er is een aanmeldmethode toegevoegd aan je InTheKnow-account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

De aanmeldmethode "password" is toegevoegd aan je InTheKnow-account.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: A sign-in method was removed from your InTheKnow account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

The sign-in method "password" was removed from your InTheKnow account, and the devices signed in with it were signed out.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Er is een aanmeldmethode verwijderd uit je InTheKnow-account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

De aanmeldmethode "password" is verwijderd uit je InTheKnow-account, en de apparaten die ermee waren aangemeld zijn afgemeld.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Your InTheKnow password was changed
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

The password of your InTheKnow account was changed, and your other devices were signed out.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Je InTheKnow-wachtwoord is gewijzigd
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Het wachtwoord van je InTheKnow-account is gewijzigd, en je andere apparaten zijn afgemeld.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: A recovery code was used for your InTheKnow account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

A recovery code was used to sign in to your InTheKnow account. You have 9 recovery codes left.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Er is een herstelcode gebruikt voor je InTheKnow-account
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Er is een herstelcode gebruikt om je aan te melden bij je InTheKnow-account. Je hebt nog 9 herstelcodes.

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-reset.en.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Reset your InTheKnow password
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Someone asked to reset the password of your InTheKnow account. Open the link to choose a new password. The link is valid for 1 hour. Your password stays the same until you choose a new one.

Choose a new password:
http://localhost:5173/account/x?token=TOKEN

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

13 changes: 13 additions & 0 deletions backend/InTheKnow.Tests/EmailSnapshots/account-reset.nl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Subject: Stel je InTheKnow-wachtwoord opnieuw in
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Iemand heeft gevraagd het wachtwoord van je InTheKnow-account opnieuw in te stellen. Open de link om een nieuw wachtwoord te kiezen. De link is 1 uur geldig. Je wachtwoord blijft hetzelfde tot je een nieuw kiest.

Kies een nieuw wachtwoord:
http://localhost:5173/account/x?token=TOKEN

Verwachtte je deze e-mail niet, dan kun je hem negeren; is er iets in je account veranderd dat je niet zelf deed, stel dan je wachtwoord opnieuw in of beantwoord deze e-mail om de beheerder te bereiken.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Subject: Your InTheKnow role was changed
To: student@example.nl
From: "InTheKnow" <intheknow@localhost>
List-Unsubscribe:
List-Unsubscribe-Post:

Your InTheKnow account is no longer an admin.

If you did not expect this email, you can ignore it; if something changed in your account that you did not do, reset your password or reply to this email to reach the operator.

Loading
Loading