Skip to content

feat: Architectural Refactor of Dependency Injection and Query System #412

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from

Conversation

YBTopaz8
Copy link
Member

@YBTopaz8 YBTopaz8 commented Jul 26, 2025

PR Classification:

Major architectural improvement, new features, and increased test coverage.

PR Summary:

This is a major stability and quality-of-life release that overhauls the internal architecture of the SDK, making it more reliable and easier to use. It also lays the critical groundwork for future features like the Parse Local Datastore (LDS)!

BREAKING CHANGE ⚠️

If you have created a custom implementation of the IParseDataDecoder interface, its Decode method signature has changed. It no longer requires the IServiceHub parameter. Please update your implementation to match the new interface. This change was made to eliminate a common source of NullReferenceExceptions.

  • The IJsonConvertible.ConvertToJSON method now returns a strongly-typed IDictionary<string, object>.

New Features & Improvements

Easier Access to the Current User!
You can now get the current user with a simple shortcut:

ParseUser currentUser = ParseClient.Instance.CurrentUser;
  • Added over 50 new unit tests covering the entire query pipeline, user management, and internal helper utilities. This means a more stable and reliable SDK for your production apps.

Foundation for Offline Storage (LDS): The SDK can now fully understand all server-side data operations (Increment, AddUnique, etc.). This is the first and most important step toward enabling full offline data caching and synchronization. Stay tuned!

Summary by CodeRabbit

  • New Features

    • Added support for combining multiple queries with a logical OR condition.
    • Introduced new unit tests for attribute handling, geo distance, query controllers, query building, internal extensions, Parse operations, and transient cache behavior.
  • Bug Fixes

    • Improved error handling for HTTP responses, including detailed handling for various status codes and error payloads.
    • Enhanced exception precision in tests and encoding logic.
  • Refactor

    • Streamlined and localized test setup and teardown across many test classes.
    • Centralized service access within data decoders and encoders.
    • Improved test isolation and coverage for ACL, user, and object state scenarios.
  • Chores

    • Upgraded test project dependencies for improved test reliability and coverage.
    • Removed obsolete or redundant test methods and formatting/comment cleanups.
  • Documentation

    • Improved test descriptions and added more comprehensive test coverage for edge cases and error conditions.
  • Style

    • Formatting and whitespace adjustments in test files for readability.

These updates enhance reliability, maintainability, and test coverage across the platform.

YBTopaz8 added 14 commits July 26, 2025 08:05
Updated the IParseCurrentUserController interface to include a new CurrentUser property that returns a ParseUser object. This enhancement allows direct access to the current user while keeping existing method signatures unchanged.
Updated `ParseObjectIdComparer` to be a readonly static field for better efficiency. Enhanced the `Decode` method to support additional operations such as "Add", "AddUnique", "Remove", "AddRelation", "RemoveRelation", and "Batch". Added XML documentation for improved clarity and maintainability.
Updated `ParseDataDecoder` to utilize `IServiceHub` for improved access to `ClassController`. Modified the constructor and enhanced the `Decode` method to support new functionality. Added clarifying comments in `ParseObjectCoder` regarding the `Encode` method and its usage context.
- Introduced a static `Or` method to combine multiple queries
  using a logical OR operation, ensuring all queries are for
  the same class.

- Implemented `GetHashCode` to generate a unique hash code
  based on relevant properties, replacing the previous placeholder.
- Added `Services` property to `CustomServiceHub` for better access to service instances.
- Replaced `CurrentUser` property with a reference to `Services.CurrentUserController.CurrentUser`.
- Updated `Decoder` initialization in `LateInitializedMutableServiceHub` to use `this`.
- Changed `Decoder` handling in `MutableServiceHub` and `ServiceHub` for improved encapsulation.
- Added new using directives in `ParseClient.cs` and removed unused ones.
- Introduced `FinalizeDecoder` method in `ParseClient` for proper decoder initialization.
- Modified `FetchAsyncInternal` in `ParseUser` to ensure correct fetching behavior.
- Removed commented-out `SessionToken` and added `AuthData` property for authentication management.
Removed the IServiceHub parameter from the Decode method, simplifying its interface to only require the object data parameter.

Refactor decoding logic in ParseCloudCodeController and ParseConfiguration

Removed the `serviceHub` parameter from the `Decoder.Decode` method calls in both `ParseCloudCodeController.cs` and `ParseConfiguration.cs`.

# This is a Breaking Change.
At least to simplify method calls.
Removed `serviceHub` parameter from method signatures across multiple classes, replacing it with `this.Services` for improved encapsulation and consistency.

Simplified object decoding in `ParseFieldOperations` by eliminating unnecessary parameters. Updated `ParseDataDecoder` and `ParseDataEncoder` to utilize the new service access pattern. Ensured `ParseObjectCoder` aligns with these changes for uniformity across the codebase.
Updated the `ConvertToJSON` method in multiple classes implementing the `IJsonConvertible` interface to return an `IDictionary<string, object>` instead of an `object`. This change improves the method's capability to generate structured JSON-compatible representations, accommodating more complex data structures. A new `ConvertValueToJSON` method was also added to the `ParseSetOperation` class to assist in converting values to JSON format.
Removed the IServiceHub parameter from Decode method calls in CloudTests, ConfigTests, and DecoderTests to simplify method signatures. Updated assertions in tests to ensure expected outcomes are maintained. Improved readability in GeoPointTests by formatting Decode method calls.
- Added necessary using directives in UserTests.cs.
- Enhanced `TestLogOut` method with new mock setups for user logout functionality.
- Introduced `HeadersContainSessionToken` method for header verification.
- Removed unused `Decoder` initialization in MutableServiceHub.cs.
- Updated `ConversionTests.cs` to use `Assert.ThrowsExactly` for better exception specificity.
- Added `InternalExtensionsTests.cs` with tests for utility methods like `Safe()`, `GetOrDefault()`, and `OnSuccess()`.
- Updated `Parse.Tests.csproj` to include `coverlet.collector` for code coverage analysis.
- Introduced `ParseQueryExtensionsTests.cs` to validate LINQ operator translations in `ParseQuery`.
- Removed a warning directive in `ProgressTests.cs` without functional changes.
- Added `TransientCacheControllerTests.cs` to test cache functionality, including add, remove, and clear operations.
- Modified `UserTests.cs` to add tests for missing properties during sign-up and ensure password removal from server data.
…ndRunner error handling and JSON support

Added new using directives for JSON serialization and Parse namespaces. Improved handling of HTTP response codes, specifically for 100, 201, 400, 401, 403, and 404. Implemented deserialization of error payloads for 400 responses, with appropriate exception handling. Updated 404 response to include more context in the exception message. Retained comment on the removal of the installationFetchTask variable due to async/await simplifications.

Updated `ParseFailureException` to include a new error code `BadRequest` (400) with XML documentation. Introduced `ParseErrorPayload` class with properties `code` (int) and `error` (string) for better error handling.
Updated `ParseQueryControllerTests` to remove `mockDecoder` in favor of `serviceHub.Decoder`, with corresponding changes to the setup method and test assertions. Removed several test methods for simplification.

Deleted `ParseQueryExtensionsTests` as part of consolidation of tests.

Introduced `ParseQueryTests` with comprehensive tests for the `ParseQuery` class, covering various query methods and ensuring proper interaction with `IServiceHub`. This enhances the overall test coverage.
Updated `DecoderTests.cs` to include tests for Increment, Delete, Add, AddUnique, and Remove operations. Reformatted existing primitive decoding tests for consistency. Modified `ParseObject` instantiation in `TestDecodeDictionary` to pass `Client` as a parameter.
- Updated `ACLTests.cs` with new tests for `ParseACL` class.
- Removed unnecessary code in `AnalyticsTests.cs` and added warnings.
- Introduced `AttributeTests.cs` for testing various attributes.
- Refactored `CloudControllerTests.cs` to improve clarity and mock usage.
- Enhanced clarity and consistency in `ConfigTests.cs` and `ConversionTests.cs`.
- Added new tests in `EncoderTests.cs` for `ParseObject` encoding.
- Created `GeoDistanceTest.cs` for testing `ParseGeoDistance` class.
- Improved organization and exception handling in `GeoPointTests.cs`, `InternalExtensionsTests.cs`, and `ProgressTests.cs`.
- Updated `ObjectCoderTests.cs` and `ObjectControllerTests.cs` for better test clarity.
- Added new tests in `ObjectStateTests.cs` for cloning and decoding.
- Introduced `ParseOperationsTests.cs` for various operation tests.
- Enhanced clarity and exception handling in `ParseQueryTests.cs` and `RelationTests.cs`.
- Improved organization and initialization in `UserTests.cs`.
Copy link

