Skip to content

Conversation

@maratal
Copy link
Collaborator

@maratal maratal commented Mar 16, 2025

Part of #235

Results of running unit tests 100 times in Xcode:

Iteration 100 ended after 0.536 seconds.
Test run with 15300 tests passed after 45.864 seconds.

Summary by CodeRabbit

  • New Features
    • Added comprehensive asynchronous tests for presence-related chat functionality, including entering, updating, leaving, retrieving, and subscribing to presence events.
  • Tests
    • Enhanced test mocks with call recording and configurable behavior for presence and room lifecycle operations.
    • Improved test utilities for deep equality checks and presence event handling.
    • Updated test annotations for clearer specification traceability.
  • Chores
    • Expanded and refined test coverage to ensure robust validation of presence features.

@coderabbitai
Copy link

coderabbitai bot commented Mar 16, 2025

Walkthrough

This change restores and expands presence-related unit tests, introduces new test helpers, and enhances mock classes to support thorough testing of presence operations. It adds a thread-safe method call recorder, convenience initializers, and deep equality utilities, and updates test annotations for specification traceability. No production code is modified except for a documentation comment update.

Changes

File(s) Change Summary
Tests/AblyChatTests/Helpers/Helpers.swift Adds test utilities: convenience initializer for ARTPresenceMessage, deep equality function compareAny, thread-safe MockMethodCallRecorder class for recording method calls, and dictionary conversion helper toAblyCocoaData().
Tests/AblyChatTests/Mocks/MockRealtimePresence.swift Enhances MockRealtimePresence with a callRecorder to log method calls, implements stubbed presence methods returning success or empty results instead of fatal errors, and adds descriptive extension for ARTRealtimePresenceQuery.
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift Adds callRecorder and configurable result for waitToBeAbleToPerformPresenceOperations, replacing previous fatalError stub with a functional mock implementation that can simulate success or failure.
Tests/AblyChatTests/DefaultPresenceTests.swift Adds comprehensive asynchronous unit tests for presence operations (enter, update, leave, get, subscribe), covering success, failure, and lifecycle states, with mock verifications and specification annotations.
Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift Updates test specification annotations from @specPartial to @specOneOf with fractional indices for clarity; no logic changes.
Sources/AblyChat/RoomLifecycleManager.swift Removes references to test cases CHA-T2c, CHA-T2d, and CHA-T2g from documentation comment of waitToBeAbleToPerformPresenceOperations; no code changes.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Case
    participant MockPresence as MockRealtimePresence
    participant Recorder as MockMethodCallRecorder

    Test->>MockPresence: Call presence operation (e.g., enter, update, get)
    MockPresence->>Recorder: addRecord(signature, arguments)
    MockPresence-->>Test: Return stubbed result (success or empty)
    Test->>Recorder: hasRecord(signature, arguments) (assertion)
Loading

Assessment against linked issues

Objective Addressed Explanation
Restore and improve presence tests (ECO-5251)
Add or update mocks and helpers to support presence testing (ECO-5251)
Ensure presence tests are robust and non-flaky (ECO-5251)

Suggested reviewers

  • lawrence-forooghian

Poem

In the warren of tests, a rabbit hops,
Restoring presence checks with clever stops.
Helpers and mocks, all neat and precise,
Ensure our chat’s presence is tested thrice.
With each async hop, a method is tracked—
The code is robust, the bugs are sacked!
🐇✨

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


📜 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 6cf2821 and 9d404f5.

📒 Files selected for processing (1)
  • Tests/AblyChatTests/DefaultPresenceTests.swift (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
Tests/AblyChatTests/DefaultPresenceTests.swift (1)
Learnt from: maratal
PR: ably/ably-chat-swift#249
File: Tests/AblyChatTests/DefaultMessagesTests.swift:45-48
Timestamp: 2025-05-22T19:17:21.392Z
Learning: The `let doIt = {}` closures in DefaultMessagesTests.swift are temporary workarounds for compiler crashes (related to issue #233) and will be removed once Xcode 16.3 is released, so they should not be flagged for missing async/throws annotations.
⏰ Context from checks skipped due to timeout of 90000ms (34)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: Generate code coverage
🔇 Additional comments (11)
Tests/AblyChatTests/DefaultPresenceTests.swift (11)

1-4: LGTM! Clean imports and test structure.

The imports are well-organized and the test structure follows Swift Testing best practices.


7-34: LGTM! Well-structured presence enter test.

The test correctly verifies that entering presence calls the underlying channel method with properly wrapped user data.


35-60: LGTM! Correctly tests presence operations during attachment.

The test properly verifies that the room lifecycle manager's wait method is called when entering presence during attachment.


129-156: LGTM! Update presence test is well-structured.

The test correctly verifies the update operation with custom data.


158-183: LGTM! Correctly tests update during attachment.


252-279: LGTM! Leave presence test is correct.

The test properly verifies that leaving presence calls the underlying channel method with empty data.


281-308: LGTM! isUserPresent test correctly verifies query construction.

The test properly verifies that the presence query is constructed with the correct client ID.


310-338: LGTM! Get presence members test is straightforward and correct.


369-394: LGTM! Get presence during attachment test is correct.


434-487: LGTM! Comprehensive presence subscription test.

The test thoroughly covers all presence event types and correctly verifies subscription behavior. Good documentation of spec coverage.


489-490: LGTM! Good documentation of untestable spec.

Properly documents why CHA-PR7c cannot be tested due to AsyncSequence limitations.

✨ Finishing Touches
  • 📝 Generate Docstrings

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 docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in 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.

@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 16, 2025 10:57 Inactive
@maratal maratal changed the title Add presence tests without using DefaultRoomLifecycleManager. [ECO-5251] Add presence tests without using DefaultRoomLifecycleManager. Mar 16, 2025
@maratal maratal changed the title [ECO-5251] Add presence tests without using DefaultRoomLifecycleManager. [ECO-5251] Presence tests without using DefaultRoomLifecycleManager. Mar 16, 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: 3

🧹 Nitpick comments (7)
Tests/AblyChatTests/Helpers/Helpers.swift (1)

54-61: Helpful extension for test iterations

The static all property for presence event types provides a convenient way to test across all event types. Consider adding a descriptive comment to explain its testing use case.

extension [PresenceEventType] {
+    /// Contains all possible presence event types for use in comprehensive testing
    static let all = [
        PresenceEventType.present,
        PresenceEventType.enter,
        PresenceEventType.leave,
        PresenceEventType.update,
    ]
}
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2)

8-8: Fix trailing whitespace

Remove the trailing whitespace on these lines to satisfy style guidelines.

    private let resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo>?
-    
+
    private(set) var attachCallCount = 0
    private(set) var detachCallCount = 0
    private(set) var releaseCallCount = 0
    private(set) var waitCallCount = 0
-    
+

Also applies to: 13-13

🧰 Tools
🪛 SwiftLint (0.57.0)

[Error] 8-8: Lines should not have trailing whitespace

(trailing_whitespace)


17-21: Fix multiline parameters brackets style

According to SwiftLint, multiline parameters should have their surrounding brackets on new lines.

-    init(attachResult: Result<Void, ARTErrorInfo>? = nil,
-         detachResult: Result<Void, ARTErrorInfo>? = nil,
-         roomStatus: RoomStatus? = nil,
-         resultOfWaitToBeAblePerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil
-    ) {
+    init(
+         attachResult: Result<Void, ARTErrorInfo>? = nil,
+         detachResult: Result<Void, ARTErrorInfo>? = nil,
+         roomStatus: RoomStatus? = nil,
+         resultOfWaitToBeAblePerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil
+    ) {
🧰 Tools
🪛 SwiftLint (0.57.0)

[Error] 17-17: Multiline parameters should have their surrounding brackets in a new line

(multiline_parameters_brackets)

Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift (3)

8-12: Consider making mockPresence a regular optional or initializing it in the constructor.
Using MockRealtimePresence! is convenient, but if it remains nil at runtime, calls to presence will crash. A safer approach is to use a regular optional and handle nil cases, or ensure mockPresence is always initialized in the initializer.


36-37: Refine default parameters in initializer.
You currently have optional parameters messageToEmitOnSubscribe and mockPresence set to nil by default. If these remain nil during test usage, referencing them could cause unexpected behavior. Consider either requiring non-nil arguments for stricter typing or adding checks to ensure safe usage.

Also applies to: 45-45


190-192: Consider extending the mock to track channel state changes.
Returning a new ARTEventListener() is fine for a basic mock, but if you eventually need to verify state transitions, storing or invoking the provided closure could be beneficial for testing.

Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1)

4-129: Guard against potential data races with shared state.
This mock class is marked @unchecked Sendable and manipulates members and subscribeCallback without synchronization. If these methods are called concurrently from multiple tasks, you risk data races. Though it may be sufficient for single-threaded test code, consider adding locking or concurrency-safe mechanisms if test scenarios require concurrency correctness.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between f86f569 and 2b6500d.

📒 Files selected for processing (7)
  • Sources/AblyChat/RoomFeature.swift (1 hunks)
  • Tests/AblyChatTests/DefaultRoomPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift (5 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2 hunks)
🧰 Additional context used
🪛 SwiftLint (0.57.0)
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift

[Error] 17-17: Multiline parameters should have their surrounding brackets in a new line

(multiline_parameters_brackets)


[Error] 8-8: Lines should not have trailing whitespace

(trailing_whitespace)


[Error] 13-13: Lines should not have trailing whitespace

(trailing_whitespace)

⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Example app, tvOS (Xcode 16)
  • GitHub Check: Example app, iOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16)
  • GitHub Check: Example app, macOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16)
  • GitHub Check: Xcode, tvOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16)
  • GitHub Check: Xcode, iOS (Xcode 16)
  • GitHub Check: SPM, release configuration (Xcode 16)
  • GitHub Check: Xcode, macOS (Xcode 16)
  • GitHub Check: SPM (Xcode 16)
