2025-02-27 17:24:58 +01:00
|
|
|
|
using LightBDD.Framework;
|
|
|
|
|
|
using LightBDD.Framework.Scenarios;
|
|
|
|
|
|
using LightBDD.MsTest3;
|
|
|
|
|
|
namespace PlanTempus.X.BDD.Scenarios;
|
|
|
|
|
|
|
|
|
|
|
|
[TestClass]
|
|
|
|
|
|
public partial class UserRegistrationSpecs : FeatureFixtures.UserRegistrationSpecs
|
|
|
|
|
|
{
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Successful_user_registration_with_valid_email()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_no_user_exists_with_email("test@example.com"),
|
|
|
|
|
|
_ => When_I_submit_registration_with_name_and_email("Test User", "test@example.com"),
|
|
|
|
|
|
_ => Then_a_new_user_should_be_created_with_email_and_confirmation_status("test@example.com", false),
|
|
|
|
|
|
_ => Then_a_confirmation_email_should_be_sent()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2025-02-28 17:56:14 +01:00
|
|
|
|
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Reject_duplicate_email_registration()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_a_user_already_exists_with_email("existing@example.com"),
|
|
|
|
|
|
_ => When_I_submit_registration_with_email("existing@example.com"),
|
|
|
|
|
|
_ => Then_registration_should_fail_with_error("Email already exists")
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TestClass]
|
|
|
|
|
|
public partial class EmailConfirmationSpecs : FeatureFixtures.EmailConfirmationSpecs
|
|
|
|
|
|
{
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Confirm_valid_email_address()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_a_user_exists_with_unconfirmed_email("test@example.com"),
|
|
|
|
|
|
_ => When_I_click_the_valid_confirmation_link_for("test@example.com"),
|
|
|
|
|
|
_ => Then_the_users_email_confirmed_should_be_true(),
|
|
|
|
|
|
_ => And_I_should_be_redirected_to_the_welcome_page()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Handle_invalid_confirmation_link()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => When_I_click_an_invalid_confirmation_link(),
|
|
|
|
|
|
_ => Then_I_should_see_an_error_message("Invalid confirmation link"),
|
|
|
|
|
|
_ => And_my_email_remains_unconfirmed()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TestClass]
|
|
|
|
|
|
public partial class OrganizationSetupSpecs : FeatureFixtures.OrganizationSetupSpecs
|
|
|
|
|
|
{
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Complete_organization_setup_after_confirmation()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_user_has_confirmed_their_email("test@example.com"),
|
|
|
|
|
|
_ => When_I_submit_organization_name_and_valid_password("Acme Corp", "ValidP@ssw0rd"),
|
|
|
|
|
|
_ => Then_a_new_organization_should_be_created_with_expected_properties(),
|
|
|
|
|
|
_ => And_the_user_should_be_linked_to_the_organization_in_user_organizations(),
|
|
|
|
|
|
_ => And_tenant_tables_should_be_created_for_the_organization(),
|
|
|
|
|
|
_ => And_I_should_be_logged_into_the_system()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task Prevent_organization_setup_without_password()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_user_has_confirmed_their_email("test@example.com"),
|
|
|
|
|
|
_ => When_I_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_user_has_completed_initial_setup("test@example.com"),
|
|
|
|
|
|
_ => When_I_create_a_new_organization("Second Org"),
|
|
|
|
|
|
_ => Then_a_new_organization_entry_should_be_created(),
|
|
|
|
|
|
_ => And_the_user_should_be_linked_to_both_organizations()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2025-02-27 17:24:58 +01:00
|
|
|
|
}
|
2025-02-28 17:56:14 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[TestClass]
|
|
|
|
|
|
public partial class AccountSecuritySpecs : FeatureFixtures.AccountSecuritySpecs
|
|
|
|
|
|
{
|
|
|
|
|
|
[Scenario]
|
|
|
|
|
|
[TestMethod]
|
|
|
|
|
|
public async Task User_lockout_after_multiple_failed_attempts()
|
|
|
|
|
|
{
|
|
|
|
|
|
await Runner.RunScenarioAsync(
|
|
|
|
|
|
_ => Given_user_exists("test@example.com"),
|
|
|
|
|
|
_ => When_I_attempt_5_failed_logins_within_5_minutes(),
|
|
|
|
|
|
_ => Then_the_account_should_be_locked(),
|
|
|
|
|
|
_ => And_lockout_end_should_be_set(),
|
|
|
|
|
|
_ => And_subsequent_login_attempts_should_fail_until_lockout_end()
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|