parse-github-assistant bot commented Jul 26, 2025

🚀 Thanks for opening this pull request!

Copy link

coderabbitai bot commented Jul 26, 2025

📝 Walkthrough

Walkthrough

This update introduces extensive changes to both the Parse SDK and its test suite. The core SDK refactors the data decoding pipeline, standardizes JSON conversion return types to IDictionary<string, object>, and enhances error handling for HTTP responses. The test suite receives new and refactored tests, improved isolation, and coverage for previously untested scenarios. Several internal APIs are updated to streamline dependencies and clarify method contracts.

Changes

File(s) / Group Change Summary
Parse.Tests/ACLTests.cs Expanded ACL unit tests: added scenarios for permissions, roles, error handling, and JSON conversion.
Parse.Tests/AnalyticsTests.cs, Parse.Tests/CloudControllerTests.cs, Parse.Tests/CloudTests.cs, Parse.Tests/ConfigTests.cs, Parse.Tests/GeoPointTests.cs, Parse.Tests/ObjectControllerTests.cs, Parse.Tests/ObjectTests.cs, Parse.Tests/ProgressTests.cs Refactored test setup/teardown, improved isolation, updated or removed shared fields, and adjusted decoder calls.
Parse.Tests/AttributeTests.cs, Parse.Tests/GeoDistanceTest.cs, Parse.Tests/InternalExtensionsTests.cs, Parse.Tests/ParseOperationsTests.cs, Parse.Tests/ParseQueryControllerTests.cs, Parse.Tests/ParseQueryTests.cs, Parse.Tests/TransientCacheControllerTests.cs Added new test classes covering attributes, geo distance, internal extensions, Parse operations, query controller, query building, and transient cache.
Parse.Tests/DecoderTests.cs, Parse.Tests/EncoderTests.cs, Parse.Tests/ObjectCoderTests.cs, Parse.Tests/ObjectStateTests.cs, Parse.Tests/UserTests.cs Added or expanded tests for decoding, encoding, object controller, object state, and user behaviors; improved coverage and edge case validation.
Parse.Tests/RelationTests.cs Removed all but one test; deleted user relation management helpers and tests.
Parse.Tests/Parse.Tests.csproj Updated test dependencies: added coverlet.collector, upgraded MSTest and Microsoft.NET.Test.Sdk.
Parse/Abstractions/Infrastructure/CustomServiceHub.cs, Parse/Abstractions/Platform/Users/IParseCurrentUserController.cs Added CurrentUser property to service hub and user controller interfaces.
Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs, Parse/Infrastructure/Data/ParseDataDecoder.cs, Parse/Infrastructure/LateInitializedMutableServiceHub.cs, Parse/Infrastructure/MutableServiceHub.cs, Parse/Infrastructure/ServiceHub.cs, Parse/Platform/Cloud/ParseCloudCodeController.cs, Parse/Platform/Configuration/ParseConfiguration.cs Refactored decoder pipeline: removed serviceHub parameter from Decode, injected service hub, updated decoder initialization and usage.
Parse/Abstractions/Infrastructure/IJsonConvertible.cs, Parse/Infrastructure/Control/ParseAddOperation.cs, Parse/Infrastructure/Control/ParseAddUniqueOperation.cs, Parse/Infrastructure/Control/ParseDeleteOperation.cs, Parse/Infrastructure/Control/ParseIncrementOperation.cs, Parse/Infrastructure/Control/ParseRelationOperation.cs, Parse/Infrastructure/Control/ParseRemoveOperation.cs, Parse/Infrastructure/Control/ParseSetOperation.cs, Parse/Platform/Configuration/ParseConfiguration.cs, Parse/Platform/Files/ParseFile.cs, Parse/Platform/Location/ParseGeoPoint.cs, Parse/Platform/Relations/ParseRelation.cs, Parse/Platform/Security/ParseACL.cs Standardized ConvertToJSON return type to IDictionary<string, object> across all relevant entities.
Parse/Infrastructure/Control/ParseFieldOperations.cs Implemented Decode method for field operations; added static comparer property.
Parse/Infrastructure/Data/ParseDataEncoder.cs Refactored dictionary encoding logic, consolidated methods, improved handling of nested and primitive types.
Parse/Infrastructure/Data/ParseObjectCoder.cs Simplified decoder calls, minor refactorings for clarity.
Parse/Infrastructure/Execution/ParseCommandRunner.cs Enhanced HTTP response handling: added explicit error code mapping, improved error payload extraction, and comprehensive status code processing.
Parse/Infrastructure/ParseFailureException.cs Added BadRequest error code and ParseErrorPayload class for error details.
Parse/Platform/ParseClient.cs Ensured recursive decoder initialization for all service hubs during client construction.
Parse/Platform/Queries/ParseQuery.cs Added static Or method for query composition and implemented GetHashCode.
Parse/Platform/Users/ParseUser.cs Removed obsolete commented code.
Parse/Utilities/ParseQueryExtensions.cs Removed commented-out code in query normalization logic.

Sequence Diagram(s)

sequenceDiagram
    participant Client as ParseClient
    participant Hub as ServiceHub/MutableServiceHub
    participant Decoder as ParseDataDecoder
    participant Controller as ParseCloudCodeController
    participant Runner as ParseCommandRunner
    participant Server as HTTP Server

    Client->>Hub: Initialize services
    Client->>Decoder: Ensure Decoder is set for each hub
    Controller->>Runner: Prepare and send command
    Runner->>Server: HTTP request
    Server-->>Runner: HTTP response (status, content)
    Runner->>Runner: Handle status codes (200, 400, 401, 403, 404, 410, 5xx)
    alt Success (200/201)
        Runner->>Decoder: Decode response data
        Decoder->>Hub: Access ClassController as needed
        Decoder-->>Controller: Return decoded result
        Controller-->>Client: Return result
    else Error (400/401/403/404/410/5xx)
        Runner-->>Controller: Throw ParseFailureException (with error code/message)
        Controller-->>Client: Propagate exception
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40–60 minutes

Complexity:

  • Broad refactoring of the decoding/encoding pipeline and error handling.
  • Standardization of JSON serialization interfaces.
  • Numerous new and updated unit tests, including new classes and expanded coverage.
  • Significant changes to test isolation, dependency injection, and error scenarios.
  • Some breaking changes to method signatures and interface contracts.
  • High-impact changes to core SDK control and data flow.

Estimated review time:
Reviewers should expect to spend significant time verifying interface changes, test coverage, error handling logic, and the consistency of SDK and test suite updates.

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1023430 and b342554.

