Adds transactional outbox and email verification

Implements outbox pattern for reliable message delivery
Adds email verification flow with Postmark integration
Enhances account registration with secure token generation

Introduces background processing for asynchronous email sending
Implements database-level notification mechanism for message processing
This commit is contained in:
Janus C. H. Knudsen 2026-01-10 11:13:33 +01:00
parent 88812177a9
commit 54b057886c
35 changed files with 1174 additions and 358 deletions

View file

@ -7,40 +7,14 @@ namespace PlanTempus.X.BDD.Scenarios;
[TestClass]
public partial class OrganizationSetupSpecs : FeatureFixtures.OrganizationSetupSpecs
{
[Scenario]
[TestMethod]
public async Task Complete_organization_setup_after_confirmation()
{
await Runner.RunScenarioAsync(
_ => Given_account_has_confirmed_their_email("test@example.com"),
_ => When_account_submit_organization_name_and_valid_password("Acme Corp", "ValidP@ssw0rd"),
_ => Then_a_new_organization_should_be_created_with_expected_properties(),
_ => And_the_account_should_be_linked_to_the_organization_in_account_organizations(),
_ => And_tenant_tables_should_be_created_for_the_organization(),
_ => And_account_should_be_logged_into_the_system()
);
}
[Scenario]
[TestMethod]
public async Task Prevent_organization_setup_without_password()
{
await Runner.RunScenarioAsync(
_ => Given_account_has_confirmed_their_email("test@example.com"),
_ => When_account_submit_organization_name_without_password("Acme Corp"),
_ => Then_organization_setup_should_fail_with_error("Password required")
);
}
[Scenario]
[TestMethod]
public async Task Handle_multiple_organization_creations()
{
await Runner.RunScenarioAsync(
_ => Given_account_has_completed_initial_setup("test@example.com"),
_ => When_account_create_a_new_organization("Second Org"),
_ => Then_a_new_organization_entry_should_be_created(),
_ => And_the_account_should_be_linked_to_both_organizations()
);
}
[Scenario]
[TestMethod]
public async Task Create_organization_for_registered_account()
{
await Runner.RunScenarioAsync(
_ => Given_a_registered_account(),
_ => When_I_create_an_organization_with_connection_string("Host=localhost;Database=tenant_db;"),
_ => Then_the_organization_should_be_created_successfully()
);
}
}