🔇 Additional comments (9)
Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift (1)

4-4: Protocol conformance added appropriately

Good addition of the EmitsDiscontinuities protocol to the mock contributor, which aligns with the changes in DefaultFeatureChannel.

Sources/AblyChat/RoomFeature.swift (1)

66-66: Good type abstraction improvement

Changing the contributor type from a concrete implementation to a protocol composition (any RoomLifecycleContributor & EmitsDiscontinuities) improves flexibility and testability. This allows for better dependency injection and supports the goal of testing without using DefaultRoomLifecycleManager.

Tests/AblyChatTests/Helpers/Helpers.swift (2)

25-32: Well-designed convenience initializer

The convenience initializer for ARTPresenceMessage is well-structured with appropriate default values, making test setup much cleaner.


34-52: Useful helper function for test setup

The createMockContributor function is a good addition that will simplify test code by reducing boilerplate. It provides sensible defaults while allowing test-specific customization.

Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2)

30-36: Improved attach operation logic

The changes to performAttachOperation correctly emit a status change and improve error handling by checking for the presence operation result.


66-72: Good implementation of waitToBeAbleToPerformPresenceOperations

This implementation properly tracks call counts and handles the result of waiting for presence operations. The fatal error provides a clear message when the mock is not configured correctly.

Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift (2)

77-77: Verify fallback to .failed state when attachResult is nil.
Right now, if attachResult is uninitialized or nil, the channel defaults to .failed. Confirm that behavior aligns with your testing requirements, since it could obscure whether the attach result was simply unset.


92-95: Equatable conformance is a good addition.
Marking AttachOrDetachResult as Equatable helps compare outcomes in tests without extra overhead.

Tests/AblyChatTests/DefaultRoomPresenceTests.swift (1)

1-478: Comprehensive test coverage is commendable.
These tests systematically cover presence scenarios—enter, update, leave, and error handling—ensuring reliability and correctness of the DefaultPresence workflow. As a whole, the suite appears logically consistent with your real-time constraints and concurrency model.

@maratal maratal marked this pull request as draft March 16, 2025 11:16
@maratal maratal force-pushed the fix/235-presence-tests branch from 2b6500d to be42380 Compare March 16, 2025 11:32
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 16, 2025 11:33 Inactive
@maratal maratal force-pushed the fix/235-presence-tests branch from be42380 to dcb9d8b Compare March 16, 2025 11:38
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 16, 2025 11:39 Inactive
@maratal maratal marked this pull request as ready for review March 16, 2025 11:43
@lawrence-forooghian
Copy link
Collaborator

@maratal can you fix merge conflicts please? I think they were introduced after I merged #234.

@lawrence-forooghian
Copy link
Collaborator

lawrence-forooghian commented Mar 17, 2025

@maratal please can you also:

@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 17, 2025 12:21 Inactive
@maratal maratal force-pushed the fix/235-presence-tests branch from ae86971 to 3d4eb27 Compare March 17, 2025 12:31
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 17, 2025 12:32 Inactive
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: 0

♻️ Duplicate comments (4)
Tests/AblyChatTests/DefaultRoomPresenceTests.swift (4)

40-44: ⚠️ Potential issue

Fix array check in presence filtering.

Here, let client2 = presenceMembers.filter { ... } returns an array, so client2 != nil will always be true. To confirm the presence is found, check for a non-empty array instead.

- #expect(client2 != nil)
+ #expect(!client2.isEmpty)

157-161: ⚠️ Potential issue

Correct the presence filtering condition.

As with the earlier logic, filter returns [PresenceMember]. Checking client1 != nil is ineffective. Instead, verify that the array is non-empty.

- #expect(client1 != nil)
+ #expect(!client1.isEmpty)