📒 Files selected for processing (2)
  • Parse/Infrastructure/Execution/ParseCommandRunner.cs (2 hunks)
  • Parse/Infrastructure/ParseFailureException.cs (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • Parse/Infrastructure/ParseFailureException.cs
  • Parse/Infrastructure/Execution/ParseCommandRunner.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: .NET 9.0
  • GitHub Check: .NET 8.0

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@YBTopaz8 YBTopaz8 self-assigned this Jul 26, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 13

🔭 Outside diff range comments (2)
Parse/Platform/Location/ParseGeoPoint.cs (1)

61-61: Fix incorrect debug message in longitude setter.

The debug message shows "Invalid Latitude" but should be "Invalid Longitude" since this is in the longitude setter.

-                Debug.WriteLine($"Invalid Latitude: {value}");
+                Debug.WriteLine($"Invalid Longitude: {value}");
Parse.Tests/ParseQueryTests.cs (1)

224-224: Fix typo in variable name

-        var Client= new ParseClient(new ServerConnectionData { Test = true }, hub);
+        var Client = new ParseClient(new ServerConnectionData { Test = true }, hub);
🧹 Nitpick comments (29)
Parse/Infrastructure/Data/ParseObjectCoder.cs (1)

4-4: Remove unused import.

The System.Diagnostics import appears to be unused in this file.

-using System.Diagnostics;
Parse/Platform/Queries/ParseQuery.cs (1)

8-8: Cosmetic change - unnecessary blank line addition.

This blank line addition doesn't add value and may have been added accidentally.

Parse.Tests/CloudControllerTests.cs (1)

16-16: Address the refactoring warning comment.

The warning indicates incomplete refactoring work. Ensure this class refactoring is completed before merging to production.

Would you like me to help identify what aspects of the refactoring still need completion?

Parse.Tests/TransientCacheControllerTests.cs (2)

18-32: Consider testing edge cases and improving assertion robustness.

The test correctly validates basic add/retrieve functionality, but consider these improvements:

  • Test with null values and empty strings
  • Use more specific assertions (e.g., Assert.AreEqual("testValue", result.ToString()) if result could be of different types)
  • Consider testing with different data types beyond strings
[TestMethod]
[Description("Tests that the cache controller can add and then retrieve a value.")]
public async Task LoadAsync_AddAsync_CanRetrieveValue()
{
    // Arrange
    var cacheController = new TransientCacheController();
    var initialCache = await cacheController.LoadAsync();

    // Act
    await initialCache.AddAsync("testKey", "testValue");
    var finalCache = await cacheController.LoadAsync();
-   finalCache.TryGetValue("testKey", out var result);
+   bool found = finalCache.TryGetValue("testKey", out var result);

    // Assert
+   Assert.IsTrue(found, "Key should be found in cache");
    Assert.IsNotNull(result);
    Assert.AreEqual("testValue", result);
}

54-68: Consider testing cache state before clearing.

While the test correctly validates that Clear empties the cache, it could be more robust by also asserting the initial state.

// Act
+   // Verify cache has items before clearing
+   var preCache = await cacheController.LoadAsync();
+   Assert.AreEqual(2, preCache.Count, "Cache should contain 2 items before clearing");
+   
    cacheController.Clear();
    var finalCache = await cacheController.LoadAsync();
Parse.Tests/GeoDistanceTest.cs (2)

22-28: Consider using named constants for Earth radius values.

The hardcoded value 3958.8 (Earth's radius in miles) should ideally match the actual constant used in the implementation to avoid test brittleness.

Consider extracting the conversion constants or verifying they match the implementation:

[TestMethod]
[Description("Tests the Miles conversion using a given Radians.")]
public void Miles_ReturnsCorrectValue()  
{
    double radians = 2.5;
    ParseGeoDistance distance = new ParseGeoDistance(radians);
-   double expected = radians * 3958.8;
+   // Use the same constant as the implementation
+   const double EARTH_RADIUS_MILES = 3958.8; // Should match ParseGeoDistance.EARTH_RADIUS_MILES
+   double expected = radians * EARTH_RADIUS_MILES;
    Assert.AreEqual(expected, distance.Miles);
}

32-39: Same constant concern applies to kilometers conversion.

Similar to the miles test, ensure the kilometers constant matches the implementation.

double radians = 2.5;
ParseGeoDistance distance = new ParseGeoDistance(radians);
-double expected = radians * 6371.0;
+const double EARTH_RADIUS_KM = 6371.0; // Should match ParseGeoDistance.EARTH_RADIUS_KM
+double expected = radians * EARTH_RADIUS_KM;
Parse.Tests/AttributeTests.cs (1)

47-47: Remove trailing comment.

The comment // 1 at the end of the method name appears to be leftover from development.

-public void PreserveWrapperTypes_HasCorrectlyAOTTypesRegistered()// 1
+public void PreserveWrapperTypes_HasCorrectlyAOTTypesRegistered()
Parse.Tests/AnalyticsTests.cs (1)

24-36: Consider extracting common mock setup.

All three test methods have similar mock setup patterns. Consider extracting this to a helper method to reduce duplication.

+private (MutableServiceHub hub, ParseClient client, Mock<IParseAnalyticsController> mockController) SetupTestEnvironment()
+{
+    var hub = new MutableServiceHub();
+    var client = new ParseClient(new ServerConnectionData { Test = true }, hub);
+    var mockController = new Mock<IParseAnalyticsController>();
+    var mockCurrentUserController = new Mock<IParseCurrentUserController>();
+    
+    mockCurrentUserController
+        .Setup(controller => controller.GetCurrentSessionTokenAsync(It.IsAny<IServiceHub>(), It.IsAny<CancellationToken>()))
+        .ReturnsAsync("sessionToken");
+    
+    hub.AnalyticsController = mockController.Object;
+    hub.CurrentUserController = mockCurrentUserController.Object;
+    
+    return (hub, client, mockController);
+}

[TestMethod]
public async Task TestTrackEvent()
{
    // Arrange
-   var hub = new MutableServiceHub();
-   var client = new ParseClient(new ServerConnectionData { Test = true }, hub);
-   var mockController = new Mock<IParseAnalyticsController>();
-   var mockCurrentUserController = new Mock<IParseCurrentUserController>();
-   // ... rest of setup
+   var (hub, client, mockController) = SetupTestEnvironment();
Parse/Platform/Configuration/ParseConfiguration.cs (1)

4-4: Remove unnecessary empty using statement

The added empty line in the using statements section doesn't serve any purpose.

-using System.Diagnostics;
-
-using Parse.Abstractions.Infrastructure;
+using System.Diagnostics;
+using Parse.Abstractions.Infrastructure;
Parse/Infrastructure/Execution/ParseCommandRunner.cs (1)

122-122: Fix error message formatting

The error message has spacing issues around the concatenation.

-            throw new ParseFailureException(ParseFailureException.ErrorCode.ERROR404, "Error 404 " +response.Item1+ response.Item2);
+            throw new ParseFailureException(ParseFailureException.ErrorCode.ERROR404, $"Error 404: {response.Item1} {response.Item2}");
Parse.Tests/DecoderTests.cs (1)

3-4: Remove unnecessary empty lines

Multiple empty lines have been added unnecessarily.

-using System.Linq;
-
-using Microsoft.VisualStudio.TestTools.UnitTesting;
-
-using Parse.Abstractions.Internal;
+using System.Linq;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using Parse.Abstractions.Internal;

Also applies to: 6-6

Parse.Tests/ObjectCoderTests.cs (1)

107-121: Consider making ExecuteBatchRequests_EmptyList test async for consistency.

The test correctly validates empty batch request handling, but since other tests in this class are async and this method likely returns a Task, consider making this test async as well for consistency.

     [TestMethod]
     [Description("Tests that ExecuteBatchRequests correctly handles empty list.")]
-    public void ExecuteBatchRequests_EmptyList()
+    public async Task ExecuteBatchRequests_EmptyList()
     {
         var mockCommandRunner = new Mock<IParseCommandRunner>();
         var mockDecoder = new Mock<IParseDataDecoder>();
         var mockServiceHub = new Mock<IServiceHub>();
         ParseObjectController controller = new ParseObjectController(mockCommandRunner.Object, mockDecoder.Object, new ServerConnectionData());
         IList<ParseCommand> emptyList = new List<ParseCommand>();

-        var task = controller.ExecuteBatchRequests(emptyList, "session", CancellationToken.None);
+        var task = await controller.ExecuteBatchRequests(emptyList, "session", CancellationToken.None);

         Assert.AreEqual(0, task.Count);
     }
Parse.Tests/ParseOperationsTests.cs (8)

3-3: Remove unused import

The System.Diagnostics import is not used in this test file.

-using System.Diagnostics;

5-6: Remove unused imports

The System.Text and System.Threading.Tasks imports are not used in this test file.

-using System.Text;
-using System.Threading.Tasks;

31-33: Remove extra blank line

         Assert.IsTrue(new List<object> { 1, 2 }.SequenceEqual(result.Value as List<object>));
-
     }

54-61: Remove extra blank lines

         Assert.IsTrue(new List<object> { 1, 4, 5, 2, 3 }.SequenceEqual(result as List<object>));
-
-
         var operation2 = new ParseAddUniqueOperation(new object[] { 4, 6, 7 });
         var result2 = operation2.Apply(null, "testKey");
-
         Assert.IsTrue(new List<object> { 4, 6, 7 }.SequenceEqual(result2 as List<object>));
-
     }

99-101: Remove extra blank line

         Assert.IsTrue(new List<object> { 1, 2 }.SequenceEqual(result.Value as List<object>));
-
     }

