Skip to content

Commit

Permalink
Added tests to EmailPasswordClient (#3472)
Browse files Browse the repository at this point in the history
  • Loading branch information
papafe authored Nov 10, 2023
1 parent 13135ad commit 0497a66
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 3 deletions.
2 changes: 1 addition & 1 deletion Tests/Realm.Tests/Sync/SyncTestHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public static void RunBaasTestAsync(Func<Task> testFunc, int timeout = 30000)
Task.Delay(1000).Wait();
}

public static string GetVerifiedUsername() => $"realm_tests_do_autoverify-{Guid.NewGuid()}";
public static string GetVerifiedUsername() => $"realm_tests_do_autoverify-{Guid.NewGuid()}@g.it";

public static string GetUnconfirmedUsername() => $"realm_tests_do_not_confirm-{Guid.NewGuid()}@g.it";

Expand Down
80 changes: 79 additions & 1 deletion Tests/Realm.Tests/Sync/UserManagementTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ public void User_LinkCredentials_WhenInUse_Throws()
}

[Test]
public void User_RetryCustomConfirmationAsync_WorksInAllScenarios()
public void User_RetryCustomConfirmationAsync_RerunsConfirmation()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
Expand Down Expand Up @@ -435,6 +435,84 @@ public void User_RetryCustomConfirmationAsync_WorksInAllScenarios()
});
}

[Test]
public void User_ConfirmUserAsync_ConfirmsUser()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var unconfirmedMail = SyncTestHelpers.GetUnconfirmedUsername();
var credentials = Credentials.EmailPassword(unconfirmedMail, SyncTestHelpers.DefaultPassword);
// The first time the confirmation function is called we return "pending", so the user needs to be confirmed.
// At the same time we save the user email, token and tokenId in a collection.
await DefaultApp.EmailPasswordAuth.RegisterUserAsync(unconfirmedMail, SyncTestHelpers.DefaultPassword).Timeout(10_000, detail: "Failed to register user");
var ex = await TestHelpers.AssertThrows<AppException>(() => DefaultApp.LogInAsync(credentials));
Assert.That(ex.Message, Does.Contain("confirmation required"));
// This retrieves the token and tokenId we saved in the confirmation function
var functionUser = await GetUserAsync();
var result = await functionUser.Functions.CallAsync("confirmationInfo", unconfirmedMail);
var token = result["token"].AsString;
var tokenId = result["tokenId"].AsString;
await DefaultApp.EmailPasswordAuth.ConfirmUserAsync(token, tokenId);
var user = await DefaultApp.LogInAsync(credentials);
Assert.That(user.State, Is.EqualTo(UserState.LoggedIn));
});
}

[Test]
public void User_CallResetPasswordFunctionAsync_ResetsUserPassword()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var user = await GetUserAsync();
var email = user.Profile.Email!;
await user.LogOutAsync();
Assert.That(user.State, Is.EqualTo(UserState.Removed));
var newPassword = "realm_tests_do_reset-testPassword";
await DefaultApp.EmailPasswordAuth.CallResetPasswordFunctionAsync(email, newPassword);
user = await DefaultApp.LogInAsync(Credentials.EmailPassword(email, newPassword));
Assert.That(user.State, Is.EqualTo(UserState.LoggedIn));
});
}

[Test]
public void User_ResetPasswordAsync_ConfirmsResetPassword()
{
SyncTestHelpers.RunBaasTestAsync(async () =>
{
var user = await GetUserAsync();
var email = user.Profile.Email!;
await user.LogOutAsync();
Assert.That(user.State, Is.EqualTo(UserState.Removed));
// This returns "pending" the first time, so the password change is not valid yet. We save the token and tokenId
// passed to the reset function, to confirm the password change later.
var newPassword = "realm_tests_do_not_reset-testPassword";
await DefaultApp.EmailPasswordAuth.CallResetPasswordFunctionAsync(email, newPassword);
var ex = await TestHelpers.AssertThrows<AppException>(() => DefaultApp.LogInAsync(Credentials.EmailPassword(email, newPassword)));
Assert.That(ex.Message, Does.Contain("invalid username/password"));
// This retrieves the token and tokenId we saved in the password reset function.
var functionUser = await GetUserAsync();
var result = await functionUser.Functions.CallAsync("resetInfo", email);
var token = result["token"].AsString;
var tokenId = result["tokenId"].AsString;
await DefaultApp.EmailPasswordAuth.ResetPasswordAsync(newPassword, token, tokenId);
user = await DefaultApp.LogInAsync(Credentials.EmailPassword(email, newPassword));
Assert.That(user.State, Is.EqualTo(UserState.LoggedIn));
});
}

[Test]
public void User_JWT_LogsInAndReadsDataFromToken()
{
Expand Down
39 changes: 38 additions & 1 deletion Tools/DeployApps/BaasClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,32 @@ public class FunctionReturn
};";

private const string ResetFuncSource =
@"exports = ({ token, tokenId, username, password }) => {
@"exports = async function ({ token, tokenId, username, password, currentPasswordValid }) {
// process the reset token, tokenId, username and password
if (password.includes(""realm_tests_do_reset"")) {
return { status: 'success' };
}
if (password.includes(""realm_tests_do_not_reset"")) {
const mongodb = context.services.get('BackingDB');
let collection = mongodb.db('test_db').collection('not_reset');
let result = await collection.findOne({'email': username});
if(result === null)
{
let newVal = {
'email': username,
'token': token,
'tokenId': tokenId,
}
await collection.insertOne(newVal);
return { status: 'pending' };
}
return { status: 'success' };
}
// will not reset the password
return { status: 'fail' };
};";
Expand All @@ -148,6 +169,20 @@ public class FunctionReturn
}
};";

private const string ConfirmationInfoFuncSource =
@"exports = async function(username){
const mongodb = context.services.get('BackingDB');
let collection = mongodb.db('test_db').collection('not_confirmed');
return await collection.findOne({'email': username});
};";

private const string ResetPasswordInfoFuncSource =
@"exports = async function(username){
const mongodb = context.services.get('BackingDB');
let collection = mongodb.db('test_db').collection('not_reset');
return await collection.findOne({'email': username});
};";

private readonly HttpClient _client = new();

private readonly string? _clusterName;
Expand Down Expand Up @@ -302,6 +337,8 @@ private async Task<BaasApp> CreateDefaultApp(string name)
};");

await CreateFunction(app, "triggerClientResetOnSyncServer", TriggerClientResetOnSyncServerFuncSource, runAsSystem: true);
await CreateFunction(app, "confirmationInfo", ConfirmationInfoFuncSource, runAsSystem: true);
await CreateFunction(app, "resetInfo", ResetPasswordInfoFuncSource, runAsSystem: true);

await CreateFunction(app, "documentFunc", @"exports = function(first, second){
return {
Expand Down

0 comments on commit 0497a66

Please sign in to comment.