-
-
Notifications
You must be signed in to change notification settings - Fork 260
/
Copy pathUserTests.cs
350 lines (286 loc) · 11.5 KB
/
UserTests.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Parse.Abstractions.Infrastructure;
using Parse.Infrastructure;
using Parse.Abstractions.Infrastructure.Control;
using Parse.Abstractions.Platform.Objects;
using Parse.Abstractions.Platform.Sessions;
using Parse.Abstractions.Platform.Users;
using Parse.Platform.Objects;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Net.Http;
namespace Parse.Tests;
[TestClass]
public class UserTests
{
private const string TestSessionToken = "llaKcolnu";
private const string TestRevocableSessionToken = "r:llaKcolnu";
private const string TestObjectId = "some0neTol4v4";
private const string TestUsername = "ihave";
private const string TestPassword = "adream";
private const string TestEmail = "gogo@parse.com";
private ParseClient Client { get; set; }
[TestInitialize]
public void SetUp()
{
Client = new ParseClient(new ServerConnectionData { Test = true });
Client.Publicize(); // Ensure the Client instance is globally available
Client.AddValidClass<ParseSession>();
Client.AddValidClass<ParseUser>();
// Ensure TLS 1.2 (or appropriate) is enabled if needed
AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);
}
[TestCleanup]
public void CleanUp()
{
(Client.Services as ServiceHub)?.Reset();
}
/// <summary>
/// Factory method for creating ParseUser objects with the ServiceHub bound.
/// </summary>
private ParseUser CreateParseUser(MutableObjectState state)
{
var user = ParseObject.Create<ParseUser>();
user.HandleFetchResult(state);
user.Bind(Client);
return user;
}
[TestMethod]
public async Task TestSignUpWithInvalidServerDataAsync()
{
var state = new MutableObjectState
{
ServerData = new Dictionary<string, object>
{
["sessionToken"] = TestSessionToken
}
};
var user = CreateParseUser(state);
// Simulate invalid server data by ensuring username and password are not set
await Assert.ThrowsExceptionAsync<InvalidOperationException>(
async () => await user.SignUpAsync(),
"Expected SignUpAsync to throw an exception due to missing username or password."
);
}
[TestMethod]
public async Task TestSignUpAsync()
{
var state = new MutableObjectState
{
ServerData = new Dictionary<string, object>
{
["sessionToken"] = TestSessionToken,
["username"] = TestUsername,
["password"] = TestPassword
}
};
var newState = new MutableObjectState
{
ObjectId = TestObjectId
};
var hub = new MutableServiceHub();
var client = new ParseClient(new ServerConnectionData { Test = true }, hub);
var mockController = new Mock<IParseUserController>();
mockController
.Setup(obj => obj.SignUpAsync(It.IsAny<IObjectState>(), It.IsAny<IDictionary<string, IParseFieldOperation>>(), It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(newState);
hub.UserController = mockController.Object;
var user = CreateParseUser(state);
user.Bind(client);
await user.SignUpAsync();
// Verify SignUpAsync is invoked
mockController.Verify(
obj => obj.SignUpAsync(
It.IsAny<IObjectState>(),
It.IsAny<IDictionary<string, IParseFieldOperation>>(),
It.IsAny<IServiceHub>(),
It.IsAny<CancellationToken>()),
Times.Once
);
Assert.IsFalse(user.IsDirty);
Assert.AreEqual(TestUsername, user.Username);
Assert.IsFalse(user.State.ContainsKey("password"));
Assert.AreEqual(TestObjectId, user.ObjectId);
}
[TestMethod]
public async Task TestLogOut()
{
// Arrange: Create a mock service hub and user state
var state = new MutableObjectState
{
ServerData = new Dictionary<string, object>
{
["sessionToken"] = TestRevocableSessionToken
}
};
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);
// 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>()))
.CallBase(); // Use the actual LogOutAsync implementation
// Mock SessionController for session revocation
var mockSessionController = new Mock<IParseSessionController>();
mockSessionController
.Setup(c => c.RevokeAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
// 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: Perform logout
await client.LogOutAsync(CancellationToken.None);
// 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 mockController = new Mock<IParseUserController>();
hub.UserController = mockController.Object;
await Client.RequestPasswordResetAsync(TestEmail);
mockController.Verify(obj => obj.RequestPasswordResetAsync(TestEmail, It.IsAny<CancellationToken>()), Times.Once);
}
[TestMethod]
public async Task TestLinkAsync()
{
// Arrange
var state = new MutableObjectState
{
ObjectId = TestObjectId,
ServerData = new Dictionary<string, object>
{
["sessionToken"] = TestSessionToken
}
};
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>
{
["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 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);
hub.ObjectController = mockObjectController.Object;
hub.CurrentUserController = new Mock<IParseCurrentUserController>().Object;
user["Alliance"] = "rekt";
// Await the save operation instead of using ContinueWith
await user.SaveAsync();
// 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.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);
}
}