122-128: Remove extra blank lines

         Assert.IsTrue(new List<object> { 1, 4, 5, 2, 3 }.SequenceEqual(result as List<object>));
-
         var operation2 = new ParseAddOperation(new object[] { 1, 4, 5, 6 });
         var result2 = operation2.Apply(null, "testKey");
-
         Assert.IsTrue(new List<object> { 1, 4, 5, 6 }.SequenceEqual(result2 as List<object>));

148-160: Remove extra blank lines

         Assert.AreEqual(operation, result);
-
         result = operation.MergeWithPrevious(ParseDeleteOperation.Instance);
         Assert.AreEqual(operation, result);
         result = operation.MergeWithPrevious(new ParseAddOperation(new List<object> { 1 }));
         Assert.AreEqual(operation, result);
-
         result = operation.MergeWithPrevious(new ParseAddUniqueOperation(new List<object> { 1 }));
         Assert.AreEqual(operation, result);
-
         result = operation.MergeWithPrevious(null);

198-200: Remove extra blank line

         Assert.AreEqual(operation, result);
-
     }
Parse.Tests/ParseQueryTests.cs (3)

2-2: Remove unused import

The System.Collections import is not used in this test file.

-using System.Collections;

5-6: Remove unused imports

The System.Text and System.Text.RegularExpressions imports are not needed since Regex is fully qualified in the code.

-using System.Text;
-using System.Text.RegularExpressions;

216-219: Remove extra blank lines

         Assert.AreEqual(2, (innerWithin["$box"] as IEnumerable).Cast<object>().Count());
-
-
     }
Parse/Infrastructure/Data/ParseDataEncoder.cs (3)

6-6: Remove unused import

The System.Runtime.ExceptionServices import is not used in this file.

-using System.Runtime.ExceptionServices;

150-151: Improve method name for clarity

The method name EncodeDictionaryStringDict is unclear. Consider a more descriptive name that reflects it handles nested dictionaries.

-    // Add a specialized method to handle double-only dictionaries
-    private object EncodeDictionaryStringDict(IDictionary<string, IDictionary<string, object>> dictionary, IServiceHub serviceHub)
+    // Encode dictionaries with nested dictionary values
+    private object EncodeNestedDictionary(IDictionary<string, IDictionary<string, object>> dictionary, IServiceHub serviceHub)

79-79: Update method call if rename is accepted

If the method is renamed, update this call as well.

-            IDictionary<string, IDictionary<string, object>> dictionary => EncodeDictionaryStringDict(dictionary, serviceHub),
+            IDictionary<string, IDictionary<string, object>> dictionary => EncodeNestedDictionary(dictionary, serviceHub),
Parse.Tests/UserTests.cs (2)

3-5: Remove unused imports

The System.Diagnostics and System.Net.Http imports appear to be unused in this test file.

-using System.Diagnostics;
-using System.Net.Http;
 using System.Runtime.CompilerServices;

5-5: Remove unused import

The System.Runtime.CompilerServices import is not used in this test file.

-using System.Runtime.CompilerServices;
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a9c1855 and a083849.

📒 Files selected for processing (54)
  • Parse.Tests/ACLTests.cs (7 hunks)
  • Parse.Tests/AnalyticsTests.cs (1 hunks)
  • Parse.Tests/AttributeTests.cs (1 hunks)
  • Parse.Tests/CloudControllerTests.cs (4 hunks)
  • Parse.Tests/CloudTests.cs (2 hunks)
  • Parse.Tests/ConfigTests.cs (5 hunks)
  • Parse.Tests/ConversionTests.cs (1 hunks)
  • Parse.Tests/DecoderTests.cs (13 hunks)
  • Parse.Tests/EncoderTests.cs (6 hunks)
  • Parse.Tests/GeoDistanceTest.cs (1 hunks)
  • Parse.Tests/GeoPointTests.cs (1 hunks)
  • Parse.Tests/InternalExtensionsTests.cs (1 hunks)
  • Parse.Tests/ObjectCoderTests.cs (2 hunks)
  • Parse.Tests/ObjectControllerTests.cs (1 hunks)
  • Parse.Tests/ObjectStateTests.cs (2 hunks)
  • Parse.Tests/ObjectTests.cs (31 hunks)
  • Parse.Tests/Parse.Tests.csproj (1 hunks)
  • Parse.Tests/ParseOperationsTests.cs (1 hunks)
  • Parse.Tests/ParseQueryControllerTests.cs (1 hunks)
  • Parse.Tests/ParseQueryTests.cs (1 hunks)
  • Parse.Tests/ProgressTests.cs (3 hunks)
  • Parse.Tests/RelationTests.cs (1 hunks)
  • Parse.Tests/TransientCacheControllerTests.cs (1 hunks)
  • Parse.Tests/UserTests.cs (8 hunks)
  • Parse/Abstractions/Infrastructure/CustomServiceHub.cs (2 hunks)
  • Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs (1 hunks)
  • Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1 hunks)
  • Parse/Abstractions/Platform/Users/IParseCurrentUserController.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseAddOperation.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseAddUniqueOperation.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseDeleteOperation.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseFieldOperations.cs (2 hunks)
  • Parse/Infrastructure/Control/ParseIncrementOperation.cs (2 hunks)
  • Parse/Infrastructure/Control/ParseRelationOperation.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseRemoveOperation.cs (1 hunks)
  • Parse/Infrastructure/Control/ParseSetOperation.cs (4 hunks)
  • Parse/Infrastructure/Data/ParseDataDecoder.cs (2 hunks)
  • Parse/Infrastructure/Data/ParseDataEncoder.cs (7 hunks)
  • Parse/Infrastructure/Data/ParseObjectCoder.cs (3 hunks)
  • Parse/Infrastructure/Execution/ParseCommandRunner.cs (2 hunks)
  • Parse/Infrastructure/LateInitializedMutableServiceHub.cs (1 hunks)
  • Parse/Infrastructure/MutableServiceHub.cs (2 hunks)
  • Parse/Infrastructure/ParseFailureException.cs (2 hunks)
  • Parse/Infrastructure/ServiceHub.cs (2 hunks)
  • Parse/Platform/Cloud/ParseCloudCodeController.cs (1 hunks)
  • Parse/Platform/Configuration/ParseConfiguration.cs (3 hunks)
  • Parse/Platform/Files/ParseFile.cs (1 hunks)
  • Parse/Platform/Location/ParseGeoPoint.cs (1 hunks)
  • Parse/Platform/ParseClient.cs (2 hunks)
  • Parse/Platform/Queries/ParseQuery.cs (3 hunks)
  • Parse/Platform/Relations/ParseRelation.cs (1 hunks)
  • Parse/Platform/Security/ParseACL.cs (1 hunks)
  • Parse/Platform/Users/ParseUser.cs (1 hunks)
  • Parse/Utilities/ParseQueryExtensions.cs (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (10)
Parse/Infrastructure/Control/ParseAddUniqueOperation.cs (7)
Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)
  • IDictionary (15-15)
Parse/Infrastructure/Control/ParseAddOperation.cs (1)
  • IDictionary (52-62)
Parse/Infrastructure/Control/ParseDeleteOperation.cs (1)
  • IDictionary (21-27)
Parse/Infrastructure/Control/ParseRemoveOperation.cs (1)
  • IDictionary (42-52)
Parse/Infrastructure/Control/ParseSetOperation.cs (1)
  • IDictionary (20-43)
Parse/Infrastructure/Control/ParseIncrementOperation.cs (1)
  • IDictionary (101-109)
Parse/Infrastructure/Data/ParseObjectCoder.cs (1)
  • IDictionary (30-46)
Parse/Infrastructure/Control/ParseAddOperation.cs (7)
Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)
  • IDictionary (15-15)
Parse/Infrastructure/Control/ParseDeleteOperation.cs (1)
  • IDictionary (21-27)
Parse/Infrastructure/Control/ParseAddUniqueOperation.cs (1)
  • IDictionary (58-68)
Parse/Infrastructure/Control/ParseRemoveOperation.cs (1)
  • IDictionary (42-52)
