Skip to content

Commit

Permalink
feat(templates): add tests for change phone number in Boilerplate #9027
Browse files Browse the repository at this point in the history
… (#9028)
  • Loading branch information
mjebrahimi authored Oct 27, 2024
1 parent 2501883 commit 9e23ee1
Show file tree
Hide file tree
Showing 23 changed files with 500 additions and 133 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -486,7 +486,6 @@
"condition": "(advancedTests != true)",
"exclude": [
"src/Tests/PageTests/**",
"src/Tests/TestInitializer.cs",
"src/Tests/Services/CulturedStringLocalizer.cs",
"src/Tests/Services/EmailReaderService.cs",
"src/Tests/Services/UserService.cs"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public partial class PhoneService
[AutoInject] private readonly IHttpContextAccessor httpContextAccessor = default!;
[AutoInject] private readonly PhoneNumberUtil phoneNumberUtil = default!;

public string? NormalizePhoneNumber(string? phoneNumber)
public virtual string? NormalizePhoneNumber(string? phoneNumber)
{
if (string.IsNullOrEmpty(phoneNumber))
return null;
Expand All @@ -26,7 +26,7 @@ public partial class PhoneService
return phoneNumberUtil.Format(parsedPhoneNumber, PhoneNumberFormat.E164);
}

public async Task SendSms(string messageText, string phoneNumber, CancellationToken cancellationToken)
public virtual async Task SendSms(string messageText, string phoneNumber, CancellationToken cancellationToken)
{
if (hostEnvironment.IsDevelopment())
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public static void AddTestProjectServices(this WebApplicationBuilder builder)

builder.AddServerWebProjectServices();

services.AddTransient<PhoneService, FakePhoneService>();

//#if (captcha == "reCaptcha")
services.AddTransient<GoogleRecaptchaHttpClient, FakeGoogleRecaptchaHttpClient>();
//#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ await server.Build(services =>

await authenticationManager.SignIn(new()
{
Email = "[email protected]",
Password = "123456"
Email = TestData.DefaultTestEmail,
Password = TestData.DefaultTestPassword
}, default);

var userController = scope.ServiceProvider.GetRequiredService<IUserController>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ public async Task SignIn_Should_WorkAsExpected()

await Expect(Page).ToHaveTitleAsync(AppStrings.SignInPageTitle);

const string email = "[email protected]";
const string password = "123456";
const string userFullName = "Boilerplate test account";
const string email = TestData.DefaultTestEmail;
const string password = TestData.DefaultTestPassword;
const string userFullName = TestData.DefaultTestFullName;

await Page.GetByPlaceholder(AppStrings.EmailPlaceholder).FillAsync(email);
await Page.GetByPlaceholder(AppStrings.PasswordPlaceholder).FillAsync(password);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public async Task SignIn(string mode)
switch (mode)
{
case "ValidCredentials":
var identityHomePage = await signInPage.SignIn();
var identityHomePage = await signInPage.SignInWithEmail();
await identityHomePage.AssertSignInSuccess();
break;
case "InvalidCredentials":
await signInPage.SignIn(email: "[email protected]", password: "invalid");
await signInPage.SignInWithEmail(email: "[email protected]", password: "invalid");
await signInPage.AssertSignInFailed();
break;
default:
Expand All @@ -61,7 +61,7 @@ public async Task SignOut()
await signInPage.Open();
await signInPage.AssertOpen();

var identityHomePage = await signInPage.SignIn(email);
var identityHomePage = await signInPage.SignInWithEmail(email);
await identityHomePage.AssertSignInSuccess(email, userFullName: null);

await dbContext.Entry(user).ReloadAsync();
Expand Down Expand Up @@ -118,20 +118,24 @@ public async Task SignUp(string mode)
[DataRow("Token")]
[DataRow("InvalidToken")]
[DataRow("MagicLink")]
[DataRow("TooManyRequests")]
[DataRow("NotExisted")]
public async Task ForgotPassword(string mode)
{
await using var scope = TestServer.WebApp.Services.CreateAsyncScope();

var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var userService = new UserService(dbContext);
var email = $"{Guid.NewGuid()}@gmail.com";
await userService.AddUser(email);
var email = await CreateNewUser();

var forgotPasswordPage = new ForgotPasswordPage(Page, WebAppServerAddress);

await forgotPasswordPage.Open();
await forgotPasswordPage.AssertOpen();

if (mode is "NotExisted")
{
await forgotPasswordPage.ForgotPassword("[email protected]");
await forgotPasswordPage.AssertUserNotFound();
return;
}

var resetPasswordPage = await forgotPasswordPage.ForgotPassword(email);
await resetPasswordPage.AssertOpen();

Expand All @@ -145,14 +149,19 @@ public async Task ForgotPassword(string mode)
var token = await resetPasswordEmail.GetToken();
await resetPasswordPage.ContinueByToken(token);
break;
case "MagicLink":
resetPasswordPage = await resetPasswordEmail.OpenMagicLink();
break;
case "InvalidToken":
await resetPasswordPage.ContinueByToken("111111");
await resetPasswordPage.SetPassword(newPassword);
await resetPasswordPage.AssertInvalidToken();
return;
case "MagicLink":
resetPasswordPage = await resetPasswordEmail.OpenMagicLink();
break;
case "TooManyRequests":
await Page.GoBackAsync();
await forgotPasswordPage.ForgotPassword(email);
await forgotPasswordPage.AssertTooManyRequests();
return;
default:
throw new NotSupportedException();
}
Expand All @@ -166,72 +175,148 @@ public async Task ForgotPassword(string mode)
await signInPage.Open();
await signInPage.AssertOpen();

var identityHomePage = await signInPage.SignIn(email, newPassword);
var identityHomePage = await signInPage.SignInWithEmail(email, newPassword);
await identityHomePage.AssertSignInSuccess(email, userFullName: null);
}

[TestMethod]
[DataRow("Token")]
[DataRow("InvalidToken")]
[DataRow("MagicLink")]
[DataRow("TooManyRequests")]
public async Task ChangeEmail(string mode)
{
await using var scope = TestServer.WebApp.Services.CreateAsyncScope();

var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var userService = new UserService(dbContext);
var email = $"{Guid.NewGuid()}@gmail.com";
await userService.AddUser(email);
var email = await CreateNewUser();

var signInPage = new SignInPage(Page, WebAppServerAddress);

await signInPage.Open();
await signInPage.AssertOpen();

var identityHomePage = await signInPage.SignIn(email);
var identityHomePage = await signInPage.SignInWithEmail(email);
await identityHomePage.AssertSignInSuccess(email, userFullName: null);

var settinsPage = new SettingsPage(Page, WebAppServerAddress);
var settingsPage = new SettingsPage(Page, WebAppServerAddress);

await settinsPage.Open();
await settinsPage.AssertOpen();
await settingsPage.Open();
await settingsPage.AssertOpen();

await settinsPage.ExpandAccount();
await settinsPage.AssertExpandAccount(email);
await settingsPage.ExpandAccount();
await settingsPage.AssertExpandAccount(email);

var newEmail = $"{Guid.NewGuid()}@gmail.com";
await settinsPage.ChangeEmail(newEmail);
await settinsPage.AssertChangeEmail();
await settingsPage.ChangeEmail(newEmail);
await settingsPage.AssertChangeEmail();

var confirmationEmail = await settinsPage.OpenConfirmationEmail();
var confirmationEmail = await settingsPage.OpenConfirmationEmail();
await confirmationEmail.AssertContent();

switch (mode)
{
case "Token":
var token = await confirmationEmail.GetToken();
await settinsPage.ConfirmByToken(token);
await settingsPage.ConfirmEmailByToken(token);
break;
case "InvalidToken":
await settinsPage.ConfirmByToken("111111");
await settinsPage.AssertInvalidToken();
return;
case "MagicLink":
settinsPage = await confirmationEmail.OpenMagicLink();
settingsPage = await confirmationEmail.OpenMagicLink();
break;
case "InvalidToken":
await settingsPage.ConfirmEmailByToken("111111");
await settingsPage.AssertEmailInvalidToken();
return;
case "TooManyRequests":
await settingsPage.ClickOnPhoneTab();
await settingsPage.ClickOnEmailTab();
await settingsPage.ChangeEmail(newEmail);
await settingsPage.AssertTooManyRequestsForChangeEmail();
return;
default:
throw new NotSupportedException();
}
await settinsPage.AssertConfirmSuccess();
await settingsPage.AssertConfirmEmailSuccess();

signInPage = await settinsPage.SignOut();
signInPage = await settingsPage.SignOut();
await signInPage.AssertOpen();
await signInPage.AssertSignOut();

await signInPage.SignIn(email);
await signInPage.SignInWithEmail(email);
await signInPage.AssertSignInFailed();

settinsPage = await signInPage.SignIn<SettingsPage>(newEmail);
await settinsPage.AssertSignInSuccess(newEmail, userFullName: null);
settingsPage = await signInPage.SignInWithEmail<SettingsPage>(newEmail);
await settingsPage.AssertSignInSuccess(newEmail, userFullName: null);
}

[TestMethod]
[DataRow("Token")]
[DataRow("InvalidToken")]
[DataRow("TooManyRequests")]
public async Task ChangePhone(string mode)
{
var email = await CreateNewUser();

var signInPage = new SignInPage(Page, WebAppServerAddress);

await signInPage.Open();
await signInPage.AssertOpen();

var identityHomePage = await signInPage.SignInWithEmail(email);
await identityHomePage.AssertSignInSuccess(email, userFullName: null);

var settingsPage = new SettingsPage(Page, WebAppServerAddress);

await settingsPage.Open();
await settingsPage.AssertOpen();

await settingsPage.ExpandAccount();
await settingsPage.ClickOnPhoneTab();
await settingsPage.AssertPhoneTab(null);

var phone = $"+1{Random.Shared.Next(1111111111, int.MaxValue)}";
await settingsPage.ChangePhone(phone);
await settingsPage.AssertChangePhone();

switch (mode)
{
case "Token":
var token = settingsPage.GetPhoneToken();
await settingsPage.ConfirmPhoneByToken(token);

await settingsPage.AssertConfirmPhoneSuccess();

signInPage = await settingsPage.SignOut();
await signInPage.AssertOpen();
await signInPage.AssertSignOut();

await signInPage.ClickOnPhoneTab();
await signInPage.AssertPhoneTab();

settingsPage = await signInPage.SignInWithPhone<SettingsPage>(phone);
await settingsPage.AssertSignInSuccess(email, userFullName: null);
return;
case "InvalidToken":
await settingsPage.ConfirmPhoneByToken("111111");
await settingsPage.AssertPhoneInvalidToken();
return;
case "TooManyRequests":
await settingsPage.ClickOnEmailTab();
await settingsPage.ClickOnPhoneTab();
await settingsPage.ChangePhone(phone);
await settingsPage.AssertTooManyRequestsForChangePhone();
return;
default:
throw new NotSupportedException();
}
}

private async Task<string> CreateNewUser()
{
await using var scope = TestServer.WebApp.Services.CreateAsyncScope();

var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();
var userService = new UserService(dbContext);
var email = $"{Guid.NewGuid()}@gmail.com";
await userService.AddUser(email);

return email;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ public partial class ConfirmationEmail<TPage>(IBrowserContext context, Uri serve
: TokenMagicLinkEmail<TPage>(context, serverAddress)
where TPage : RootLayout
{
protected override bool WaitForRedirectOnMagicLink => true;
protected override string EmailSubject => EmailStrings.ConfirmationEmailSubject.Replace("{0}", "\\d{6}");
protected override bool WaitForRedirectOnMagicLink => false;
protected override string EmailSubject => EmailStrings.ConfirmationEmailSubject.Replace("{0}", @"\b\d{6}\b");

protected override async Task AssertContentCore()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ public partial class ResetPasswordEmail(IBrowserContext context, Uri serverAddre
: TokenMagicLinkEmail<ResetPasswordPage>(context, serverAddress)
{
protected override bool WaitForRedirectOnMagicLink => false;
protected override string EmailSubject => EmailStrings.ResetPasswordEmailSubject.Replace("{0}", "\\d{6}");
protected override string EmailSubject => EmailStrings.ResetPasswordEmailSubject.Replace("{0}", @"\b\d{6}\b");

protected override async Task AssertContentCore()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public virtual async Task<string> GetToken()
{
Assert.IsNotNull(Page, OpenEmailFirstMessage);

var token = await Page.GetByText(new Regex("^\\d{6}$")).TextContentAsync();
var token = await Page.GetByText(new Regex(@"^\d{6}$")).TextContentAsync();
Assert.IsNotNull(token, "Confirmation token not found in email");
return token;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override async Task AssertOpen()
{
await Assertions.Expect(emailInput).ToBeVisibleAsync();
await Assertions.Expect(emailInput).ToBeDisabledAsync();
await Assertions.Expect(emailInput).ToBeEditableAsync(new() { Editable = false });
await Assertions.Expect(emailInput).Not.ToBeEditableAsync();
}
await Assertions.Expect(Page.GetByPlaceholder(AppStrings.EmailTokenPlaceholder)).ToBeVisibleAsync();
await Assertions.Expect(Page.GetByRole(AriaRole.Button, new() { Name = AppStrings.EmailTokenConfirmButtonText })).ToBeVisibleAsync();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Boilerplate.Tests.PageTests.PageModels.Email;
using System.Text.RegularExpressions;
using Boilerplate.Tests.PageTests.PageModels.Email;
using Boilerplate.Tests.PageTests.PageModels.Layout;

namespace Boilerplate.Tests.PageTests.PageModels.Identity;
Expand All @@ -24,7 +25,7 @@ public override async Task AssertOpen()
await Assertions.Expect(resetPasswordLink).ToHaveAttributeAsync("href", Urls.ResetPasswordPage);
}

public async Task<ResetPasswordPage> ForgotPassword(string email = "[email protected]")
public async Task<ResetPasswordPage> ForgotPassword(string email = TestData.DefaultTestEmail)
{
this.email = email;
await Page.GetByPlaceholder(AppStrings.EmailPlaceholder).FillAsync(email);
Expand All @@ -33,6 +34,17 @@ public async Task<ResetPasswordPage> ForgotPassword(string email = "test@bitplat
return new(Page, WebAppServerAddress) { EmailAddress = email };
}

public async Task AssertUserNotFound()
{
await Assertions.Expect(Page.GetByText(AppStrings.UserNotFound)).ToBeVisibleAsync();
}

public async Task AssertTooManyRequests()
{
var pattern = new Regex(AppStrings.WaitForResetPasswordTokenRequestResendDelay.Replace("{0}", ".*"));
await Assertions.Expect(Page.GetByText(pattern)).ToBeVisibleAsync();
}

public async Task<ResetPasswordEmail> OpenResetPasswordEmail()
{
Assert.IsNotNull(email, $"Call {nameof(ForgotPassword)} method first.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public override async Task AssertOpen()
{
await Assertions.Expect(emailInput).ToBeVisibleAsync();
await Assertions.Expect(emailInput).ToBeDisabledAsync();
await Assertions.Expect(emailInput).ToBeEditableAsync(new() { Editable = false });
await Assertions.Expect(emailInput).Not.ToBeEditableAsync();
}
await Assertions.Expect(Page.GetByPlaceholder(AppStrings.TokenPlaceholder)).ToBeVisibleAsync();
await Assertions.Expect(Page.GetByRole(AriaRole.Button, new() { Name = AppStrings.Continue })).ToBeVisibleAsync();
Expand Down
Loading

0 comments on commit 9e23ee1

Please sign in to comment.