40-44: ⚠️ Potential issue

Fix array check in presence filtering

Here, let client2 = presenceMembers.filter { ... } returns an array, so client2 != nil will always be true. To confirm the presence is found, check for a non-empty array instead.

- #expect(client2 != nil)
+ #expect(!client2.isEmpty)

157-161: ⚠️ Potential issue

Correct the presence filtering condition

As with the earlier logic, filter returns [PresenceMember]. Checking client1 != nil is ineffective. Instead, verify that the array is non-empty.

- #expect(client1 != nil)
+ #expect(!client1.isEmpty)
🧹 Nitpick comments (2)
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2)

17-22: Consider addressing parameter name inconsistency.

The parameter name resultOfWaitToBeAblePerformPresenceOperations is missing the word "To" between "Able" and "Perform", while the property name includes it correctly.

init(
    attachResult: Result<Void, ARTErrorInfo>? = nil,
    detachResult: Result<Void, ARTErrorInfo>? = nil,
    roomStatus: RoomStatus? = nil,
-   resultOfWaitToBeAblePerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil
+   resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil
) {

21-21: Parameter name doesn't match property name

There's a slight inconsistency in naming between the parameter and the property it sets:

- resultOfWaitToBeAblePerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil
+ resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo>? = nil

The parameter is missing the word "To" between "Able" and "Perform".

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between ae86971 and 3d4eb27.

📒 Files selected for processing (8)
  • Sources/AblyChat/RoomFeature.swift (1 hunks)
  • Tests/AblyChatTests/DefaultMessagesTests.swift (6 hunks)
  • Tests/AblyChatTests/DefaultRoomPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift (5 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift
  • Tests/AblyChatTests/DefaultMessagesTests.swift
  • Tests/AblyChatTests/Helpers/Helpers.swift
  • Sources/AblyChat/RoomFeature.swift
  • Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: Example app, tvOS (Xcode 16)
  • GitHub Check: Example app, iOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16)
  • GitHub Check: Example app, macOS (Xcode 16)
  • GitHub Check: Xcode, tvOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16)
  • GitHub Check: Xcode, iOS (Xcode 16)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16)
  • GitHub Check: Xcode, macOS (Xcode 16)
  • GitHub Check: SPM, release configuration (Xcode 16)
  • GitHub Check: SPM (Xcode 16)
🔇 Additional comments (37)
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (7)

7-8: Good addition of the result property for presence operations testing.

The new property enables testing of presence operation scenarios, which aligns with the PR objective of implementing presence tests without using DefaultRoomLifecycleManager.


31-41: Good implementation of status change emission before checking results.

The addition of emitting a status change before proceeding with attachment logic correctly simulates the behavior of a real lifecycle manager, which is important for testing presence operations.


75-84: Well-implemented waiting mechanism with proper error handling.

The implementation correctly tracks wait calls and provides appropriate error handling, which is essential for testing presence operations in different room states.


7-7: Added property to support presence operations

The addition of resultOfWaitToBeAbleToPerformPresenceOperations enables the mock to simulate presence operation results, aligning with the PR's goal of implementing presence tests without using DefaultRoomLifecycleManager.


25-25: Ensure property assignment matches parameter name

This line assigns the value from the parameter to the property, but since the parameter name differs slightly from the property name, it might lead to confusion for future maintainers.


31-41: Enhanced performAttachOperation with status change emission

The implementation now emits status changes before proceeding with attachment logic and adds conditional processing based on the presence operation capability state. This creates a more realistic simulation of the real component's behavior.


75-85: Implementation of waitToBeAbleToPerformPresenceOperations

Good implementation that follows the same pattern as the existing operations in this class. It correctly tracks call counts, validates required parameters, and properly handles errors by converting them to InternalError.

Tests/AblyChatTests/DefaultRoomPresenceTests.swift (15)

5-20: Good basic test for channel name verification.

This test verifies that the channel name matches the expected format, which is an important foundation for presence functionality.


46-72: Well-structured test for presence entry during attachment.

This test effectively simulates the real-world scenario of entering presence while a room is in the attaching state, which is an important use case to verify.


74-115: Comprehensive error handling test for failed attachment.

The test thoroughly verifies the error details when attempting presence operations during a failed attachment, ensuring proper error propagation.


117-138: Good test for invalid room state handling.

This test verifies that attempts to enter presence when the room is in an invalid state are properly rejected with appropriate error information.


163-189: Good test for update presence during attachment.

This test mirrors the structure used for testing enter presence during attachment, providing consistent verification of both operations.


191-232: Thorough test for update failure during attachment.

The test properly verifies error details when attempting to update presence during a failed attachment.


338-364: Well-implemented test for retrieving presence during attachment.

The test follows the same pattern as the enter and update tests, providing consistent verification of all presence operations during attachment.


409-455: Comprehensive test for presence event subscription.

This test verifies that all types of presence events (present, enter, update, leave) are properly received through the subscription, which is crucial for real-time presence functionality.


459-476: Well-structured test for discontinuity handling.

The test properly verifies that discontinuity events are propagated through the presence system, which is important for handling connection issues gracefully.


1-20: Good test structure for channel name verification

The test correctly validates that the channel name is set as expected when initializing DefaultPresence. The test follows a clear given-when-then structure which improves readability.


50-72: Well-structured test for presence operations during attachment

This test effectively validates that users can enter presence while the room is attaching. The use of mock components and async let for concurrent operations creates a realistic test scenario.


76-115: Comprehensive test for handling attachment failures

The test thoroughly examines error handling when entering presence during a failed attachment. It validates the correct error codes and ensures the lifecycle manager was called correctly.


275-294: Good validation of presence checking functionality

The test effectively validates the isUserPresent method by checking both positive and negative cases. The assertion structure is clear and confirms expected behavior.


338-407: Thorough testing of presence retrieval during attachment

These tests provide comprehensive coverage of retrieving presence members while the room is in an attaching state, including both success and failure scenarios. The error validation is particularly well-implemented.


457-476: Proper testing of discontinuity events

This test ensures that discontinuity events from the feature channel are correctly propagated through the DefaultPresence implementation, which is an important aspect of robust presence management.

Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (15)

4-9: Good implementation of mock presence with proper memory management.

The class now properly inherits from NSObject and conforms to @unchecked Sendable, which allows it to be safely used in async contexts while maintaining the expected behavior of Ably's native classes.


11-16: Well-structured initializer with sensible defaults.

The initializer properly sets up the mock state with appropriate defaults, making the mock easy to use in tests with minimal configuration.


18-24: Effective implementation of presence retrieval methods.

These methods correctly handle both unfiltered and filtered retrieval of presence members, supporting the test cases that verify presence state.


34-41: Simple but effective update implementation.

The implementation correctly updates the current member's data and handles callbacks, which is sufficient for testing the update functionality.