Parse/Infrastructure/Control/ParseSetOperation.cs (1)
  • IDictionary (20-43)
Parse/Infrastructure/Control/ParseIncrementOperation.cs (1)
  • IDictionary (101-109)
Parse/Infrastructure/Data/ParseObjectCoder.cs (1)
  • IDictionary (30-46)
Parse/Infrastructure/LateInitializedMutableServiceHub.cs (1)
Parse/Infrastructure/Utilities/LateInitializer.cs (1)
  • LateInitializer (14-90)
Parse/Platform/Cloud/ParseCloudCodeController.cs (2)
Parse/Infrastructure/Data/ParseDataDecoder.cs (1)
  • Decode (23-63)
Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs (1)
  • Decode (14-14)
Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)
Parse/Platform/ParseClient.cs (1)
  • IServiceHub (171-182)
Parse/Infrastructure/Data/ParseObjectCoder.cs (2)
Parse/Infrastructure/Data/ParseDataDecoder.cs (1)
  • Decode (23-63)
Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs (1)
  • Decode (14-14)
Parse/Platform/Configuration/ParseConfiguration.cs (4)
Parse/Utilities/ConfigurationServiceExtensions.cs (2)
  • ParseConfiguration (12-15)
  • ParseConfiguration (17-20)
Parse/Infrastructure/Data/ParseDataDecoder.cs (1)
  • Decode (23-63)
Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs (1)
  • Decode (14-14)
Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)
  • IDictionary (15-15)
Parse/Infrastructure/Data/ParseDataEncoder.cs (3)
Parse/Platform/ParseClient.cs (6)
  • IServiceHub (171-182)
  • ParseClient (21-183)
  • ParseClient (60-60)
  • ParseClient (68-122)
  • ParseClient (127-127)
  • IDictionary (148-159)
Parse/Infrastructure/Control/ParseSetOperation.cs (4)
  • ParseSetOperation (12-75)
  • ParseSetOperation (14-17)
  • ConvertValueToJSON (56-72)
  • IDictionary (20-43)
Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)
  • IDictionary (15-15)
Parse/Infrastructure/Execution/ParseCommandRunner.cs (1)
Parse/Infrastructure/ParseFailureException.cs (3)
  • ParseErrorPayload (274-278)
  • ParseFailureException (8-273)
  • ParseFailureException (267-267)
Parse.Tests/UserTests.cs (5)
Parse/Platform/ParseClient.cs (1)
  • Publicize (133-139)
Parse/Utilities/ObjectServiceExtensions.cs (1)
  • AddValidClass (25-28)
Parse/Platform/Objects/ParseObject.cs (1)
  • HandleFetchResult (801-807)
Parse/Infrastructure/MutableServiceHub.cs (2)
  • MutableServiceHub (35-109)
  • MutableServiceHub (69-108)
Parse/Platform/Users/ParseUser.cs (12)
  • Task (15-37)
  • Task (61-65)
  • Task (88-120)
  • Task (123-136)
  • Task (138-149)
  • Task (151-163)
  • Task (165-170)
  • Task (209-218)
  • Task (220-228)
  • Task (230-233)
  • Remove (39-46)
  • HandleSave (50-56)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: .NET 9.0
  • GitHub Check: .NET 8.0
🔇 Additional comments (100)
Parse.Tests/Parse.Tests.csproj (1)

9-17: Good package maintenance and coverage enhancement

The addition of coverlet.collector for code coverage and updates to the test SDK and MSTest packages are excellent improvements that will enhance the testing capabilities and provide better coverage reporting for this architectural refactor.

Parse.Tests/ObjectTests.cs (2)

32-32: Minor formatting improvement

Good fix to the indentation of the private Client property for consistency.


735-1062: Excellent test coverage expansion

The addition of numerous well-structured unit tests significantly improves coverage of the ParseObject functionality. The tests are properly isolated, have clear descriptions, and cover important edge cases and functionality like property validation, operations, and state management.

Parse.Tests/ProgressTests.cs (2)

35-46: Excellent test isolation improvement

Converting from shared mock fields to per-test local mocks eliminates potential test interdependencies and makes tests more reliable and maintainable. This follows testing best practices.


52-63: Consistent test isolation pattern

Good consistency in applying the same local mock pattern across both test methods, ensuring uniform test isolation throughout the class.

Parse.Tests/ConversionTests.cs (1)

27-30: Improved test precision with exact exception matching

Using Assert.ThrowsExactly<InvalidCastException> instead of Assert.ThrowsException provides more precise exception validation, ensuring the exact exception type is thrown rather than allowing derived types.

Parse/Platform/Users/ParseUser.cs (1)

6-6: Good code cleanup and formatting

The addition of appropriate whitespace and removal of commented-out code (as noted in the summary) improves code readability and maintainability.

Parse/Abstractions/Infrastructure/CustomServiceHub.cs (1)

50-50: LGTM! Consistent service hub pattern.

The new CurrentUser property follows the established pattern of exposing controller functionality through the service hub abstraction. This provides convenient direct access to the current user while maintaining the architecture's consistency.

Parse/Abstractions/Platform/Users/IParseCurrentUserController.cs (1)

10-10: All implementations now include the CurrentUser property

  • IParseCurrentUserController declares ParseUser CurrentUser { get; }.
  • ParseCurrentUserController provides a public getter (get => currentUser) and satisfies the interface.
  • No other concrete implementations of the interface exist (tests use mocks).

No further changes are required.

Parse/Platform/Security/ParseACL.cs (1)

108-108: Excellent type safety improvement.

Changing the return type from object to IDictionary<string, object> improves type safety and API clarity. Since the method implementation already returns a dictionary, this change makes the contract explicit and consistent with the broader standardization effort across the codebase.

Parse.Tests/GeoPointTests.cs (1)

27-27: Good API simplification.

Removing the second parameter from Client.Decoder.Decode aligns with the dependency injection refactoring where the decoder now maintains an internal service hub reference. This reduces parameter complexity while maintaining the same functionality.

Parse/Platform/Location/ParseGeoPoint.cs (1)

94-94: Consistent type safety improvement.

The return type change from object to IDictionary<string, object> maintains consistency with the broader refactoring pattern and improves type safety without changing the functional behavior.

Parse/Abstractions/Infrastructure/Data/IParseDataDecoder.cs (1)

14-14: LGTM! Interface simplification improves dependency injection pattern.

The removal of the IServiceHub serviceHub parameter from the Decode method signature is a good architectural improvement. This change supports constructor-based dependency injection where the decoder receives the service hub instance at creation time rather than on each method call, leading to cleaner and more consistent API design.

Parse/Infrastructure/LateInitializedMutableServiceHub.cs (1)

151-155: Consistent with dependency injection refactoring.

The change to pass the entire service hub instance (this) to the ParseDataDecoder constructor instead of just the ClassController is consistent with the interface simplification in IParseDataDecoder. This allows the decoder to access all necessary services through constructor injection rather than requiring them as method parameters.

Parse/Infrastructure/Control/ParseAddOperation.cs (1)

52-52: Excellent type safety improvement.

Changing the return type from object to IDictionary<string, object> provides better type safety and clarity about what the method returns. This standardization across Parse operation classes makes the API more predictable and reduces the need for casting in consuming code.

Parse/Infrastructure/Control/ParseAddUniqueOperation.cs (1)

58-58: Consistent type safety improvement across operation classes.

The return type change from object to IDictionary<string, object> aligns with similar changes in other Parse operation classes like ParseAddOperation. This standardization improves type safety and API consistency across the codebase.

Parse/Infrastructure/ServiceHub.cs (2)

49-49: Good architectural change to support explicit decoder initialization.

Changing the Decoder property from lazy initialization to an auto-implemented property with an internal setter is a positive architectural improvement. This allows explicit control over when and how the decoder is initialized, which supports the dependency injection pattern where the decoder can be set during service hub construction rather than being created on first access.


2-2: Using System directive is required.

The file uses Lazy<T> (e.g. new Lazy<IParseUserController>(…)), which resides in the System namespace. The using System; import is therefore needed.

Parse/Infrastructure/MutableServiceHub.cs (2)

2-2: Minor formatting improvement.

Good addition of the blank line for better code organization and readability.


