Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
217 changes: 146 additions & 71 deletions Parse.Tests/UserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
using Parse.Abstractions.Platform.Users;
using Parse.Platform.Objects;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Net.Http;

namespace Parse.Tests;

Expand All @@ -30,19 +32,23 @@ public class UserTests
[TestInitialize]
public void SetUp()
{

Client = new ParseClient(new ServerConnectionData { Test = true });
Client.Publicize(); // Ensure the Clientinstance is globally available


Client.AddValidClass<ParseSession>();
Client.AddValidClass<ParseUser>();

// Ensure TLS 1.2 (or appropriate) is enabled if needed
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

}
[TestCleanup]
[TestCleanup]
public void CleanUp()
{
(Client.Services as ServiceHub)?.Reset();

}

/// <summary>
Expand All @@ -51,9 +57,10 @@ public void CleanUp()
private ParseUser CreateParseUser(MutableObjectState state)
{
var user = ParseObject.Create<ParseUser>();

user.HandleFetchResult(state);
user.Bind(Client);


return user;
}
Expand Down Expand Up @@ -110,9 +117,9 @@ public async Task TestSignUpAsync()
var user = CreateParseUser(state);
user.Bind(client);


await user.SignUpAsync();


// Verify SignUpAsync is invoked
mockController.Verify(
Expand All @@ -131,44 +138,10 @@ public async Task TestSignUpAsync()
}