52-65: Complete implementation of enter client methods.

The methods properly create and add presence members, trigger callbacks, and set the appropriate action, fully supporting the enter presence test cases.


71-79: Good error handling in update client method.

The precondition check ensures that attempting to update a non-existent client fails fast with a clear error message, which helps maintain test integrity.


89-95: Well-implemented subscribe method with notification of existing members.

The method correctly sets up the callback and notifies it about all existing members, which mirrors the behavior of the real Ably presence implementation.


4-9: Enhanced mock implementation with proper state management

The updated mock now inherits from NSObject and conforms to @unchecked Sendable, with proper state management properties. This facilitates more realistic behavior simulation and enables thorough testing of presence functionality.


11-16: Well-structured initializer

The initializer properly sets up the mock state, including a smart handling of the current member (taking the first member if there's only one). This allows for flexible test configurations.


18-24: Implemented get methods for presence retrieval

Both get methods are now implemented to return members based on query parameters, supporting the test scenarios in DefaultRoomPresenceTests. The error handling in the first method is particularly well done.


34-41: Added update method implementation

The update methods now properly modify the current member's data and call the callback if provided, allowing tests to validate update operations.


43-50: Added leave method implementation

The leave methods now properly remove the current member from the members collection and call the callback if provided, supporting leave operation testing.


52-65: Added enterClient method implementation

The enterClient methods correctly create and add a new member, set the action to enter, and notify subscribers. The implementation ensures proper state for presence tests.


71-79: Good error handling in updateClient

The implementation properly validates that the client exists before attempting the update, with a clear precondition failure message if not. This helps catch test setup issues early.


89-95: Implemented subscribe method

The subscribe method now stores the callback and immediately invokes it for all existing members, which matches the behavior of the real implementation. This is essential for proper presence notification testing.

@maratal
Copy link
Collaborator Author

maratal commented Mar 17, 2025

@maratal can you fix merge conflicts please? I think they were introduced after I merged #234.

Now compiler fails for the reason I can't immediately recognize:

While evaluating request TypeCheckSourceFileRequest(source_file "/Users/runner/work/ably-chat-swift/ably-chat-swift/Tests/AblyChatTests/DefaultRoomPresenceTests.swift")

Couldn't you have a look? @lawrence-forooghian

@lawrence-forooghian
Copy link
Collaborator

Will take a look

@lawrence-forooghian
Copy link
Collaborator

lawrence-forooghian commented Mar 17, 2025

@maratal I imagine this is because of #233; search for https://github.com/ably/ably-chat-swift/issues/233 in the codebase to see how I worked around it

@maratal maratal force-pushed the fix/235-presence-tests branch from 3d4eb27 to f53befd Compare March 17, 2025 22:07
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 17, 2025 22:09 Inactive
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: 0

🧹 Nitpick comments (5)
Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (5)

22-24: Consider returning presenceGetError in all get calls.

Currently, the query-based get method ignores presenceGetError. Consistency might require returning this error if set, as with the other get method.

 func get(_ query: ARTRealtimePresenceQuery, callback: @escaping ARTPresenceMessagesCallback) {
+    if let error = presenceGetError {
+        callback(nil, error)
+        return
+    }
     callback(members.filter { $0.clientId == query.clientId }, nil)
 }

26-32: Consider implementing or removing these unimplemented enter methods.

They currently call fatalError, which may disrupt tests. If they are not required, removing them can avoid accidental usage. If needed, implement them to maintain consistency.


97-99: Attach-aware subscription is stubbed out.

Up to you whether to implement or remove if not used by the tests.


101-103: Filtered subscription by ARTPresenceAction is also stubbed.

If not needed for these tests, removing might keep the code cleaner.


105-107: Attachment-based subscription with presence action is also stubbed.

Same suggestion: implement or remove based on test requirements.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 3d4eb27 and f53befd.

📒 Files selected for processing (8)
  • Sources/AblyChat/RoomFeature.swift (1 hunks)
  • Tests/AblyChatTests/DefaultMessagesTests.swift (6 hunks)
  • Tests/AblyChatTests/DefaultRoomPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (3 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift (5 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift (2 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • Sources/AblyChat/RoomFeature.swift
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleContributor.swift
  • Tests/AblyChatTests/DefaultMessagesTests.swift
  • Tests/AblyChatTests/Helpers/Helpers.swift
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift
  • Tests/AblyChatTests/Mocks/MockRealtimeChannel.swift
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Xcode, iOS (Xcode 16)
🔇 Additional comments (26)
Tests/AblyChatTests/DefaultRoomPresenceTests.swift (17)

5-20: Test struct initialization looks consistent.

The overall structure of this DefaultRoomPresenceTests suite is well-organized, providing a clear setup for verifying presence-related functionality.


22-44: Use a non-empty array check instead of != nil.

The variable client2 is an array, so checking client2 != nil will always pass. Consider verifying !client2.isEmpty to confirm that the member is present.


46-72: Presence enter while attaching is thoroughly tested.

This test correctly simulates the attaching state scenario and verifies that presence enter is deferred until the room is ready.


74-112: Good coverage of failure scenario during attach.

This test properly confirms that an attachment failure leads to the correct error when trying to enter presence.


114-134: Failure path test accurately captures invalid state behavior.

The test ensures a proper error is thrown and helps confirm robust error handling.


136-157: Check for array emptiness instead of != nil.

Same as the earlier comment, the variable client1 is an array. Verifying !client1.isEmpty is more accurate than client1 != nil.


159-185: Presence update while attaching is validated correctly.

The logic verifies that the test waits for the room to be ready before allowing presence updates.


187-225: Failure during attaching is correctly tested for updates.

This checks that an attach error interrupts the update flow as expected.


227-247: Invalid state error handling for presence update.

The test accurately confirms the correct error is thrown when the room state is invalid.


249-266: Coverage for leaving presence is complete.

Removing the member from presence is verified, ensuring correct logic under normal conditions.


270-286: Presence-check functionality appears solid.

Ensures that the presence system accurately detects whether a given user ID is present.


290-305: All-members retrieval logic is tested properly.

Verifies that all present members are returned, covering normal operation.


307-327: Failure during retrieval in invalid state is correctly handled.

Ensures the error path is tested when the room is not in an appropriate state.


329-355: Retrieval while attaching is thoroughly validated.

Checks that the attach flow and wait logic function properly before retrieving presence data.


357-395: Attach failure scenario for retrieval.

Verifies an attach error leads to a matching error on presence retrieval, maintaining consistency.


399-443: Comprehensive subscription coverage for all presence events.

Captures the .present, .enter, .update, and .leave events, confirming the subscription logic is correct.


447-465: Discontinuity handling test is succinct and accurate.

Confirms that emitted discontinuities are surfaced as expected through onDiscontinuity().

Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (9)

4-10: Class setup and concurrency marking look appropriate.

Adopting @unchecked Sendable is reasonable for this test mock when used carefully in concurrency contexts.


11-16: Constructor provides robust initialization.

Ensures syncComplete, members, and presenceGetError are all correctly captured.


34-41: Update methods correctly modify the current member.

Mimics real presence updates by setting data; the callback approach helps confirm asynchronous logic is used in tests.


43-50: Leaving presence properly removes the current member.

This approach matches the expected behavior of leaving an active presence session.


52-65: Enter client logic is straightforward and effective.

Valid for simulating presence entries, and the subscription callback is appropriately invoked.


67-79: Precondition failure might warrant more graceful handling.

Crashing on missing members can be suitable for tests, but confirm this is desired behavior.

Would you like to keep terminating the test when a client does not exist, or handle it with a custom error? If you’d prefer verification, I can provide a script or code snippet to confirm usage across the test suite.


81-88: Client leave logic straightforwardly removes the member.

Properly ensures that once a client leaves, it is no longer in the array.


89-95: Subscription replays existing members.

This is a valid design choice, though it might differ from real-world presence defaults. The approach is acceptable for test scenarios.


109-118: Unsubscribe methods differ in implementation.

func unsubscribe() is unimplemented (fatalError), but unsubscribe(_:) zeroes out the callback. Clarify if you want both to behave consistently.

@maratal
Copy link
Collaborator Author

maratal commented Mar 17, 2025

@maratal I imagine this is because of #233; search for https://github.com/ably/ably-chat-swift/issues/233 in the codebase to see how I worked around it

Thanks @lawrence-forooghian, it's now ready.

Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian left a comment

Choose a reason for hiding this comment

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

Haven't finished reviewing this but will leave some comments based on what I've looked at so far

@maratal maratal force-pushed the fix/235-presence-tests branch from f53befd to 5a9cba5 Compare March 19, 2025 23:36
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat March 19, 2025 23:38 Inactive
lawrence-forooghian added a commit that referenced this pull request Apr 30, 2025
Resolves #242.

The API changes are based on the JS API changes from branch
integration/single-channel-integration at 0924cd5. The behavioural
changes are based on [1] at 27ddbb3.

This commit is quite large, and combines API and behavioural changes,
because the new specification points are written with reference to the
new API and so it was hard to disentangle the two.

Key changes to public API:

- Updated room options API:
  - there's no concept of a feature being turned "on" any more, and
    correspondingly no error when you try and use a feature that's not
    turned on

  - removed `allFeaturesEnabled`, since the equivalent has been removed
    from JS

  - you can now fetch a room without passing a room options; this uses
    the default options

- Removed feature-specific error codes

- Discontinuities now always have an error

- Extended the set of RoomStatus that can have an error (this does not
  have an equivalent in the JS API; it's a result of the room lifecycle
  manager statuses that mean we're now more driven by the errors emitted
  by ably-cocoa; we still need to revisit this in #12)

Key changes to interactions with Realtime:

- Switched to v3 of the REST API

- Use a single channel for all room features; this simplifies the room
  lifecycle manager and the DefaultRoom class

- Room reactions now use ephemeral messages

- Resolves #133 (setting of presence-related channel modes).

Internal changes:

- Removed FeatureChannel and RoomLifecycleContributor

- Switch to using callbacks for ably-cocoa state changes (i.e. end the
  experiment of using AsyncSequence in the ably-cocoa wrapper) and
  enforce that ably-cocoa deliver its state changes on the main thread;
  together with fc83fc1 this allows us to no longer have to work around
  the fact that the spec's method for detecting a discontinuity assumes a
  single-threaded environment, hence resolving #239.

[1] ably/specification#282
lawrence-forooghian added a commit that referenced this pull request Apr 30, 2025
Resolves #242.

The API changes are based on the JS API changes from branch
integration/single-channel-integration at 0924cd5. The behavioural
changes are based on [1] at 27ddbb3.

This commit is quite large, and combines API and behavioural changes,
because the new specification points are written with reference to the
new API and so it was hard to disentangle the two.

Key changes to public API:

- Updated room options API:
  - there's no concept of a feature being turned "on" any more, and
    correspondingly no error when you try and use a feature that's not
    turned on

  - removed `allFeaturesEnabled`, since the equivalent has been removed
    from JS

  - you can now fetch a room without passing a room options; this uses
    the default options

- Removed feature-specific error codes

- Discontinuities now always have an error

- Extended the set of RoomStatus that can have an error (this does not
  have an equivalent in the JS API; it's a result of the room lifecycle
  manager statuses that mean we're now more driven by the errors emitted
  by ably-cocoa; we still need to revisit this in #12)

Key changes to interactions with Realtime:

- Switched to v3 of the REST API

- Use a single channel for all room features; this simplifies the room
  lifecycle manager and the DefaultRoom class

- Room reactions now use ephemeral messages

- Resolves #133 (setting of presence-related channel modes).

Internal changes:

- Removed FeatureChannel and RoomLifecycleContributor

- Switch to using callbacks for ably-cocoa state changes (i.e. end the
  experiment of using AsyncSequence in the ably-cocoa wrapper) and
  enforce that ably-cocoa deliver its state changes on the main thread;
  together with fc83fc1 this allows us to no longer have to work around
  the fact that the spec's method for detecting a discontinuity assumes a
  single-threaded environment, hence resolving #239.

[1] ably/specification#282
lawrence-forooghian added a commit that referenced this pull request May 1, 2025
Resolves #242.

The API changes are based on the JS API changes from branch
integration/single-channel-integration at 0924cd5. The behavioural
changes are based on [1] at 2f88b1b.

This commit is quite large, and combines API and behavioural changes,
because the new specification points are written with reference to the
new API and so it was hard to disentangle the two.

Key changes to public API:

- Updated room options API:
  - there's no concept of a feature being turned "on" any more, and
    correspondingly no error when you try and use a feature that's not
    turned on

  - removed `allFeaturesEnabled`, since the equivalent has been removed
    from JS

  - you can now fetch a room without passing a room options; this uses
    the default options

- Removed feature-specific error codes

- Discontinuities now always have an error

- Extended the set of RoomStatus that can have an error (this does not
  have an equivalent in the JS API; it's a result of the room lifecycle
  manager statuses that mean we're now more driven by the errors emitted
  by ably-cocoa; we still need to revisit this in #12)

Key changes to interactions with Realtime:

- Switched to v3 of the REST API

- Use a single channel for all room features; this simplifies the room
  lifecycle manager and the DefaultRoom class

- Room reactions now use ephemeral messages

- Resolves #133 (setting of presence-related channel modes).

Internal changes:

- Removed FeatureChannel and RoomLifecycleContributor

- Switch to using callbacks for ably-cocoa state changes (i.e. end the
  experiment of using AsyncSequence in the ably-cocoa wrapper) and
  enforce that ably-cocoa deliver its state changes on the main thread;
  together with fc83fc1 this allows us to no longer have to work around
  the fact that the spec's method for detecting a discontinuity assumes a
  single-threaded environment, hence resolving #239.

[1] ably/specification#282
@maratal maratal force-pushed the fix/235-presence-tests branch from b3427a1 to c74b428 Compare May 17, 2025 19:35
@maratal maratal changed the title [ECO-5251] Presence tests without using DefaultRoomLifecycleManager. [ECO-5251] Presence tests. May 17, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat May 17, 2025 19:36 Inactive
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: 0

♻️ Duplicate comments (1)
Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1)

61-64: ⚠️ Potential issue

Fix force unwrapping of optional clientId.

The force unwrap of clientId! could cause a runtime crash if clientId is nil.

-    var callRecorderDescription: String {
-        "clientId=\(clientId!)"
+    var callRecorderDescription: String {
+        "clientId=\(clientId ?? "nil")"

Note: I see this issue was previously flagged in a past review and supposedly addressed, but the fix doesn't appear to be reflected in this code.

🧹 Nitpick comments (5)
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (2)

14-20: Property can be non-optional, which removes the run-time fatalError guard.

resultOfWaitToBeAbleToPerformPresenceOperations is declared as optional but always initialised (default parameter provides .success(())).
Turning it into a non-optional removes the need for the guard let … else fatalError at the call-site and makes the intent clearer (tests that really want the “unset → crash” behaviour can still pass nil explicitly by changing the parameter type to Result<Void, ARTErrorInfo>?).

-    private let resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo>?
+    private let resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo>

and in the initializer:

-    init(...,
-         resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo> = .success(())) {
+    init(...,
+         resultOfWaitToBeAbleToPerformPresenceOperations: Result<Void, ARTErrorInfo> = .success(())) {

…followed by removing the guard inside waitToBeAbleToPerformPresenceOperations.
This simplifies the mock and avoids surprising crashes in future refactors.


66-79: Minor nit: recorded argument can keep the enum value instead of its string description.

Storing "\(requestedByFeature)" means the test must compare against the exact CustomStringConvertible
implementation. Keeping the raw enum makes comparisons type-safe and immune to description changes:

-            arguments: ["requestedByFeature": "\(requestedByFeature)"]
+            arguments: ["requestedByFeature": requestedByFeature]

MockMethodCallRecorder.compareAny already handles enums (via String currently); adding a generic Equatable fallback would make this change work seamlessly.

Tests/AblyChatTests/Helpers/Helpers.swift (2)

97-122: compareAny misses several common literal types and could short-circuit earlier.

The helper is very handy, but:

  1. Double, Float, Date, UUID, etc. are not covered – comparisons will silently fall through to false.
  2. The recursive array comparison performs count check inside the loop; moving it outside is cheaper.
  3. A generic Equatable branch would catch most simple cases without hand-listing every type.

Illustrative refactor:

+    // Generic fast-path for any Equatable pair of the same concrete type
+    if let lhs = any1 as? (any Equatable),
+       let rhs = any2 as? (any Equatable),
+       type(of: lhs) == type(of: rhs) {
+        return lhs == rhs
+    }

Followed by type-specific fallbacks only where required (e.g. NSDictionary deep equality for [String:Any]).
This keeps the helper future-proof and reduces maintenance.


146-164: Lock scope can be reduced to minimise contention.

hasRecord holds mutex for the entire search as well as the equality work.
Copying the array under lock and performing the expensive search after releasing the lock keeps the recorder thread-safe while improving parallelism, e.g.:

-        mutex.lock()
-        let result = records.contains { record in
+        mutex.lock()
+        let snapshot = records
         mutex.unlock()
+        let result = snapshot.contains { record in
             ...
         }
-        mutex.unlock()
         return result

The pattern mirrors the write-heavy addRecord, but optimises read paths used by assertions in heavily concurrent tests.

Tests/AblyChatTests/DefaultPresenceTests.swift (1)

81-88: Factor out the “work-around-closure” once the compiler bug is gone.

The repeated TODO blocks add indirection and noise to each negative-test case.
Consider extracting a helper like #expectAsyncThrows (or remove the closure wrapper entirely) when upgrading past the compiler issue referenced in #233 to keep the tests concise.

No action required right now, but worth tracking so dead code doesn’t linger.

Also applies to: 204-213, 358-367, 415-424

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between b3427a1 and c74b428.

📒 Files selected for processing (5)
  • Tests/AblyChatTests/DefaultPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift
🧰 Additional context used
🧬 Code Graph Analysis (1)
Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (3)
Tests/AblyChatTests/Helpers/Helpers.swift (1)
  • addRecord (146-150)
Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (2)
  • get (23-29)
  • get (31-37)
Sources/AblyChat/InternalError.swift (6)
  • toInternalError (35-37)
  • toInternalError (41-43)
  • toInternalError (47-49)
  • toInternalError (53-55)
  • toInternalError (59-61)
  • toInternalError (65-67)
⏰ Context from checks skipped due to timeout of 90000ms (34)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: Generate code coverage
🔇 Additional comments (3)
Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (3)

7-9: Improved mock implementation provides better testability.

The mock now returns dummy ARTEventListener instances for subscribe methods and implements a no-op for unsubscribe, making it more useful for testing without crashing with fatal errors.

Also applies to: 11-13, 15-17


23-29: Enhanced testing capabilities with call recording.

The implementation now records method calls with their arguments instead of failing with fatal errors. This pattern allows tests to verify which methods were called with what arguments, greatly improving testability while reducing the logic within the mock itself.

Also applies to: 31-37, 39-44, 46-51, 53-58


5-6:

✅ Verification successful

Verify thread safety of the callRecorder.

The callRecorder is used to track method invocations across multiple methods, which could potentially be called from different threads. Make sure that MockMethodCallRecorder implements proper synchronization mechanisms to avoid race conditions.


🏁 Script executed:

#!/bin/bash
# Check if MockMethodCallRecorder is thread-safe
rg -A 20 "class MockMethodCallRecorder" --type swift

Length of output: 1473


🏁 Script executed:

#!/bin/bash
# Locate the file containing MockMethodCallRecorder and display its implementation along with lock usage
file=$(rg -l "class MockMethodCallRecorder" --type swift)
echo "Inspecting file: $file"
echo "----- Class Definition and Methods -----"
sed -n '1,200p' "$file"
echo
echo "----- Lock Usage -----"
rg -n "mutex" -A3 "$file"
echo
echo "----- Methods Operating on records -----"
rg -nE "func (record|callCount|reset)" -A5 "$file"

Length of output: 7328


Thread Safety of MockMethodCallRecorder Verified

The addRecord and hasRecord methods both lock access to the shared records array using an NSLock, ensuring serialized reads and writes and preventing race conditions.

Optionally, you could replace the explicit lock()/unlock() calls with a defer { mutex.unlock() } pattern for added safety in future early-exit scenarios, but the current implementation is thread-safe as is.

@maratal maratal force-pushed the fix/235-presence-tests branch from c74b428 to ce99af3 Compare May 17, 2025 20:27
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: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between c74b428 and ce99af3.

📒 Files selected for processing (6)
  • Sources/AblyChat/RoomLifecycleManager.swift (1 hunks)
  • Tests/AblyChatTests/DefaultPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • Sources/AblyChat/RoomLifecycleManager.swift
🚧 Files skipped from review as they are similar to previous changes (4)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift
  • Tests/AblyChatTests/Helpers/Helpers.swift
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift
🔇 Additional comments (10)
Tests/AblyChatTests/DefaultPresenceTests.swift (10)

8-9: Clear specification mapping with @SPEC and @specOneOf annotations

Good use of specification annotations to clearly trace test coverage back to specific requirements. This practice enhances maintainability by providing explicit documentation of which specification items are being tested.


11-33: LGTM: Well-structured test for entering presence

This test effectively verifies that entering presence sends the correct data to the Ably SDK. The Given-When-Then structure provides clear separation of test phases.


36-60: Good test for entering presence during attachment

This test properly verifies that the presence operations coordinate with the room lifecycle manager, which is crucial for ensuring proper state management during transitions.


117-126: Test pattern for error case is consistent

The error verification pattern is consistent with other tests, which is good for maintainability. The use of isChatError helper ensures proper error validation.


131-156: LGTM: Well-structured test for updating presence

This test effectively validates that updating presence sends the correct data to the Ably SDK. The pattern is consistent with the enter test which aids readability.


254-279: Good implementation of leave presence test

This test properly verifies that leaving presence invokes the correct Ably SDK method with the expected parameters.


283-308: Effective test for isUserPresent functionality

The test properly verifies that the query is constructed correctly when checking if a user is present.


312-338: Good implementation of presence retrieval test

The test correctly verifies that getting all members of the presence set invokes the right Ably SDK method.


436-487: Comprehensive test for presence event subscription

Excellent test coverage for subscribing to presence events. The test verifies all four event types (present, enter, update, leave) and confirms the correct event details are received.


1-490: Overall excellent test coverage for presence functionality

This file provides comprehensive test coverage for all presence-related operations including enter, update, leave, query, and subscribe functionality. Tests cover happy paths, error cases, and state transitions. The structure is consistent and follows good testing practices.

Some minor suggestions:

  1. Consider extracting common setup code to reduce duplication, as many tests share similar initialization patterns
  2. Follow up on the TODOs once the compiler issue is fixed and specification PR is merged

@maratal maratal force-pushed the fix/235-presence-tests branch from ce99af3 to 410e4ae Compare May 17, 2025 20:29
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat May 17, 2025 20:30 Inactive
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: 0

♻️ Duplicate comments (2)
Tests/AblyChatTests/DefaultPresenceTests.swift (2)

489-489: Remove @specUntested annotation.

Remove this entire line with the @specUntested annotation and TODO comment once specification PR 282 is merged, as noted in past review comments.

-    // @specUntested CHA-PR8 - Discontinuity is now only within `Room` itself. TODO: Remove this once specification PR 282 is merged.

81-91: 🛠️ Refactor suggestion

Remove compiler crash workaround.

The TODO comments about avoiding compiler crash (issue #233) with the workaround pattern should be removed now that Xcode 16.3+ is available, as noted in past review comments. The tests should call the API directly inside the #expect blocks.

Apply this pattern across all instances:

-        // TODO: avoids compiler crash (https://github.com/ably/ably-chat-swift/issues/233), revert once Xcode 16.3 released
-        let doIt = {
-            // When
-            try await defaultPresence.enter()
-        }
-        await #expect {
-            try await doIt()
-        } /* Then */ throws: { error in
+        await #expect {
+            try await defaultPresence.enter()
+        } throws: { error in
             isChatError(error, withCodeAndStatusCode: .variableStatusCode(.roomInInvalidState, statusCode: 500), cause: attachError)
         }

Also applies to: 117-127, 204-214, 240-250, 357-367, 415-425

🧹 Nitpick comments (1)
Tests/AblyChatTests/Helpers/Helpers.swift (1)

173-178: Consider adding a comment explaining the implementation.

Line 176 has a comment "Probably there is a better way of doing this" but doesn't explain what exactly this conversion does or why it's implemented this way. Consider adding more details about the implementation and its purpose.

 extension [String: Any] {
     func toAblyCocoaData() -> Any {
-        // Probaly there is a better way of doing this
+        // Converts a Swift dictionary to Ably Cocoa-compatible data format
+        // by wrapping it in PresenceDataDTO and then converting to JSONValue
+        // This ensures compatibility with Ably Cocoa's serialization expectations
         PresenceDataDTO(userCustomData: JSONValue(ablyCocoaData: self)).toJSONValue.toAblyCocoaData
     }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between ce99af3 and 410e4ae.

📒 Files selected for processing (6)
  • Sources/AblyChat/RoomLifecycleManager.swift (1 hunks)
  • Tests/AblyChatTests/DefaultPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • Sources/AblyChat/RoomLifecycleManager.swift
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift
⏰ Context from checks skipped due to timeout of 90000ms (34)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: Generate code coverage
🔇 Additional comments (3)
Tests/AblyChatTests/Helpers/Helpers.swift (2)

124-165: Well-implemented thread-safe mock method call recorder.

The MockMethodCallRecorder class is well designed with proper thread safety using mutex locks for both reads and writes. This implementation correctly addresses the data race issues that were previously flagged in reviews.


97-122: Comprehensive deep equality check implementation.

The compareAny function provides thorough type-checking and comparison for various data types, which is essential for testing heterogeneous values. The recursive implementation for arrays is particularly well done.

Tests/AblyChatTests/DefaultPresenceTests.swift (1)

5-487: Well-structured and comprehensive presence test suite.

The test suite provides thorough coverage of presence functionality including enter, update, leave, query, and subscription operations. Tests appropriately verify both success scenarios and error handling. The use of mock objects with call recorders allows for precise verification of interactions with dependencies.

@maratal maratal force-pushed the fix/235-presence-tests branch from 410e4ae to 6cf2821 Compare May 17, 2025 21:06
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat May 17, 2025 21:08 Inactive
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: 0

♻️ Duplicate comments (1)
Tests/AblyChatTests/DefaultPresenceTests.swift (1)

80-90: 🛠️ Refactor suggestion

Remove the compiler-crash workaround closure once Xcode 16.3+ is in CI

The doIt wrapper and the surrounding TODO comment were temporary to avoid
SR-16440 (issue #233).
CI now runs Xcode 16.3; the workaround can be safely removed for cleaner tests:

-        // TODO: avoids compiler crash (https://github.com/ably/ably-chat-swift/issues/233), revert once Xcode 16.3 released
-        let doIt = {
-            try await defaultPresence.enter()
-        }
-        await #expect {
-            try await doIt()
-        } /* Then */ throws: { error in
+        await #expect {
+            try await defaultPresence.enter()
+        } throws: { error in
             isChatError(error, withCodeAndStatusCode: .variableStatusCode(.roomInInvalidState, statusCode: 500), cause: attachError)
         }

Apply the same removal to all six occurrences highlighted above.

Also applies to: 118-126, 204-214, 241-249, 358-366, 415-424

🧹 Nitpick comments (1)
Tests/AblyChatTests/DefaultPresenceTests.swift (1)

12-23: Consider extracting a reusable makeDefaultPresence() test helper

Every test repeats ~15 lines of boiler-plate to build a DefaultPresence
instance. A small factory function would:

  • cut >120 duplicated lines,
  • surface the intent of the “Given” section,
  • make future changes (e.g. new ctor parameter) one-liner.

Example:

func makePresence(
    roomLifecycleManager: MockRoomLifecycleManager = .init(),
    channelName: String = "basketball::$chat::$chatMessages"
) async -> DefaultPresence {
    let channel = await MockRealtimeChannel(name: channelName)
    return await DefaultPresence(
        channel: channel,
        roomLifecycleManager: roomLifecycleManager,
        roomID: "basketball",
        clientID: "client1",
        logger: TestLogger(),
        options: .init()
    )
}

Tests then become:

let defaultPresence = await makePresence()
try await defaultPresence.enter()

Also applies to: 38-50, 135-147, 160-172, 256-268, 285-298, 315-327, 371-383, 439-451

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 410e4ae and 6cf2821.

📒 Files selected for processing (6)
  • Sources/AblyChat/RoomLifecycleManager.swift (1 hunks)
  • Tests/AblyChatTests/DefaultPresenceTests.swift (1 hunks)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift (4 hunks)
  • Tests/AblyChatTests/Helpers/Helpers.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift (1 hunks)
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • Tests/AblyChatTests/DefaultRoomLifecycleManagerTests.swift
  • Sources/AblyChat/RoomLifecycleManager.swift
  • Tests/AblyChatTests/Mocks/MockRoomLifecycleManager.swift
  • Tests/AblyChatTests/Mocks/MockRealtimePresence.swift
  • Tests/AblyChatTests/Helpers/Helpers.swift
⏰ Context from checks skipped due to timeout of 90000ms (34)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, tvOS (Xcode 16.1)
  • GitHub Check: Example app, iOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.2)
  • GitHub Check: Example app, tvOS (Xcode 16.3)
  • GitHub Check: Example app, tvOS (Xcode 16.1)
  • GitHub Check: Example app, tvOS (Xcode 16.2)
  • GitHub Check: Xcode, release configuration, macOS (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.3)
  • GitHub Check: Example app, macOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.1)
  • GitHub Check: Xcode, tvOS (Xcode 16.3)
  • GitHub Check: Xcode, release configuration, iOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.2)
  • GitHub Check: Example app, iOS (Xcode 16.1)
  • GitHub Check: Example app, macOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.2)
  • GitHub Check: Xcode, iOS (Xcode 16.3)
  • GitHub Check: Xcode, macOS (Xcode 16.2)
  • GitHub Check: Xcode, tvOS (Xcode 16.1)
  • GitHub Check: Xcode, iOS (Xcode 16.1)
  • GitHub Check: Xcode, macOS (Xcode 16.3)
  • GitHub Check: SPM (Xcode 16.1)
  • GitHub Check: SPM, release configuration (Xcode 16.3)
  • GitHub Check: SPM, release configuration (Xcode 16.2)
  • GitHub Check: SPM, release configuration (Xcode 16.1)
  • GitHub Check: SPM (Xcode 16.2)
  • GitHub Check: Generate code coverage
🔇 Additional comments (1)
Tests/AblyChatTests/DefaultPresenceTests.swift (1)

28-32:

❌ Incorrect review comment

Verify argument key – should it be clientId instead of name?

enterClient(_:data:) takes the clientId as its first unlabeled parameter.
The call-recorder assertion is matching the key "name", which looks out of line with the API and with the rest of the file (everywhere else you use "clientID"/"clientId").

A mismatched key will cause the expectation to pass even when the client id is wrong, defeating the purpose of the test.

-            arguments: ["name": "client1",
+            arguments: ["clientId": "client1",

Please check the exact key used by MockRealtimePresence’s callRecorder for enterClient and adjust all similar assertions if necessary.


🏁 Script executed:

#!/bin/bash
# Locate the recording call in the mock to confirm the argument key
rg -n 'record\(.*enterClient' -t swift

Length of output: 40


🏁 Script executed:

#!/bin/bash
echo "## Searching for MockRealtimePresence class definition"
rg -n 'class .*MockRealtimePresence' -t swift

echo -e "\n## Listing Swift files matching '*Mock*Presence*'"
fd -e swift | grep -i 'Mock.*Presence'

echo -e "\n## Searching for callRecorder usage"
rg -n 'callRecorder' -t swift

echo -e "\n## Searching for recordCall usage"
rg -n 'recordCall' -t swift

echo -e "\n## Searching for hasRecord usage"
rg -n 'hasRecord' -t swift || true

echo -e "\n## Searching for enterClient function definitions"
rg -n 'func enterClient' -t swift

echo -e "\n## Searching for enterClient calls"
rg -n 'enterClient(' -t swift

Length of output: 5835


🏁 Script executed:

#!/bin/bash
# Show the enterClient implementation in MockRealtimePresence
rg -n 'func enterClient' -C5 Tests/AblyChatTests/Mocks/MockRealtimePresence.swift

# Show how arguments are recorded in addRecord for enterClient
rg -n 'addRecord' -C5 Tests/AblyChatTests/Mocks/MockRealtimePresence.swift

Length of output: 1809


Ignore argument key change – “name” is correct in mock
MockRealtimePresence’s enterClient(_ name:data:) records the argument under the key "name", so the test’s expectation using "name" matches the mock implementation. No change required.

Likely an incorrect or invalid review comment.

@maratal maratal changed the title [ECO-5251] Presence tests. [ECO-5251] Presence tests (single channel) May 18, 2025
@maratal maratal mentioned this pull request May 22, 2025
@github-actions github-actions bot temporarily deployed to staging/pull/239/AblyChat May 24, 2025 21:13 Inactive
@lawrence-forooghian
Copy link
Collaborator

Pushed a change to use mutex.withLock instead of .lock() and .unlock(); less error-prone and you don't have to use an intermediate variable for the result

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Restore messages, presence, and room reactions tests

4 participants