83-83: Excellent dependency injection refactor.

The change from passing ClassController to passing the entire service hub (this) to the ParseDataDecoder constructor is a solid architectural improvement. This allows the decoder to access all necessary services through the injected hub rather than requiring specific dependencies or runtime parameters.

This change aligns well with the broader refactoring mentioned in the summary and follows good dependency injection principles.

Parse/Infrastructure/ParseFailureException.cs (1)

274-278: Well-designed error payload structure.

The ParseErrorPayload class provides a clean, structured way to handle error responses from the Parse server. The simple properties code and error align well with typical REST API error formats and integrate nicely with the enhanced HTTP response handling mentioned in the summary.

Parse/Infrastructure/Control/ParseDeleteOperation.cs (1)

21-21: Excellent type safety improvement.

Changing the return type from object to IDictionary<string, object> is a great enhancement that:

  • Provides explicit type information for better code clarity
  • Improves type safety and IntelliSense support
  • Aligns with the broader standardization effort across Parse operation classes
  • Makes the JSON-like return structure immediately apparent to consumers

The method already returned a dictionary, so this change just makes the contract explicit without any functional changes.

Parse/Platform/Files/ParseFile.cs (1)

168-168: Excellent type safety enhancement.

The return type change from object to IDictionary<string, object> is a valuable improvement that:

  • Explicitly declares the JSON-like dictionary structure being returned
  • Enhances type safety and developer experience with better IntelliSense
  • Aligns perfectly with the systematic standardization across the Parse SDK
  • Maintains full backward compatibility since the implementation was already returning a dictionary

This change makes the API more self-documenting and easier to work with.

Parse/Infrastructure/Control/ParseIncrementOperation.cs (2)

4-4: Good formatting improvement.

The added blank line enhances code readability and organization.


101-101: Perfect type safety enhancement.

The return type change from object to IDictionary<string, object> continues the excellent pattern of improvements seen across the Parse operation classes. This change:

  • Makes the JSON dictionary return structure explicit and type-safe
  • Improves developer experience with better tooling support
  • Maintains consistency with the broader SDK standardization effort
  • Preserves all existing functionality while enhancing the API contract

This systematic approach to type refinement across the operation classes is commendable.

Parse/Abstractions/Infrastructure/IJsonConvertible.cs (1)

14-16: Good improvement to type safety

Changing the return type from object to IDictionary<string, object> provides better compile-time type checking and makes the API contract clearer. This aligns well with the architectural refactoring objectives.

Parse/Infrastructure/Control/ParseRemoveOperation.cs (1)

42-52: Return type correctly updated to match interface

The return type change to IDictionary<string, object> properly implements the updated IJsonConvertible interface. The implementation already returned a dictionary, so no logic changes were needed.

Parse/Platform/Relations/ParseRelation.cs (1)

73-80: Consistent implementation of updated interface

The return type change properly implements the updated IJsonConvertible interface. The method already returned the correct dictionary structure.

Parse/Utilities/ParseQueryExtensions.cs (1)

7-7: Minor whitespace change

This appears to be just a whitespace/formatting change with no functional impact.

Parse/Infrastructure/Control/ParseRelationOperation.cs (1)

85-85: LGTM: Improved type safety with specific return type.

The change from object to IDictionary<string, object> for the ConvertToJSON method return type enhances type safety and makes the interface contract clearer. The implementation already returns dictionary objects, so this change aligns perfectly with the architectural refactoring goals.

Parse/Infrastructure/Data/ParseObjectCoder.cs (3)

91-91: LGTM: Simplified decoder call aligns with interface changes.

The removal of the serviceHub parameter from decoder.Decode() correctly reflects the updated IParseDataDecoder interface where service hub access is now internal to the decoder implementation.


117-124: LGTM: Improved Extract method implementation.

The refactored Extract<T> method now properly checks for key existence before attempting removal and conversion, which is more robust than the previous implementation.


129-135: LGTM: Added braces improve code clarity.

The addition of braces to the PopulateServerData method enhances readability without changing behavior.

Parse.Tests/EncoderTests.cs (3)

34-34: LGTM: Consistent client context provision.

Adding the Client parameter to ParseObject constructors ensures proper client context, which aligns with the architectural refactoring goals.

Also applies to: 52-52


53-55: LGTM: Improved exception testing precision.

The change from Assert.ThrowsException to Assert.ThrowsExactly enforces exact exception type matching, which provides more precise test validation and better catches regressions.

Also applies to: 106-106, 250-253


79-85: LGTM: Added test coverage for NoObjectsEncoder.

The new test method TestEncodeParseObjectWithNoObjectsEncoder provides valuable coverage for the NoObjectsEncoder scenario, ensuring it properly throws ArgumentException when attempting to encode a ParseObject.

Parse/Platform/ParseClient.cs (1)

100-119: LGTM: Excellent decoder initialization architecture.

The FinalizeDecoder local method provides a clean, recursive solution for ensuring all service hubs in the hierarchy have their Decoder property properly initialized. The implementation correctly:

  • Handles nested OrchestrationServiceHub structures recursively
  • Prevents overwriting existing decoders with null checks
  • Covers both ServiceHub and MutableServiceHub instances
  • Aligns with the architectural refactoring goals by centralizing decoder initialization

This ensures consistent decoder availability across the entire service hierarchy.

Parse.Tests/ConfigTests.cs (3)

69-69: LGTM: Simplified test comments improve readability.

The removal of difficulty level indicators from test comments makes the code cleaner while maintaining the descriptive nature of the test methods.

Also applies to: 79-79, 93-93, 103-103


118-125: LGTM: Activated test improves error handling coverage.

The Get_ThrowsExceptionNotFound test provides valuable coverage for the error case when accessing non-existent configuration keys, ensuring proper KeyNotFoundException behavior.


138-138: LGTM: Mock setup aligns with simplified decoder interface.

The removal of the second parameter from the mockDecoder.Setup() call correctly reflects the updated IParseDataDecoder.Decode method signature that no longer requires a service hub parameter.

Parse/Platform/Queries/ParseQuery.cs (2)

814-836: Well-implemented static Or method with proper validation.

The implementation correctly validates input queries, ensures they target the same class, and constructs the $or clause appropriately. The error messages are clear and helpful.


937-942: Proper GetHashCode implementation using standard hash combining technique.

The implementation correctly combines hash codes from key properties using the standard multiplier approach. This complements the existing Equals method well.

Parse/Infrastructure/Control/ParseSetOperation.cs (1)

20-43: Good type safety improvement but verify primitive type handling logic.

The return type change to IDictionary<string, object> improves type safety. However, the logic for primitive types (lines 30-33) wraps them in a dictionary with a "value" key, which may not be the intended behavior for set operations.

Consider whether primitive values should be wrapped in a dictionary or handled differently for set operations.

Parse.Tests/ObjectControllerTests.cs (1)

21-30: Excellent test isolation improvements.

The addition of proper ParseClient initialization in SetUp and cleanup in TearDown significantly improves test isolation and prevents potential test interference. The Client.Publicize() call ensures the client is properly initialized for testing.

Parse.Tests/ObjectStateTests.cs (2)

5-6: Good addition of necessary using statements.

The Moq and Parse.Abstractions.Infrastructure using statements are appropriately added to support the new test functionality with mocking.


168-305: Comprehensive test coverage expansion with good edge case handling.

The new test methods provide excellent coverage of edge cases:

  • Null value handling in cloning
  • Exception resilience in mutation operations
  • Dictionary decoding with date/time parsing
  • Graceful handling of invalid data
  • Field operation exception handling
  • State copying verification

The tests are well-structured with clear descriptions and appropriate assertions.

Parse.Tests/CloudControllerTests.cs (1)

24-24: Excellent test isolation improvements.

The refactoring from shared mock fields to local mock creation using the CreateMockRunner helper method significantly improves test isolation and maintainability. Each test now has its own clean mock setup without risk of shared state interference.

Also applies to: 140-151

Parse.Tests/TransientCacheControllerTests.cs (2)

36-50: Test logic is correct and follows good patterns.

The removal test properly validates that items are removed from the cache and uses appropriate assertions.


72-76: Exception test is correctly implemented.

The test properly validates that GetRelativeFile throws the expected NotSupportedException.