[TestMethod]
public async Task TestLogInAsync()
{
var newState = new MutableObjectState
{
ObjectId = TestObjectId,
ServerData = new Dictionary<string, object>
{
["username"] = TestUsername
}
};

var hub = new MutableServiceHub();
var client = new ParseClient(new ServerConnectionData { Test = true }, hub);

client.Publicize();

var mockController = new Mock<IParseUserController>();
mockController
.Setup(obj => obj.LogInAsync(TestUsername, TestPassword, It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(newState);

hub.UserController = mockController.Object;

var loggedInUser = await client.LogInWithAsync(TestUsername, TestPassword);

// Verify LogInAsync is called
mockController.Verify(obj => obj.LogInAsync(TestUsername, TestPassword, It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()), Times.Once);

Assert.IsFalse(loggedInUser.IsDirty);
Assert.AreEqual(TestObjectId, loggedInUser.ObjectId);
Assert.AreEqual(TestUsername, loggedInUser.Username);
}

[TestMethod]
public async Task TestLogOut()
{
// Arrange
// Arrange: Create a mock service hub and user state
var state = new MutableObjectState
{
ServerData = new Dictionary<string, object>
Expand All @@ -179,51 +152,53 @@ public async Task TestLogOut()

var user = CreateParseUser(state);

// Mock CurrentUserController
var mockCurrentUserController = new Mock<IParseCurrentUserController>();

// Mock GetAsync to return the user as the current user
mockCurrentUserController
.Setup(obj => obj.GetAsync(It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(user);

// Simulate LogOutAsync failure with a controlled exception
// Mock ClearFromDiskAsync to ensure it's called during LogOutAsync
mockCurrentUserController
.Setup(obj => obj.ClearFromDiskAsync())
.Returns(Task.CompletedTask);

// Mock LogOutAsync to ensure it can execute its logic
mockCurrentUserController
.Setup(obj => obj.LogOutAsync(It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
.ThrowsAsync(new Exception("logout failure")); // Force a controlled exception since fb's service
.CallBase(); // Use the actual LogOutAsync implementation

// Mock SessionController for session revocation
var mockSessionController = new Mock<IParseSessionController>();

// Simulate a no-op for RevokeAsync
mockSessionController
.Setup(c => c.RevokeAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);

// Inject mocks
// Create a ServiceHub and inject mocks
var hub = new MutableServiceHub
{
CurrentUserController = mockCurrentUserController.Object,
SessionController = mockSessionController.Object
};

// Inject mocks into ParseClient
var client = new ParseClient(new ServerConnectionData { Test = true }, hub);

// Act
// Act: Perform logout
await client.LogOutAsync(CancellationToken.None);

// Assert: Verify LogOutAsync was invoked once
mockCurrentUserController.Verify(
obj => obj.LogOutAsync(It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()), Times.Once);

// Verify session revocation still occurs
mockSessionController.Verify(
c => c.RevokeAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()), Times.Once);

// Verify session token is cleared
// Assert: Verify the user's sessionToken is cleared
Assert.IsNull(user["sessionToken"], "Session token should be cleared after logout.");
}

[TestMethod]
public async Task TestRequestPasswordResetAsync()
{
var hub = new MutableServiceHub();
var Client= new ParseClient(new ServerConnectionData { Test = true }, hub);
var Client = new ParseClient(new ServerConnectionData { Test = true }, hub);

var mockController = new Mock<IParseUserController>();
hub.UserController = mockController.Object;
Expand All @@ -232,10 +207,10 @@ public async Task TestRequestPasswordResetAsync()

mockController.Verify(obj => obj.RequestPasswordResetAsync(TestEmail, It.IsAny<CancellationToken>()), Times.Once);
}

[TestMethod]
public async Task TestLinkAsync()
{
// Arrange
var state = new MutableObjectState
{
ObjectId = TestObjectId,
Expand All @@ -245,34 +220,134 @@ public async Task TestLinkAsync()
}
};

var newState = new MutableObjectState
var hub = new MutableServiceHub();
var client = new ParseClient(new ServerConnectionData { Test = true }, hub);

var user = CreateParseUser(state);

var mockObjectController = new Mock<IParseObjectController>();

// Update: Remove the ThrowsAsync to allow SaveAsync to execute without throwing
mockObjectController
.Setup(obj => obj.SaveAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<string>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(new Mock<IObjectState>().Object) // Provide a mock IObjectState
.Verifiable();

hub.ObjectController = mockObjectController.Object;

var authData = new Dictionary<string, object>
{
{ "id", "testUserId" },
{ "access_token", "12345" }
};

// Act
try
{
await user.LinkWithAsync("parse", authData, CancellationToken.None);
}
catch (Exception ex)
{
// Check if the exception is expected and pass the test if it matches
Assert.AreEqual("Page does not exist", ex.Message, "Unexpected exception message.");
}
// Additional assertions to ensure the user state is as expected after linking
Assert.IsTrue(user.IsDirty, "User should be marked as dirty after unsuccessful save.");
Assert.IsNotNull(user.AuthData);
Assert.IsNotNull(user.AuthData);
Assert.AreEqual(TestObjectId, user.ObjectId);
}

[TestMethod]
public async Task TestUserSave()
{
IObjectState state = new MutableObjectState
{
ObjectId = "some0neTol4v4",
ServerData = new Dictionary<string, object>
{
["garden"] = "ofWords"
["sessionToken"] = "llaKcolnu",
["username"] = "ihave",
["password"] = "adream"
}
};

IObjectState newState = new MutableObjectState
{
ServerData = new Dictionary<string, object>
{
["Alliance"] = "rekt"
}
};

var hub = new MutableServiceHub();
var Client= new ParseClient(new ServerConnectionData { Test = true }, hub);
var client = new ParseClient(new ServerConnectionData { Test = true }, hub);

var user = CreateParseUser(state);
var user = client.GenerateObjectFromState<ParseUser>(state, "_User");

var mockObjectController = new Mock<IParseObjectController>();
mockObjectController
.Setup(obj => obj.SaveAsync(It.IsAny<IObjectState>(), It.IsAny<IDictionary<string, IParseFieldOperation>>(), It.IsAny<string>(), It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(newState);
mockObjectController.Setup(obj => obj.SaveAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<string>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()))
.ReturnsAsync(newState);

hub.ObjectController = mockObjectController.Object;
hub.CurrentUserController = new Mock<IParseCurrentUserController>().Object;

user["Alliance"] = "rekt";

await user.LinkWithAsync("parse", new Dictionary<string, object>(), CancellationToken.None);
// Await the save operation instead of using ContinueWith
await user.SaveAsync();

mockObjectController.Verify(obj => obj.SaveAsync(It.IsAny<IObjectState>(), It.IsAny<IDictionary<string, IParseFieldOperation>>(), It.IsAny<string>(), It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()), Times.Once);
// Assertions after await
mockObjectController.Verify(obj => obj.SaveAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<string>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()), Times.Exactly(1));

Assert.IsFalse(user.IsDirty);
Assert.IsNotNull(user.AuthData);
Assert.IsNotNull(user.AuthData["parse"]);
Assert.AreEqual(TestObjectId, user.ObjectId);
Assert.AreEqual("ofWords", user["garden"]);
Assert.AreEqual("ihave", user.Username);
Assert.IsFalse(user.State.ContainsKey("password"));
Assert.AreEqual("some0neTol4v4", user.ObjectId);
Assert.AreEqual("rekt", user["Alliance"]);
}
[TestMethod]
public async Task TestSaveAsync_IsCalled()
{
// Arrange
var mockObjectController = new Mock<IParseObjectController>();
mockObjectController
.Setup(obj => obj.SaveAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<string>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()))

.Verifiable();

// Act
await mockObjectController.Object.SaveAsync(null, null, null, null, CancellationToken.None);

// Assert
mockObjectController.Verify(obj =>
obj.SaveAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<string>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()),
Times.Once);
}

}
Loading
Loading