Skip to content

Commit d0577f4

Browse files
authored
Update Project (#302)
* Completely refactored the entire solution to just be one .NET Standard 2 project with a unit test. * Updated dependencies to fix the issue pointed out by @danibjor, and re-added support for AppVeyor through the use of OpenCover. * Attempted to make AppVeyor support work properly. * Added AppVeyor code coverage analysis support. * Added AppVeyor Console unit testing support. * Corrected syntax formatting across all files in the Parse project, added NuGet package metadata to the Parse project because NuSpec file metadata declaration not supported for .NET Standard projects, added XML code documentation, and modified the AppVeyor configuration to upload the build-created NuGet package to the build console as an artifact. * Change project defaults to automatically use latest C# language version. Add EditorConfig configuration file for formatting normalization. * Normalize formatting for all files. * Organize loose ParseAnalytics and ParsePush files. Remove the need to reference Microsoft.DotNet.PlatformAbstractions and alter DeviceInfoController to reflect this change. * Organize loose ParseAnalytics and ParsePush files. Remove the need to reference Microsoft.DotNet.PlatformAbstractions and alter DeviceInfoController to reflect this change. Reformat some of the code and update Readme.md. * Update Readme.md * Update README.md * Add tests for ParseObjectCoder and Conversion utility. Tests will only be added to cover left over code; if some code in the classes being tested is covered by another test indirectly, a test will not be added for that code, for now. * Add extra conversion test. * Cover ParseAnalytics, and cover ParseACL some more. * Fix coverage errors * Fix coverage errors. * Removed dependecy on StandardStorage. * Fixed null wrapped StorageDictionary bug in StorageController. * Updated Parse project metadata and fixed namespace typo in testing assembly, also updated testing assembly target framework to the newer version of .NET Core, netcoreapp2.1. * Correct project structure mistake. * Undo disabled release configuration for Parse.Test.csproj because it makes no difference. * Added support for configuring storage settings, as well a static default fallback path that is used first before anything else is configured. Removed dependency on Microsoft.Extensions.PlatformAbstractions. Renamed some ParseClient.Configuration members, added MasterKey initialization parameter and reformatted some code. * Bump versioning * Fix to minor bug that prevented IdentifierBasedStorageConfiguration instances from generating file paths that already exist even when not in fallback mode. * Cleaned up ParseQuery constructor and fixed where clause chaining bug that only respects latest clause in chain. * Fix possible unintended behaviour change in ParseQuery skip parameter processing. * Fix typo. * Fix caching bug. * Documented some APIs, slightly refactored a few files, and updated test adapter for faster test times. * Removed unneeded dependency. * Updated metadata on Parse SDK project file, slightly changed versioning style in AppVeyor, slightly updated CONTRIBUTING.md, and udpated README.md.
1 parent 674a6a0 commit d0577f4

File tree

107 files changed

+1708
-1790
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+1708
-1790
lines changed

.appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: '2.0.0-{build}'
1+
version: '2.0.0-develop-{build}'
22
image: Visual Studio 2017
33
before_build:
44
- nuget restore Parse.sln

.editorconfig

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
[*]
2+
3+
end_of_line = crlf
4+
indent_style = space
5+
indent_size = tab
6+
tab_width = 4
7+
charset = utf-8
8+
trim_trailing_whitespace = true
9+
insert_final_newline = false
10+
max_line_length = off
11+
12+
13+
[*.cs]
14+
15+
dotnet_style_qualification_for_field = false : suggestion
16+
dotnet_style_qualification_for_property = false : suggestion
17+
dotnet_style_qualification_for_method = false : suggestion
18+
dotnet_style_qualification_for_event = false : suggestion
19+
20+
dotnet_style_predefined_type_for_locals_parameters_members = true : suggestion
21+
dotnet_style_predefined_type_for_member_access = false : suggestion
22+
23+
dotnet_style_require_accessibility_modifiers = never : suggestion
24+
25+
dotnet_style_object_initializer = true : suggestion
26+
dotnet_style_collection_initializer = true : suggestion
27+
28+
dotnet_style_explicit_tuple_names = true : suggestion
29+
dotnet_style_prefer_inferred_tuple_names = true : suggestion
30+
dotnet_style_prefer_inferred_anonymous_type_member_names = true : suggestion
31+
32+
dotnet_style_coalesce_expression = true : suggestion
33+
dotnet_style_null_propagation = true : suggestion
34+
35+
dotnet_sort_system_directives_first = true
36+
37+
csharp_preferred_modifier_order = public, private, protected, internal, static, extern, new, virtual, abstract, sealed, override, readonly, unsafe, volatile, async
38+
39+
csharp_style_var_for_built_in_types = false : suggestion
40+
csharp_style_var_when_type_is_apparent = false : suggestion
41+
csharp_style_var_elsewhere = false : suggestion
42+
43+
csharp_style_expression_bodied_methods = true : suggestion
44+
csharp_style_expression_bodied_constructors = true : suggestion
45+
csharp_style_expression_bodied_operators = true : suggestion
46+
csharp_style_expression_bodied_properties = true : suggestion
47+
csharp_style_expression_bodied_indexers = true : suggestion
48+
csharp_style_expression_bodied_accessors = true : suggestion
49+
50+
csharp_style_pattern_matching_over_is_with_cast_check = true : suggestion
51+
csharp_style_pattern_matching_over_as_with_null_check = true : suggestion
52+
53+
csharp_style_inlined_variable_declaration = true : suggestion
54+
55+
csharp_style_deconstructed_variable_declaration = true : suggestion
56+
csharp_style_pattern_local_over_anonymous_function = true
57+
58+
csharp_style_throw_expression = true : suggestion
59+
csharp_style_conditional_delegate_call = true : suggestion
60+
61+
csharp_prefer_simple_default_expression = true : suggestion
62+
63+
csharp_prefer_braces = false : suggestion
64+
65+
csharp_new_line_before_open_brace = all
66+
csharp_new_line_before_else = true
67+
csharp_new_line_before_catch = true
68+
csharp_new_line_before_finally = true
69+
csharp_new_line_before_members_in_object_initializers = true
70+
csharp_new_line_before_members_in_anonymous_types = true
71+
csharp_new_line_between_query_expression_clauses = true
72+
73+
csharp_indent_case_contents = true
74+
csharp_indent_switch_labels = true
75+
csharp_indent_labels = no_change
76+
77+
csharp_space_after_cast = true
78+
csharp_space_after_keywords_in_control_flow_statements = true
79+
csharp_space_between_method_declaration_parameter_list_parentheses = false
80+
csharp_space_between_method_call_parameter_list_parentheses = false
81+
csharp_space_between_parentheses = false
82+
83+
csharp_preserve_single_line_statements = false
84+
csharp_preserve_single_line_blocks = true

.nuget/NuGet.Config

Lines changed: 0 additions & 6 deletions
This file was deleted.

CONTRIBUTING.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe
4848
## Style Guide
4949
We're still working on providing a more concise code style for your IDE and getting a linter on GitHub, but for now try to keep the following:
5050

51-
* If you're developing on Visual Studio, please use `Parse.vssettings`.
5251
* We use [editorconfig](https://editorconfig.org) to manage basic editor settings, please install a compatible plugin for your preferred environment.
5352
* Most importantly, match the existing code style as much as possible.
5453
* Try to keep lines under 120 characters, if possible.
@@ -62,4 +61,4 @@ By contributing to Parse .NET SDK, you agree that your contributions will be lic
6261
[rest-api]: https://www.parse.com/docs/rest/guide
6362
[parse-api-console]: http://blog.parse.com/announcements/introducing-the-parse-api-console/
6463
[stacktrace-or-gtfo]: http://i.imgur.com/jacoj.jpg
65-
[tests-dir]: /ParseTest.Unit
64+
[tests-dir]: /Parse.Test

Parse.Test/ACLTests.cs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using Moq;
3+
using Parse.Core.Internal;
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Text;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
10+
namespace Parse.Test
11+
{
12+
[TestClass]
13+
public class ACLTests
14+
{
15+
[TestInitialize]
16+
public void SetUp()
17+
{
18+
ParseObject.RegisterSubclass<ParseUser>();
19+
ParseObject.RegisterSubclass<ParseSession>();
20+
}
21+
22+
[TestCleanup]
23+
public void TearDown() => ParseCorePlugins.Instance = null;
24+
25+
[TestMethod]
26+
public void TestCheckPermissionsWithParseUserConstructor()
27+
{
28+
ParseUser owner = GenerateUser("OwnerUser");
29+
ParseUser user = GenerateUser("OtherUser");
30+
ParseACL acl = new ParseACL(owner);
31+
Assert.IsTrue(acl.GetReadAccess(owner.ObjectId));
32+
Assert.IsTrue(acl.GetWriteAccess(owner.ObjectId));
33+
Assert.IsTrue(acl.GetReadAccess(owner));
34+
Assert.IsTrue(acl.GetWriteAccess(owner));
35+
}
36+
37+
[TestMethod]
38+
public void TestReadWriteMutationWithParseUserConstructor()
39+
{
40+
ParseUser owner = GenerateUser("OwnerUser");
41+
ParseUser otherUser = GenerateUser("OtherUser");
42+
ParseACL acl = new ParseACL(owner);
43+
acl.SetReadAccess(otherUser, true);
44+
acl.SetWriteAccess(otherUser, true);
45+
acl.SetReadAccess(owner.ObjectId, false);
46+
acl.SetWriteAccess(owner.ObjectId, false);
47+
Assert.IsTrue(acl.GetReadAccess(otherUser.ObjectId));
48+
Assert.IsTrue(acl.GetWriteAccess(otherUser.ObjectId));
49+
Assert.IsTrue(acl.GetReadAccess(otherUser));
50+
Assert.IsTrue(acl.GetWriteAccess(otherUser));
51+
Assert.IsFalse(acl.GetReadAccess(owner));
52+
Assert.IsFalse(acl.GetWriteAccess(owner));
53+
}
54+
55+
[TestMethod]
56+
public void TestParseACLCreationWithNullObjectIdParseUser() => Assert.ThrowsException<ArgumentException>(() => new ParseACL(GenerateUser(null)));
57+
58+
ParseUser GenerateUser(string objectID) => ParseObjectExtensions.FromState<ParseUser>(new MutableObjectState { ObjectId = objectID }, "_User");
59+
}
60+
}

Parse.Test/AnalyticsControllerTests.cs

Lines changed: 52 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -11,67 +11,78 @@
1111

1212
using Microsoft.VisualStudio.TestTools.UnitTesting;
1313

14-
namespace ParseTest
14+
namespace Parse.Test
1515
{
1616
[TestClass]
1717
public class AnalyticsControllerTests
1818
{
1919
[TestInitialize]
20-
public void SetUp() => ParseClient.Initialize(new ParseClient.Configuration { ApplicationId = "", WindowsKey = "" });
20+
public void SetUp() => ParseClient.Initialize(new ParseClient.Configuration { ApplicationID = "", Key = "" });
2121

2222
[TestMethod]
2323
[AsyncStateMachine(typeof(AnalyticsControllerTests))]
24-
public Task TestTrackEventWithEmptyDimension()
24+
public Task TestTrackEventWithEmptyDimensions()
2525
{
26-
var responseDict = new Dictionary<string, object>();
27-
var response = new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, responseDict);
28-
var mockRunner = CreateMockRunner(response);
26+
Mock<IParseCommandRunner> mockRunner = CreateMockRunner(new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, new Dictionary<string, object> { }));
2927

30-
var controller = new ParseAnalyticsController(mockRunner.Object);
31-
return controller.TrackEventAsync("SomeEvent",
32-
dimensions: null,
33-
sessionToken: null,
34-
cancellationToken: CancellationToken.None).ContinueWith(t =>
35-
{
36-
Assert.IsFalse(t.IsFaulted);
37-
Assert.IsFalse(t.IsCanceled);
38-
mockRunner.Verify(obj => obj.RunCommandAsync(It.Is<ParseCommand>(command => command.Uri.AbsolutePath == "/1/events/SomeEvent"),
39-
It.IsAny<IProgress<ParseUploadProgressEventArgs>>(),
40-
It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(),
41-
It.IsAny<CancellationToken>()), Times.Exactly(1));
42-
});
28+
return new ParseAnalyticsController(mockRunner.Object).TrackEventAsync("SomeEvent", dimensions: null, sessionToken: null, cancellationToken: CancellationToken.None).ContinueWith(t =>
29+
{
30+
Assert.IsFalse(t.IsFaulted);
31+
Assert.IsFalse(t.IsCanceled);
32+
mockRunner.Verify(obj => obj.RunCommandAsync(It.Is<ParseCommand>(command => command.Uri.AbsolutePath == "/1/events/SomeEvent"), It.IsAny<IProgress<ParseUploadProgressEventArgs>>(), It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
33+
});
34+
}
35+
36+
[TestMethod]
37+
[AsyncStateMachine(typeof(AnalyticsControllerTests))]
38+
public Task TestTrackEventWithNonEmptyDimensions()
39+
{
40+
Mock<IParseCommandRunner> mockRunner = CreateMockRunner(new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, new Dictionary<string, object> { }));
41+
42+
Dictionary<string, string> dimensions = new Dictionary<string, string> { ["njwerjk12"] = "5523dd" };
43+
44+
return new ParseAnalyticsController(mockRunner.Object).TrackEventAsync("SomeEvent", dimensions: dimensions, sessionToken: null, cancellationToken: CancellationToken.None).ContinueWith(t =>
45+
{
46+
Assert.IsFalse(t.IsFaulted);
47+
Assert.IsFalse(t.IsCanceled);
48+
mockRunner.Verify(obj => obj.RunCommandAsync(It.Is<ParseCommand>(command => command.Uri.AbsolutePath.Contains("/1/events/SomeEvent")), It.IsAny<IProgress<ParseUploadProgressEventArgs>>(), It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
49+
});
4350
}
4451

4552
[TestMethod]
4653
[AsyncStateMachine(typeof(AnalyticsControllerTests))]
4754
public Task TestTrackAppOpenedWithEmptyPushHash()
4855
{
49-
var responseDict = new Dictionary<string, object>();
50-
var response = new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, responseDict);
51-
var mockRunner = CreateMockRunner(response);
56+
Mock<IParseCommandRunner> mockRunner = CreateMockRunner(new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, new Dictionary<string, object>()));
57+
58+
return new ParseAnalyticsController(mockRunner.Object).TrackAppOpenedAsync(null, sessionToken: null, cancellationToken: CancellationToken.None).ContinueWith(t =>
59+
{
60+
Assert.IsFalse(t.IsFaulted);
61+
Assert.IsFalse(t.IsCanceled);
62+
mockRunner.Verify(obj => obj.RunCommandAsync(It.Is<ParseCommand>(command => command.Uri.AbsolutePath == "/1/events/AppOpened"), It.IsAny<IProgress<ParseUploadProgressEventArgs>>(), It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
63+
});
64+
}
65+
66+
[TestMethod]
67+
[AsyncStateMachine(typeof(AnalyticsControllerTests))]
68+
public Task TestTrackAppOpenedWithNonEmptyPushHash()
69+
{
70+
Mock<IParseCommandRunner> mockRunner = CreateMockRunner(new Tuple<HttpStatusCode, IDictionary<string, object>>(HttpStatusCode.Accepted, new Dictionary<string, object>()));
71+
72+
string pushHash = "32j4hll12lkk";
5273

53-
var controller = new ParseAnalyticsController(mockRunner.Object);
54-
return controller.TrackAppOpenedAsync(null,
55-
sessionToken: null,
56-
cancellationToken: CancellationToken.None).ContinueWith(t =>
57-
{
58-
Assert.IsFalse(t.IsFaulted);
59-
Assert.IsFalse(t.IsCanceled);
60-
mockRunner.Verify(obj => obj.RunCommandAsync(It.Is<ParseCommand>(command => command.Uri.AbsolutePath == "/1/events/AppOpened"),
61-
It.IsAny<IProgress<ParseUploadProgressEventArgs>>(),
62-
It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(),
63-
It.IsAny<CancellationToken>()), Times.Exactly(1));
64-
});
74+
return new ParseAnalyticsController(mockRunner.Object).TrackAppOpenedAsync(pushHash, sessionToken: null, cancellationToken: CancellationToken.None).ContinueWith(t =>
75+
{
76+
Assert.IsFalse(t.IsFaulted);
77+
Assert.IsFalse(t.IsCanceled);
78+
mockRunner.Verify(obj => obj.RunCommandAsync(It.IsAny<ParseCommand>(), It.IsAny<IProgress<ParseUploadProgressEventArgs>>(), It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(), It.IsAny<CancellationToken>()), Times.Exactly(1));
79+
});
6580
}
6681

67-
private Mock<IParseCommandRunner> CreateMockRunner(Tuple<HttpStatusCode, IDictionary<string, object>> response)
82+
Mock<IParseCommandRunner> CreateMockRunner(Tuple<HttpStatusCode, IDictionary<string, object>> response)
6883
{
69-
var mockRunner = new Mock<IParseCommandRunner>();
70-
mockRunner.Setup(obj => obj.RunCommandAsync(It.IsAny<ParseCommand>(),
71-
It.IsAny<IProgress<ParseUploadProgressEventArgs>>(),
72-
It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(),
73-
It.IsAny<CancellationToken>()))
74-
.Returns(Task<Tuple<HttpStatusCode, IDictionary<string, object>>>.FromResult(response));
84+
Mock<IParseCommandRunner> mockRunner = new Mock<IParseCommandRunner>();
85+
mockRunner.Setup(obj => obj.RunCommandAsync(It.IsAny<ParseCommand>(), It.IsAny<IProgress<ParseUploadProgressEventArgs>>(), It.IsAny<IProgress<ParseDownloadProgressEventArgs>>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(response));
7586

7687
return mockRunner;
7788
}

0 commit comments

Comments
 (0)