Parse.Tests/GeoDistanceTest.cs (5)

8-8: Modern C# syntax usage is good.

Using file-scoped namespaces is a good practice for test files.


14-19: Basic constructor test is correct.

The test properly validates that the constructor sets the radians value.


43-49: Factory method test logic is correct.

The test properly validates the FromMiles static factory method.


53-59: Factory method test logic is correct.

The test properly validates the FromKilometers static factory method.


64-69: Factory method test logic is correct.

The test properly validates the FromRadians static factory method.

Parse.Tests/AttributeTests.cs (4)

19-28: Property test logic is correct.

The test properly validates that PreserveAttribute boolean properties can be set and retrieved correctly.


31-35: Basic instantiation test is appropriate.

Simple test to ensure LinkerSafeAttribute can be created without exceptions.


38-43: Reflection-based attribute validation is correct.

The test properly uses reflection to verify that PreserveWrapperTypes has the expected PreserveAttribute with AllMembers=true.


47-58: AOT type registration test is comprehensive.

The test validates that specific wrapper types are registered in the AOTPreservations list, which is important for AOT compilation scenarios.

Parse.Tests/CloudTests.cs (5)

27-65: Mock setup and test logic are correct.

The refactoring successfully eliminates shared state by creating local mocks. The test properly validates that missing "result" key throws ParseFailureException.

Key improvements:

  • Local mock instantiation improves test isolation
  • Simplified Decode mock setup aligns with interface changes
  • Proper exception testing

41-42: Fully qualified HttpStatusCode usage is consistent.

Using System.Net.HttpStatusCode instead of a using directive is consistent with the refactoring pattern.


49-51: Simplified Decode mock setup is correct.

The change from two parameters to one parameter in the Decode method mock aligns with the interface refactoring mentioned in the PR summary.


68-105: Second test method follows same good patterns.

The second test method uses the same improved patterns as the first, with local mock setup and proper exception testing.


22-25: Post-Test Cleanup Verification
We didn’t find any static fields or singleton references to ParseCorePlugins in this repo, so it’s unclear whether Reset() is necessary. Please confirm:

  • If ParseCorePlugins.Instance retains global state that could leak between tests, re-enable the cleanup:
    -#warning Skipped post-test-evaluation cleaning method may be needed.
    
    +[TestCleanup]
    +public void TearDown() => ParseCorePlugins.Instance.Reset();
  • Otherwise, remove the #warning and the commented-out method entirely to avoid confusion.
Parse.Tests/AnalyticsTests.cs (3)

22-52: Test refactoring and logic are correct.

The refactoring successfully moves from shared state to local mock instantiation. The test properly validates that TrackAnalyticsEventAsync calls the controller with expected parameters.


55-87: Test with dimensions is well-implemented.

The test properly validates analytics tracking with custom dimensions, including verification that the dimensions dictionary is correctly passed to the controller.


90-119: App launch tracking test is correct.

The test validates the TrackLaunchAsync functionality, properly checking that TrackAppOpenedAsync is called with null push hash.

Parse/Platform/Configuration/ParseConfiguration.cs (2)

28-28: LGTM! Decoder interface simplification

The removal of the serviceHub parameter from decoder.Decode aligns with the architectural refactor to simplify the decoder interface.


110-110: Good type safety improvement

Changing the return type from object to IDictionary<string, object> provides better type safety and clarity about what the method returns.

Parse/Infrastructure/Execution/ParseCommandRunner.cs (1)

92-111: Well-structured error handling for 400 Bad Request

Good implementation of JSON deserialization for error payloads with proper exception handling when deserialization fails.

Parse.Tests/RelationTests.cs (1)

11-27: Significant reduction in test coverage

According to the AI summary, this file previously contained extensive tests for user relation management, exception handling, and other relation-related functionality. The removal of these tests significantly reduces coverage.

Please verify that the removed relation management tests have been moved to another test file or are covered elsewhere in the test suite. If not, consider restoring these tests to maintain adequate test coverage.

Parse.Tests/DecoderTests.cs (2)

43-142: Excellent test coverage for field operations

The new test methods provide comprehensive coverage for decoding various field operations (Increment, Delete, Add, AddUnique, Remove). The tests are well-structured with clear Arrange-Act-Assert patterns and descriptive assertions.


22-22: Consistent decoder interface simplification

The removal of the Client parameter from all decoder.Decode calls is consistent with the architectural refactor to simplify the decoder interface.

Also applies to: 36-41

Parse/Infrastructure/Control/ParseFieldOperations.cs (2)

37-38: Good improvement to comparer initialization

Making the comparer field readonly and properly initializing it ensures thread safety and prevents accidental modifications.


40-105: Well-structured field operation decoding implementation

The new Decode method provides comprehensive support for all Parse field operations with proper recursive decoding of nested objects. The implementation is clean, uses modern C# features effectively, and has appropriate error handling for unsupported operations.

Parse.Tests/ParseQueryControllerTests.cs (4)

34-47: Good dependency injection setup with proper service hub initialization.

The test setup correctly uses MutableServiceHub with SetDefaults() to ensure all dependencies are properly initialized, and creates a test-configured ParseClient. This pattern aligns well with the architectural refactoring objectives.


49-75: Comprehensive test for FindAsync with proper response structure.

The test correctly mocks the server response structure with the expected "results" array containing Parse objects with proper type annotations. The assertions validate both the count and object properties appropriately.


77-95: Well-structured CountAsync test with correct response format.

The test properly mocks the expected server response format for count queries and validates the returned count value.


97-119: FirstAsync test validates correct object extraction.

The test ensures that the first object is properly extracted and decoded from the results array, with appropriate assertions on the returned object's properties.

Parse.Tests/ObjectCoderTests.cs (1)

84-105: Well-structured async delete test with proper verification.

The test correctly mocks the command runner and verifies that the delete operation calls RunCommandAsync exactly once. The setup and assertions are appropriate for testing the delete functionality.

Parse/Infrastructure/Data/ParseDataDecoder.cs (3)

16-19: Excellent dependency injection implementation with proper validation.

The refactoring to inject IServiceHub directly into the decoder centralizes service access and eliminates the need to pass it as a parameter to decode methods. The null check with ArgumentNullException ensures proper validation.


23-62: Well-structured switch expression with comprehensive type handling.

The switch expression pattern provides clear, readable logic for handling different Parse data types. The explicit null handling and consistent use of KeyNotFoundException for missing required fields improves error clarity. The recursive decoding for dictionaries and lists maintains the decoding tree properly.


65-66: DecodePointer method correctly uses injected services.

The method properly uses the internal Services property instead of the external parameter, maintaining consistency with the refactored architecture.

Parse.Tests/InternalExtensionsTests.cs (7)

16-24: Good null safety test for Safe() extension method.

The test correctly validates that calling Safe() on a null task returns a completed task, which is essential for preventing null reference exceptions in async workflows.


26-35: Comprehensive test for generic Safe() method.

The test properly validates that Safe<T>() returns a completed task with the default value for the type when called on a null task, ensuring type safety in async operations.


37-53: Thorough dictionary extension testing with both positive and negative cases.

Both GetOrDefault tests properly validate the expected behavior when keys exist and don't exist, ensuring the extension method works correctly for dictionary lookups.


55-71: Collection equality tests cover both equal and unequal scenarios.

The tests correctly validate that CollectionsEqual distinguishes between collections with the same elements in the same order versus different orders, which is the expected behavior for sequence equality.


89-104: Excellent WhileAsync test with predicate-controlled loop.

The test properly validates that the WhileAsync method executes the loop body the correct number of times based on the predicate condition, ensuring the async looping utility works as expected.


140-153: Good exception propagation test for faulted tasks.

The test correctly validates that OnSuccess propagates exceptions from faulted tasks, which is crucial for proper error handling in async continuation chains.


155-167: Proper cancellation handling test.

The test appropriately validates that canceled tasks are handled correctly by the OnSuccess extension, ensuring proper cancellation token propagation.

Parse.Tests/ACLTests.cs (8)

19-52: Well-structured test setup with comprehensive mocking.

The test initialization properly mocks the service hub and class controller, with appropriate setup for object instantiation. The cleanup method ensures proper test isolation.


58-64: Simple but effective default constructor test.

The test validates basic ACL instantiation, which is fundamental for ensuring the class can be created without errors.


66-81: Comprehensive ParseUser constructor test.

The test properly validates that creating an ACL with a ParseUser owner sets the appropriate read and write permissions for that user, testing both ObjectId-based and ParseUser-based access methods.


145-157: Good public access property testing.

The test validates both getter and setter behavior for public read/write access properties, ensuring the basic public access functionality works correctly.


178-189: Excellent null input validation testing.

The test properly validates that ACL methods throw ArgumentException when passed null user IDs, which is essential for preventing runtime errors and ensuring proper input validation.


220-234: Comprehensive role access testing.

The test thoroughly validates role-based read/write access functionality, including both setting and getting permissions, which is crucial for role-based security models.


236-254: Good JSON conversion test with proper type validation.

The test validates that ACL JSON conversion returns the expected IDictionary<string, object> type and contains the appropriate keys for users and roles, aligning with the standardized JSON conversion return types mentioned in the AI summary.


257-277: Excellent edge case testing for invalid ACL data.

Both tests properly validate that the ACL handles invalid data gracefully, including invalid public key values and non-dictionary user permission data. This ensures robustness against malformed input data.

Parse.Tests/ParseOperationsTests.cs (1)

226-234: Good test coverage for edge cases

The test properly validates that incrementing non-numeric values throws an exception.

Parse.Tests/UserTests.cs (2)

148-205: Excellent test refactoring with proper isolation

The refactored TestLogOut method demonstrates best practices:

  • Complete isolation from static state
  • Clear mock setup and verification
  • Proper assertion of both the command execution and local cache clearing

This is a significant improvement over the previous implementation.


378-539: Good test coverage for edge cases

The new tests provide excellent coverage for:

  • Missing credentials validation
  • Authentication state checks
  • Username removal protection
  • New user save restrictions
  • Auth data linking checks
  • Password removal verification

These tests strengthen the overall test suite quality.

Comment on lines +56 to +72
public object ConvertValueToJSON(IServiceHub serviceHub = null)
{
// Get the values of the dictionary
var vals = ConvertToJSON(serviceHub).Values;



// Check if vals is a ValueCollection and contains exactly one element , that's how we get operations working! because they are dict<string,obj> of dict<string,obj>
if (vals.Count == 1)
{
// Return the first and only value
return vals.FirstOrDefault();
}

// Return vals if no single value is found
return vals;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Questionable method design and implementation.

The ConvertValueToJSON method has several concerns:

  1. The method name is misleading - it's unwrapping dictionary values, not converting to JSON
  2. The comment on line 63 is verbose and unclear
  3. The logic assumes the dictionary always has exactly one value, which may not be reliable
  4. The return type is object, losing type safety

Consider renaming this method and clarifying its purpose, or removing it if it's not essential to the API.

🤖 Prompt for AI Agents
In Parse/Infrastructure/Control/ParseSetOperation.cs around lines 56 to 72, the
ConvertValueToJSON method is misleadingly named and has unclear comments,
unreliable assumptions about dictionary size, and returns a loosely typed
object. Rename the method to better reflect its purpose, such as
ExtractSingleValueOrValues, simplify and clarify the comments to explain the
logic clearly, add checks to handle cases where the dictionary has zero or
multiple values more robustly, and consider using a more specific return type or
generics to improve type safety. If this method is not essential, evaluate
removing it to keep the API clean.

Comment on lines 55 to 59
// Decode the result
var decoded = Decoder.Decode(commandResult.Item2, serviceHub) as IDictionary<string, object>;

if (decoded == null)
{
throw new ParseFailureException(ParseFailureException.ErrorCode.OtherCause, "Failed to decode cloud function response.");
}
var decoded = Decoder.Decode(commandResult.Item2) as IDictionary<string, object>;

// Extract the result key
if (decoded.TryGetValue("result", out var result))
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add null check after the cast to prevent potential NullReferenceException

The cast to IDictionary<string, object> on line 56 could return null if the decoded object is not a dictionary. The subsequent TryGetValue call on line 59 would throw a NullReferenceException if decoded is null.

Consider adding a null check:

 // Decode the result
 var decoded = Decoder.Decode(commandResult.Item2) as IDictionary<string, object>;
+if (decoded == null)
+{
+    throw new ParseFailureException(ParseFailureException.ErrorCode.OtherCause, "Cloud function returned invalid response format.");
+}

 // Extract the result key
 if (decoded.TryGetValue("result", out var result))
🤖 Prompt for AI Agents
In Parse/Platform/Cloud/ParseCloudCodeController.cs around lines 55 to 59, add a
null check after casting the decoded object to IDictionary<string, object> to
prevent a NullReferenceException. Specifically, verify that the decoded variable
is not null before calling TryGetValue on it. If decoded is null, handle that
case appropriately to avoid exceptions.

Copy link

codecov bot commented Jul 26, 2025

Codecov Report

❌ Patch coverage is 47.66839% with 101 lines in your changes missing coverage. Please review.
✅ Project coverage is 54.53%. Comparing base (2e81163) to head (1023430).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
...rse/Infrastructure/Control/ParseFieldOperations.cs 28.20% 23 Missing and 5 partials ⚠️
...rse/Infrastructure/Execution/ParseCommandRunner.cs 20.00% 19 Missing and 5 partials ⚠️
Parse/Platform/Queries/ParseQuery.cs 0.00% 22 Missing ⚠️
Parse/Infrastructure/Data/ParseDataEncoder.cs 26.31% 13 Missing and 1 partial ⚠️
Parse/Infrastructure/Control/ParseSetOperation.cs 0.00% 8 Missing ⚠️
Parse/Infrastructure/ParseFailureException.cs 0.00% 2 Missing ⚠️
...se/Abstractions/Infrastructure/CustomServiceHub.cs 0.00% 1 Missing ⚠️
...Infrastructure/LateInitializedMutableServiceHub.cs 0.00% 1 Missing ⚠️
Parse/Infrastructure/MutableServiceHub.cs 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #412      +/-   ##
==========================================
+ Coverage   48.20%   54.53%   +6.33%     
==========================================
  Files         106      106              
  Lines        6199     6273      +74     
  Branches      950      981      +31     
==========================================
+ Hits         2988     3421     +433     
+ Misses       2907     2523     -384     
- Partials      304      329      +25     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@mtrezza
Copy link
Member

mtrezza commented Jul 26, 2025

@YBTopaz8 First of all, thanks for your efforts with this PR. If you remember the discussion from the last redesign, it was incredibly complex to review because many changes were packed into a single PR. Is there a way to break this down into smaller, discrete PRs, also to minimize the risk of bugs? We also try to avoid breaking changes as much as possible.

YBTopaz8 added 2 commits July 26, 2025 09:44
Removed unnecessary checks for response codes 100 and 200.
Updated handling for response code 401 to throw
`InvalidSessionToken` instead of `ObjectNotFound`.
Retained structure for response code 400 with added
deserialization of `ParseErrorPayload`.
@YBTopaz8
Copy link
Member Author

Thank you for the feedback.

I need to be clear that this changeset is a single, atomic architectural upgrade. The core of this work is a critical bug fix to the DI system, and all subsequent features and tests are built directly upon that new, stable foundation. As such, these changes cannot be broken up into smaller, preceding PRs unless one has time for that —the dependency is foundational.

This refactor is not a redesign for its own sake; it's a necessary stabilization of the previous architecture that simplifies the developer experience and eliminates a class of runtime bugs, as detailed in the PR description.

I understand your team's process, but it's also difficult to provide the necessary documentation and context when my foundational README PR from last March still hasn't been reviewed. A comprehensive review of this PR would depend on that context.

This contribution is offered as a complete, necessary solution. Please let me know if you are able to review and accept this foundational contribution as a whole.
I do not mind answering any questions at all.
If not, I will close the PR and focus my efforts on other projects.
Thank you.

@mtrezza
Copy link
Member

mtrezza commented Jul 26, 2025

@YBTopaz8 #410 seems to be just a few lines in the README. If a PR falls through the cracks please comment as reminder. I posted a comment there.

Major architectural improvement, new features

Could you break this down briefly - what are the improvements and new features? We'd need a list of all breaking changes for the changelog entry.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants