Skip to content

Conversation

laevandus
Copy link
Contributor

@laevandus laevandus commented Oct 7, 2025

🔗 Issue Links

Related: #IOS-1173

🎯 Goal

Describe why we are making this change.

📝 Summary

Provide bullet points with the most important changes in the codebase.

🛠 Implementation

Provide a detailed description of the implementation and explain your decisions if you find them relevant.

🎨 Showcase

Add relevant screenshots and/or videos/gifs to easily see what this PR changes, if applicable.

Before After
img img

🧪 Manual Testing Notes

Explain how this change can be tested manually, if applicable.

☑️ Contributor Checklist

  • I have signed the Stream CLA (required)
  • This change should be manually QAed
  • Changelog is updated with client-facing changes
  • Changelog is updated with new localization keys
  • New code is covered by unit tests
  • Documentation has been updated in the docs-content repo

Summary by CodeRabbit

  • New Features

    • Debug menu enhanced with stepwise flows for adding/removing/showing members and channel truncation, plus inline input dialogs and clearer messages.
  • Bug Fixes / Reliability

    • Improved server/network robustness (stricter request/body handling, multipart/header fixes, safer WebSocket handling).
    • Minor UI polish in share/composer flows for smoother behavior.
  • Chores

    • Lint/config simplifications and widespread formatting cleanups.
  • Testing & Tooling

    • Test helpers, mocks, and assertion APIs refined; some test utilities/signatures updated.

@laevandus laevandus requested a review from a team as a code owner October 7, 2025 13:25
@laevandus laevandus added the 🤖 CI/CD Any work related to CI/CD label Oct 7, 2025
Copy link

coderabbitai bot commented Oct 7, 2025

Walkthrough

Widespread formatting, import-order, lint/config and header updates across the repo; several targeted behavioral edits: DebugMenu alert flow rewritten, ParticipantRobot.uploadAttachment gains in-thread handling, HttpParser guards negative Content-Length, sendfile write loop improved, and SHA1 converted from struct to enum.

Changes

Cohort / File(s) Summary of Changes
Lint & Format configs
\.swiftlint.yml, \.swiftformat
Exclude paths adjusted, trailing_whitespace rule removed, and SwiftFormat rule/--exclude syntax updated.
DemoShare UI
DemoShare/DemoShareView.swift, DemoShare/DemoShareViewModel.swift, DemoShare/ShareViewController.swift
Replaced count == 0 with isEmpty, reordered imports, and made whitespace/import formatting edits only.
Example apps
Examples/... (e.g., Examples/EdgeCases/ViewController.swift, Examples/YouTubeClone/..., Examples/iMessageClone/...)
Removed viewDidLoad override in EdgeCases VC; minor whitespace and loop/alert formatting tweaks.
UITest app (app code)
StreamChatUITestsApp/...
Import reorder and formatting; DebugMenu rewritten into segmented alert flows (add/remove/show members, truncate) and new presentAlert overload accepting text input.
UITest suite (tests & robots)
StreamChatUITestsAppUITests/...
Import reorders and formatting; public API changes: MessageListPage.ContextMenu.Element changed struct → enum, UserRobot.assertQuotedMessage(...) gained quotedText param; many isEmpty/count -> isEmpty adjustments.
Test Mock Server (Swifter & MockServer)
TestTools/StreamChatTestMockServer/...
Mostly formatting/import reorders; functional edits include ChannelConfig CodingKeys simplification, AttachmentResponses closures ignoring request param, HttpParser negative Content-Length guard, HttpRequest/HttpRouter .isEmpty fixes, partial-write loop in sendfile, WebSocket frame-handling normalizations, and SHA1 changed struct → enum.
TestTools helpers & mocks
TestTools/StreamChatTestTools/...
Formatting and API-signature refinements in test helpers (XCTest helper overloads/new params), ParticipantRobot.uploadAttachment updated with in-thread parent handling and conditional websocket message fields, assorted import reorders.
Package / Playgrounds / Podspecs / Misc
Package.swift, Stream.playground/..., *.podspec, assorted files
Header updates, minor formatting/parenthesis alignment, import order changes, and Ruby podspec syntax/style conversions.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant DebugMenu
  participant Alerts as "presentAlert(...)"
  participant ChannelAPI as "Channel actions"

  User->>DebugMenu: open debug menu
  DebugMenu->>Alerts: presentAlert("Choose action")
  note right of Alerts #DDEEFF: each action presents its own focused alert flow
  Alerts-->>DebugMenu: selected action (e.g., Add member)
  DebugMenu->>Alerts: presentAlert(input placeholder, OK handler)
  Alerts->>ChannelAPI: perform add/remove/truncate/showMembers
  ChannelAPI-->>Alerts: success / error
  Alerts-->>User: show success or error message
Loading
sequenceDiagram
  autonumber
  participant ParticipantRobot
  participant TypingAPI as "Typing API"
  participant WS as "WebSocketMessage"

  ParticipantRobot->>ParticipantRobot: uploadAttachment(inThread: Bool)
  alt inThread == true
    ParticipantRobot->>TypingAPI: startTypingInThread(parentId)
    TypingAPI-->>ParticipantRobot: ack
    ParticipantRobot->>WS: send message (channelId: nil, type: reply)
    ParticipantRobot->>TypingAPI: stopTypingInThread(parentId)
  else inThread == false
    ParticipantRobot->>TypingAPI: startTyping(channelId)
    TypingAPI-->>ParticipantRobot: ack
    ParticipantRobot->>WS: send message (channelId: channelId, type: regular)
    ParticipantRobot->>TypingAPI: stopTyping(channelId)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • testableapple

Poem

"I hopped through imports and nibbled a line,
Split alerts and threaded a reply so fine,
Guarded a parser, mended a socket's pace,
Turned SHA1 to enum, looped writes in place,
Cleaned trailing spaces — a tidy rabbit's trace. 🐇"

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning While the PR’s intent is to update CI configurations, it includes extensive formatting, import reordering, and minor code adjustments across many unrelated files, which are beyond the scope of removing a SwiftLint rule and do not align with the linked issue’s focus on CI tool unification. Please separate the CI configuration changes into a focused PR and move the broadly scoped formatting and code edits into a separate review with a clear purpose and context.
Docstring Coverage ⚠️ Warning Docstring coverage is 5.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Linked Issues Check ❓ Inconclusive The linked issue requests unifying rules and versions for SwiftLint and SwiftFormat across CI, but the PR only removes and renames specific rules without addressing version alignment or demonstrating how the changes synchronize the two tool configurations, so it is unclear if the unification objective is fully met. Please clarify how the modified SwiftLint and SwiftFormat configurations unify rule sets and versions as described in IOS-1173 and update the PR description to document the version changes or cross-tool consistency measures applied.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly identifies that the pull request modifies linting behavior by updating linter rules and the set of paths subject to linting, which aligns with the primary changes to the SwiftLint configuration in the diff.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ci/remove-trailing-whitespace

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@Stream-SDK-Bot
Copy link
Collaborator

Stream-SDK-Bot commented Oct 7, 2025

SDK Size

title develop branch diff status
StreamChat 8.25 MB 8.25 MB 0 KB 🟢
StreamChatUI 4.89 MB 4.89 MB 0 KB 🟢

Copy link

github-actions bot commented Oct 7, 2025

1 Warning
⚠️ Big PR

Generated by 🚫 Danger

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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (1)

415-421: Align messageType and channelReply with replyToMessageInThread pattern.

The websocketMessage call has two inconsistencies compared to replyToMessageInThread (lines 260–268):

  1. channelId is nil when inThread, but replyToMessageInThread keeps it as server.currentChannelId. Verify if this is intentional.
  2. messageType ignores alsoInChannel: When inThread is true, messageType is always .reply regardless of alsoInChannel. In replyToMessageInThread, when alsoSendInChannel is true, messageType is .regular and channelReply is true.

When a user uploads an attachment in a thread with alsoInChannel: true, the message may not appear in the main channel as expected.

Apply this diff to align with the established pattern:

 server.websocketMessage(
-    channelId: inThread ? nil : server.currentChannelId,
+    channelId: server.currentChannelId,
     messageId: TestData.uniqueId,
     parentId: parentId,
-    messageType: !inThread ? .regular : .reply,
+    messageType: (inThread && !alsoInChannel) ? .reply : .regular,
     eventType: .messageNew,
-    user: participant()
+    user: participant(),
+    channelReply: inThread && alsoInChannel
 )
StreamChatUITestsApp/DebugMenu.swift (1)

129-135: Use .cancel for Cancel actions and ensure main-thread presentation.

Cancel should use .cancel (not .destructive). Also guard present on main to avoid UI-thread violations.

-        alert.addAction(.init(title: "Cancel", style: .destructive, handler: { _ in
+        alert.addAction(.init(title: "Cancel", style: .cancel, handler: { _ in
             cancelHandler?()
         }))
-
-        viewController.present(alert, animated: true, completion: nil)
+        if Thread.isMainThread {
+            viewController.present(alert, animated: true, completion: nil)
+        } else {
+            DispatchQueue.main.async {
+                viewController.present(alert, animated: true, completion: nil)
+            }
+        }
-        alert.addAction(.init(title: "Cancel", style: .destructive, handler: { _ in
+        alert.addAction(.init(title: "Cancel", style: .cancel, handler: { _ in
             cancelHandler?()
         }))
-
-        viewController.present(alert, animated: true, completion: nil)
+        if Thread.isMainThread {
+            viewController.present(alert, animated: true, completion: nil)
+        } else {
+            DispatchQueue.main.async {
+                viewController.present(alert, animated: true, completion: nil)
+            }
+        }

Also applies to: 160-165

🧹 Nitpick comments (5)
TestTools/StreamChatTestMockServer/MockServer/ChannelConfig.swift (1)

107-112: Consider keeping explicit rawValues for refactoring safety.

Removing explicit rawValue assignments (e.g., changing case search = "search" to case search) relies on Swift's synthesized rawValues. While functionally equivalent now, this reduces safety for future refactoring:

  • If a case is renamed (e.g., case searchcase isSearchEnabled), the rawValue changes automatically from "search" to "isSearchEnabled"
  • This silently breaks JSON encoding/decoding compatibility
  • The update(json:) method (lines 119-133) depends on these rawValues remaining stable

Revert to explicit rawValues to protect against accidental breaking changes:

-        case search
-        case reactions
-        case replies
-        case quotes
-        case mutes
-        case uploads
+        case search = "search"
+        case reactions = "reactions"
+        case replies = "replies"
+        case quotes = "quotes"
+        case mutes = "mutes"
+        case uploads = "uploads"
         case urlEnrichment = "url_enrichment"
         case customEvents = "custom_events"
         case pushNotifications = "push_notifications"
-        case reminders
+        case reminders = "reminders"

Also applies to: 116-116

TestTools/StreamChatTestMockServer/Swifter/HttpServer.swift (1)

21-34: Optional: Route initialization reordering.

The route properties are now initialized in a different order (uppercase variants first, then lowercase). This is functionally equivalent since both sets of properties wrap the same router instance. However, the rationale for this reordering is unclear.

If there's no specific reason for this order, consider keeping the original initialization order for consistency with past versions, or document why uppercase routes should be initialized first.

StreamChatUITestsApp/DebugMenu.swift (3)

31-39: Avoid Optional(...) in titles; use cid?.description ?? "unknown" instead of String(describing:).

-                                    title: "Couldn't add user \(id) to channel \(String(describing: channelController.cid))",
+                                    title: "Couldn't add user \(id) to channel \(channelController.cid?.description ?? "unknown")",
-                                            title: "Couldn't remove user \(member.id) from channel \(String(describing: channelController.cid))",
+                                            title: "Couldn't remove user \(member.id) from channel \(channelController.cid?.description ?? "unknown")",

Also applies to: 49-56


23-31: Trim user input before validation to avoid whitespace-only IDs.

-                        guard let id = id, !id.isEmpty else {
+                        let trimmed = id?.trimmingCharacters(in: .whitespacesAndNewlines)
+                        guard let id = trimmed, !id.isEmpty else {
                             self.presentAlert(
                                 in: viewController,
                                 title: "User ID is not valid",
                                 actions: []
                             )
                             return
                         }

73-77: Present a readable members list; avoid debugDescription of [String?].

-                            message: channelController.channel?.lastActiveMembers.map(\.name).debugDescription,
+                            message: channelController.channel?
+                                .lastActiveMembers
+                                .map { $0.name ?? $0.id }
+                                .joined(separator: "\n")
+                            ?? "No members",
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c1450e6 and 74a244f.

📒 Files selected for processing (107)
  • DemoShare/DemoShareView.swift (1 hunks)
  • DemoShare/DemoShareViewModel.swift (1 hunks)
  • DemoShare/ShareViewController.swift (1 hunks)
  • Examples/EdgeCases/ViewController.swift (1 hunks)
  • Examples/YouTubeClone/Composer/YTChatComposerViewController.swift (0 hunks)
  • Examples/iMessageClone/iMessageComposerVC.swift (0 hunks)
  • Package.swift (2 hunks)
  • Stream.playground/Contents.swift (1 hunks)
  • StreamChatUITestsApp/AppDelegate.swift (2 hunks)
  • StreamChatUITestsApp/DebugMenu.swift (1 hunks)
  • StreamChatUITestsApp/InternetConnection/InternetConnectionMonitor_Mock.swift (0 hunks)
  • StreamChatUITestsApp/Settings.swift (0 hunks)
  • StreamChatUITestsApp/StreamChat/ChannelVC.swift (0 hunks)
  • StreamChatUITestsApp/StreamChat/CustomChannelListRouter.swift (1 hunks)
  • StreamChatUITestsApp/StreamChat/CustomChatMessageListRouter.swift (1 hunks)
  • StreamChatUITestsApp/StreamChat/DemoAppCoordinator+TestApp.swift (0 hunks)
  • StreamChatUITestsApp/StreamChat/StreamChatWrapper+TestApp.swift (0 hunks)
  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift (2 hunks)
  • StreamChatUITestsApp/StreamChat/ThreadVC.swift (1 hunks)
  • StreamChatUITestsApp/StreamChat/User.swift (0 hunks)
  • StreamChatUITestsApp/ViewController.swift (1 hunks)
  • StreamChatUITestsAppUITests/Pages/ChannelListPage.swift (1 hunks)
  • StreamChatUITestsAppUITests/Pages/MessageListPage.swift (3 hunks)
  • StreamChatUITestsAppUITests/Pages/SpringBoard.swift (1 hunks)
  • StreamChatUITestsAppUITests/Pages/ThreadPage.swift (0 hunks)
  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (23 hunks)
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift (6 hunks)
  • StreamChatUITestsAppUITests/StreamChatUITests.swift (1 hunks)
  • StreamChatUITestsAppUITests/Tests/Attachments_Tests.swift (1 hunks)
  • StreamChatUITestsAppUITests/Tests/Authentication_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/Base TestCase/StreamTestCase.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/ChannelList_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/Ephemeral_Messages_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus+ChannelList_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus_Tests.swift (2 hunks)
  • StreamChatUITestsAppUITests/Tests/MessageList_Tests.swift (1 hunks)
  • StreamChatUITestsAppUITests/Tests/Performance/ChannelListScrollTime.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/Performance/MessageListScrollTime.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/PushNotification_Tests.swift (5 hunks)
  • StreamChatUITestsAppUITests/Tests/QuotedReply_Tests.swift (1 hunks)
  • StreamChatUITestsAppUITests/Tests/Reactions_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/SlowMode_Tests.swift (0 hunks)
  • StreamChatUITestsAppUITests/Tests/StreamTestCase+Tags.swift (1 hunks)
  • StreamChatUITestsAppUITests/Tests/UserDetails_Tests.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/Extensions/Dictionary.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Extensions/String.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Extensions/Swifter.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/AttachmentResponses.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/ChannelConfig.swift (3 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/ChannelResponses.swift (5 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/DeviceRemoteControl.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/EventResponses.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/MembersResponse.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/MessageList.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/MessageResponses.swift (4 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/MockServerAttributes.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/ReactionResponses.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/User.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/MockServer/WebsocketResponses.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Robots/BackendRobot.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (4 hunks)
  • TestTools/StreamChatTestMockServer/StreamChatTestMockServer.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/DemoServer.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Errno.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Files.swift (5 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpParser.swift (4 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpRequest.swift (7 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpResponse.swift (5 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpRouter.swift (2 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpServer.swift (2 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/HttpServerIO.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/MimeTypes.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Process.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Scopes.swift (3 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Socket+File.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Socket+Server.swift (3 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/Socket.swift (7 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/String+BASE64.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/String+File.swift (2 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/String+Misc.swift (1 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/String+SHA1.swift (6 hunks)
  • TestTools/StreamChatTestMockServer/Swifter/WebSockets.swift (10 hunks)
  • TestTools/StreamChatTestMockServer/Utilities/LaunchArgument.swift (0 hunks)
  • TestTools/StreamChatTestMockServer/Utilities/TestData.swift (1 hunks)
  • TestTools/StreamChatTestTools/Assertions/AssertAsync.swift (0 hunks)
  • TestTools/StreamChatTestTools/Difference/Difference.swift (9 hunks)
  • TestTools/StreamChatTestTools/Extensions/FileManager+Extensions.swift (1 hunks)
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelId+Unique.swift (1 hunks)
  • TestTools/StreamChatTestTools/Extensions/Unique/ChatUser+Unique.swift (1 hunks)
  • TestTools/StreamChatTestTools/Extensions/Unique/Poll+Unique.swift (1 hunks)
  • TestTools/StreamChatTestTools/Extensions/XCTest+Helpers.swift (10 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/AttachmentUploadingState_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageAudioAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageFileAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageImageAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageLinkAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageVideoAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageVoiceRecordingAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/StreamAttachment_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatMessage_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/MessageReminder_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Poll_Mock.swift (2 hunks)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/ConnectionRepository_Mock.swift (2 hunks)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChannelListController_Mock.swift (1 hunks)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatChannelController_Mock.swift (2 hunks)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatMessageController_Mock.swift (0 hunks)
⛔ Files not processed due to max files limit (34)
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatUserSearchController_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/PollController_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/AuthenticationRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/ChannelRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/DraftMessagesRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/OfflineRequestsRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/PollsRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/RemindersRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Repositories/SyncRepository_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/State/ChannelList_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/State/Chat_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/State/MessageSearch_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/State/UserSearch_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Utils/MessagesPaginationStateHandler_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAVPlayer.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAVURLAsset.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAudioPlayer.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAudioRecorder.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAudioRecordingDelegate.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/VoiceRecording/MockAudioSessionConfigurator.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/WebSocketClient/WebSocketClient_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/WebSocketClient/WebSocketEngine_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/ManualEventHandler_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Workers/UserUpdater_Mock.swift
  • TestTools/StreamChatTestTools/SpyPattern/Spy/APIClient_Spy.swift
  • TestTools/StreamChatTestTools/SpyPattern/Spy/AttachmentUploader_Spy.swift
  • TestTools/StreamChatTestTools/SpyPattern/Spy/CDNClient_Spy.swift
  • TestTools/StreamChatTestTools/SpyPattern/Spy/DatabaseContainer_Spy.swift
  • TestTools/StreamChatTestTools/StreamChatTestTools.swift
  • TestTools/StreamChatTestTools/TestData/AnyEndpoint.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/MessageAttachmentPayload.swift
  • TestTools/StreamChatTestTools/TestData/DummyData/UploadedAttachment.swift
  • fastlane/Fastfile
  • lefthook.yml
💤 Files with no reviewable changes (28)
  • StreamChatUITestsApp/StreamChat/User.swift
  • StreamChatUITestsAppUITests/Tests/Ephemeral_Messages_Tests.swift
  • TestTools/StreamChatTestMockServer/MockServer/DeviceRemoteControl.swift
  • StreamChatUITestsApp/StreamChat/StreamChatWrapper+TestApp.swift
  • StreamChatUITestsApp/StreamChat/DemoAppCoordinator+TestApp.swift
  • StreamChatUITestsAppUITests/Tests/Performance/ChannelListScrollTime.swift
  • TestTools/StreamChatTestMockServer/MockServer/User.swift
  • TestTools/StreamChatTestMockServer/Utilities/LaunchArgument.swift
  • StreamChatUITestsApp/Settings.swift
  • TestTools/StreamChatTestMockServer/StreamChatTestMockServer.swift
  • StreamChatUITestsAppUITests/Tests/Authentication_Tests.swift
  • StreamChatUITestsApp/InternetConnection/InternetConnectionMonitor_Mock.swift
  • StreamChatUITestsAppUITests/Tests/UserDetails_Tests.swift
  • StreamChatUITestsApp/StreamChat/ChannelVC.swift
  • StreamChatUITestsAppUITests/Tests/Base TestCase/StreamTestCase.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatMessageController_Mock.swift
  • StreamChatUITestsAppUITests/Tests/SlowMode_Tests.swift
  • TestTools/StreamChatTestMockServer/MockServer/EventResponses.swift
  • StreamChatUITestsAppUITests/Tests/ChannelList_Tests.swift
  • StreamChatUITestsAppUITests/Tests/Reactions_Tests.swift
  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus+ChannelList_Tests.swift
  • StreamChatUITestsAppUITests/Pages/ThreadPage.swift
  • TestTools/StreamChatTestTools/Assertions/AssertAsync.swift
  • TestTools/StreamChatTestMockServer/MockServer/MembersResponse.swift
  • TestTools/StreamChatTestMockServer/MockServer/ReactionResponses.swift
  • Examples/iMessageClone/iMessageComposerVC.swift
  • Examples/YouTubeClone/Composer/YTChatComposerViewController.swift
  • StreamChatUITestsAppUITests/Tests/Performance/MessageListScrollTime.swift
✅ Files skipped from review due to trivial changes (45)
  • TestTools/StreamChatTestMockServer/Swifter/Socket+Server.swift
  • StreamChatUITestsAppUITests/Tests/MessageList_Tests.swift
  • TestTools/StreamChatTestMockServer/Swifter/DemoServer.swift
  • StreamChatUITestsAppUITests/Tests/StreamTestCase+Tags.swift
  • TestTools/StreamChatTestMockServer/Robots/BackendRobot.swift
  • StreamChatUITestsApp/AppDelegate.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/MessageReminder_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageVoiceRecordingAttachment_Mock.swift
  • TestTools/StreamChatTestTools/Extensions/Unique/ChannelId+Unique.swift
  • TestTools/StreamChatTestMockServer/Swifter/String+Misc.swift
  • DemoShare/ShareViewController.swift
  • TestTools/StreamChatTestMockServer/MockServer/WebsocketResponses.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/AttachmentUploadingState_Mock.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpResponse.swift
  • TestTools/StreamChatTestMockServer/Swifter/MimeTypes.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/StreamAttachment_Mock.swift
  • TestTools/StreamChatTestMockServer/Swifter/Scopes.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpServerIO.swift
  • StreamChatUITestsAppUITests/Tests/PushNotification_Tests.swift
  • TestTools/StreamChatTestMockServer/Swifter/Errno.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageLinkAttachment_Mock.swift
  • TestTools/StreamChatTestMockServer/Swifter/String+File.swift
  • TestTools/StreamChatTestMockServer/Swifter/String+BASE64.swift
  • TestTools/StreamChatTestMockServer/MockServer/MessageList.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageImageAttachment_Mock.swift
  • StreamChatUITestsAppUITests/Tests/QuotedReply_Tests.swift
  • TestTools/StreamChatTestMockServer/MockServer/MessageResponses.swift
  • TestTools/StreamChatTestMockServer/Swifter/Files.swift
  • TestTools/StreamChatTestMockServer/MockServer/ChannelResponses.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageAudioAttachment_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/ChatMessage_Mock.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageVideoAttachment_Mock.swift
  • Package.swift
  • StreamChatUITestsAppUITests/Pages/ChannelListPage.swift
  • TestTools/StreamChatTestMockServer/Extensions/String.swift
  • StreamChatUITestsAppUITests/Tests/Attachments_Tests.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Poll_Mock.swift
  • StreamChatUITestsAppUITests/Pages/SpringBoard.swift
  • StreamChatUITestsApp/StreamChat/CustomChannelListRouter.swift
  • TestTools/StreamChatTestTools/Mocks/Models + Extensions/Attachments/ChatMessageFileAttachment_Mock.swift
  • Stream.playground/Contents.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/ConnectionRepository_Mock.swift
  • DemoShare/DemoShareViewModel.swift
  • TestTools/StreamChatTestMockServer/MockServer/MockServerAttributes.swift
  • StreamChatUITestsApp/ViewController.swift
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift

📄 CodeRabbit inference engine (AGENTS.md)

**/*.swift: Respect .swiftlint.yml rules; do not suppress SwiftLint rules broadly—scope and justify any exceptions
Adhere to the project’s zero warnings policy—fix new warnings and avoid introducing any

Files:

  • TestTools/StreamChatTestMockServer/Extensions/Dictionary.swift
  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus_Tests.swift
  • DemoShare/DemoShareView.swift
  • TestTools/StreamChatTestTools/Extensions/FileManager+Extensions.swift
  • Examples/EdgeCases/ViewController.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpServer.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpParser.swift
  • StreamChatUITestsApp/StreamChat/CustomChatMessageListRouter.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChannelListController_Mock.swift
  • StreamChatUITestsApp/DebugMenu.swift
  • TestTools/StreamChatTestMockServer/Swifter/Process.swift
  • TestTools/StreamChatTestMockServer/Extensions/Swifter.swift
  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift
  • TestTools/StreamChatTestTools/Extensions/Unique/Poll+Unique.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpRequest.swift
  • TestTools/StreamChatTestMockServer/Swifter/HttpRouter.swift
  • TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift
  • TestTools/StreamChatTestTools/Difference/Difference.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • TestTools/StreamChatTestMockServer/Swifter/Socket.swift
  • TestTools/StreamChatTestTools/Extensions/Unique/ChatUser+Unique.swift
  • TestTools/StreamChatTestMockServer/Swifter/Socket+File.swift
  • TestTools/StreamChatTestMockServer/Utilities/TestData.swift
  • StreamChatUITestsAppUITests/Pages/MessageListPage.swift
  • StreamChatUITestsAppUITests/StreamChatUITests.swift
  • TestTools/StreamChatTestMockServer/MockServer/ChannelConfig.swift
  • TestTools/StreamChatTestMockServer/Swifter/WebSockets.swift
  • TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
  • StreamChatUITestsApp/StreamChat/ThreadVC.swift
  • TestTools/StreamChatTestMockServer/Swifter/String+SHA1.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatChannelController_Mock.swift
  • TestTools/StreamChatTestTools/Extensions/XCTest+Helpers.swift
  • TestTools/StreamChatTestMockServer/MockServer/AttachmentResponses.swift
🧠 Learnings (5)
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatTests/**/*.swift : Ensure tests cover core models and API surface of StreamChat

Applied to files:

  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus_Tests.swift
  • TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChannelListController_Mock.swift
  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift
  • TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • StreamChatUITestsAppUITests/StreamChatUITests.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatUITests/**/*.swift : Ensure tests cover view controllers and UI behaviors of StreamChatUI

Applied to files:

  • StreamChatUITestsAppUITests/Tests/Message Delivery Status/MessageDeliveryStatus_Tests.swift
  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • StreamChatUITestsAppUITests/StreamChatUITests.swift
  • StreamChatUITestsApp/StreamChat/ThreadVC.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Sources/{StreamChat,StreamChatUI}/**/*.swift : When altering public API, update inline documentation comments in source

Applied to files:

  • TestTools/StreamChatTestMockServer/Extensions/Swifter.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/{StreamChatTests,StreamChatUITests}/**/*.swift : Add or extend tests in the matching module’s Tests folder

Applied to files:

  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift
  • StreamChatUITestsAppUITests/StreamChatUITests.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/{StreamChatTests,StreamChatUITests}/**/*.swift : Prefer using provided test fakes/mocks in tests when possible

Applied to files:

  • StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift
  • TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift
  • StreamChatUITestsAppUITests/StreamChatUITests.swift
🧬 Code graph analysis (12)
TestTools/StreamChatTestMockServer/Swifter/HttpServer.swift (1)
TestTools/StreamChatTestMockServer/Swifter/Scopes.swift (1)
  • head (218-218)
StreamChatUITestsApp/DebugMenu.swift (2)
Sources/StreamChatUI/CommonViews/AvatarView/ChatChannelAvatarView.swift (1)
  • lastActiveMembers (258-263)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (1)
  • truncateChannel (519-528)
TestTools/StreamChatTestMockServer/Extensions/Swifter.swift (1)
TestTools/StreamChatTestMockServer/Swifter/HttpRouter.swift (1)
  • register (45-54)
StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (3)
StreamChatUITestsAppUITests/Pages/MessageListPage.swift (3)
  • text (183-185)
  • text (191-193)
  • threadReplyCountButton (171-173)
TestTools/StreamChatTestMockServer/MockServer/DeviceRemoteControl.swift (1)
  • pushNotification (8-43)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (1)
  • typeText (79-87)
TestTools/StreamChatTestMockServer/Swifter/Socket.swift (1)
TestTools/StreamChatTestMockServer/Swifter/HttpServerIO.swift (5)
  • write (143-145)
  • write (147-149)
  • write (151-153)
  • write (155-157)
  • write (159-161)
TestTools/StreamChatTestMockServer/Swifter/Socket+File.swift (2)
TestTools/StreamChatTestMockServer/Swifter/HttpServerIO.swift (5)
  • write (143-145)
  • write (147-149)
  • write (151-153)
  • write (155-157)
  • write (159-161)
TestTools/StreamChatTestMockServer/Swifter/String+File.swift (1)
  • write (44-53)
TestTools/StreamChatTestMockServer/MockServer/ChannelConfig.swift (1)
TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift (3)
  • updateConfig (112-114)
  • updateConfig (116-118)
  • config (108-110)
TestTools/StreamChatTestMockServer/Swifter/WebSockets.swift (1)
TestTools/StreamChatTestMockServer/Swifter/Socket.swift (5)
  • close (38-44)
  • close (221-227)
  • read (127-140)
  • read (147-151)
  • read (161-183)
TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (2)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (1)
  • sendMessage (89-112)
TestTools/StreamChatTestTools/TestData/DummyData/MessageAttachmentPayload.swift (1)
  • file (72-86)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (2)
TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (1)
  • sendMessage (98-146)
StreamChatUITestsAppUITests/Pages/MessageListPage.swift (2)
  • text (183-185)
  • text (191-193)
TestTools/StreamChatTestTools/Extensions/XCTest+Helpers.swift (1)
TestTools/StreamChatTestTools/Difference/Difference.swift (2)
  • diff (56-59)
  • diff (380-389)
TestTools/StreamChatTestMockServer/MockServer/AttachmentResponses.swift (1)
TestTools/StreamChatTestMockServer/Extensions/Swifter.swift (1)
  • register (8-18)
🔇 Additional comments (40)
TestTools/StreamChatTestTools/Extensions/Unique/ChatUser+Unique.swift (1)

9-9: Modifier order matches Swift conventions.

Switching to public static aligns with standard Swift access modifier ordering without changing behavior. Nicely done.

TestTools/StreamChatTestTools/Extensions/FileManager+Extensions.swift (1)

16-16: LGTM! Idiomatic Swift improvement.

Using isEmpty instead of comparing count > 0 follows Swift best practices and is more efficient.

TestTools/StreamChatTestMockServer/Swifter/Process.swift (2)

2-2: LGTM: Copyright header updated.

The copyright year has been updated to 2025, which is appropriate for current maintenance.


14-18: LGTM: Formatting cleanup aligns with PR objectives.

The whitespace and indentation adjustments improve consistency without altering functionality. This aligns with the PR's goal of formatting cleanup after removing the trailing_whitespace SwiftLint rule.

TestTools/StreamChatTestMockServer/Extensions/Dictionary.swift (1)

7-25: LGTM! Formatting changes align with PR objectives.

The changes are purely formatting-related (whitespace/indentation adjustments) with no impact on the function's logic or behavior. This is consistent with the PR's goal of addressing trailing whitespace issues in SwiftLint rules.

TestTools/StreamChatTestMockServer/MockServer/AttachmentResponses.swift (1)

10-15: LGTM! Clean style improvement.

Using _ to explicitly ignore the unused HttpRequest parameter is the correct Swift idiom and aligns with SwiftLint best practices for unused closure parameters.

StreamChatUITestsApp/StreamChat/StreamChatWrapperExtensions.swift (2)

7-8: LGTM: Import reordering aligns with formatter rules.

The import order change is consistent with the PR's objective to unify SwiftLint/SwiftFormat rules. No functional impact.


26-30: LGTM: Multiline formatting improves readability.

The NSError initialization reformatting maintains all original values while improving code readability. This change is consistent with the formatter standardization objective.

TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChannelListController_Mock.swift (1)

30-30: LGTM!

Trailing whitespace removed. No functional impact.

TestTools/StreamChatTestTools/Mocks/StreamChat/Controllers/ChatChannelController_Mock.swift (1)

69-69: LGTM!

Dictionary type formatting corrected to remove space before colon. Aligns with Swift style conventions.

Also applies to: 148-148

Examples/EdgeCases/ViewController.swift (1)

7-7: Verify that removing viewDidLoad is intentional.

This PR aims to address SwiftLint's trailing_whitespace rule issues, yet this change removes the entire viewDidLoad() lifecycle method. If the previous implementation contained setup logic for the EdgeCases example, removing it could break the example's functionality.

Please confirm:

  1. The removed viewDidLoad() contained only boilerplate (e.g., just super.viewDidLoad())
  2. This example still functions as intended without the lifecycle override

</review_comment_end>

TestTools/StreamChatTestMockServer/Utilities/TestData.swift (1)

24-24: LGTM: Formatting change aligned with PR objectives.

The change from 10_000 to 10000 is a minor formatting adjustment with no functional impact. Both represent ten thousand milliseconds (10 seconds). While underscores can improve readability for large numbers, this change is consistent with the broader formatting cleanup described in the PR objectives.

TestTools/StreamChatTestMockServer/MockServer/StreamMockServer.swift (1)

5-7: LGTM! Import ordering aligns with SwiftLint rules.

The import reordering (Foundation → StreamChat → XCTest) is consistent with the PR's goal of unifying SwiftLint rules across the codebase.

TestTools/StreamChatTestMockServer/MockServer/ChannelConfig.swift (1)

39-43: LGTM! Multi-line function signatures improve readability.

The reformatting of function signatures to multi-line format enhances readability and aligns with the updated SwiftLint/SwiftFormat rules.

Also applies to: 61-64, 72-75

StreamChatUITestsAppUITests/StreamChatUITests.swift (1)

5-7: LGTM! Clean test helper imports.

The import reorganization looks good:

  • Consolidating Foundation import at the top eliminates duplication
  • Using @_exported to re-export test utilities (StreamChatTestMockServer and StreamSwiftTestHelpers) is idiomatic for Swift test targets and makes these helpers available throughout the test suite
  • Import order follows conventions (system frameworks first, then project test utilities)

This aligns with the PR's goal of unifying linting rules and the retrieved learnings about using provided test helpers.

TestTools/StreamChatTestTools/Difference/Difference.swift (3)

65-65: LGTM! Idiomatic Swift improvement.

Using isEmpty instead of count-based checks is the preferred Swift idiom for checking collection emptiness. This improves readability while maintaining the same logic.


182-187: LGTM! Clear conditional logic.

The use of isEmpty in these conditional checks makes the intent clear and follows Swift best practices for collection emptiness checks.


321-321: LGTM! Appropriate access control.

Changing these file-scoped extensions from fileprivate to private is appropriate since they serve as internal helpers used only within this file.

Also applies to: 344-344

StreamChatUITestsAppUITests/Pages/MessageListPage.swift (3)

8-8: LGTM! Import order adjusted.

The XCTest import has been moved to follow the StreamChatUI import, which appears to be part of the formatting cleanup related to SwiftLint rule adjustments.


58-59: LGTM! Trailing whitespace cleaned up.

Whitespace adjustments in the Alert.Debug section align with the PR's objective to address trailing whitespace issues.


149-149: Approve enum Element refactor. No Element() instantiations or direct ContextMenu.Element references found in any Swift file; the change is safe.

TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (6)

68-68: LGTM! Improved numeric literal readability.

Using underscores in numeric literals enhances readability without changing the value.


99-108: LGTM! Multiline signature formatting improves readability.

The method signature is reformatted to multiline without changing parameters, types, or defaults.


383-395: LGTM! Multiline signature formatting with new thread parameters.

The signature is reformatted to multiline and includes new inThread and alsoInChannel parameters for thread support.


404-413: LGTM! Thread typing indicators follow established pattern.

The conditional logic correctly calls thread-specific typing methods and computes parentId when inThread is true, matching the pattern in replyToMessageInThread.


439-439: LGTM! Improved numeric literal readability.

Consistent with the change on Line 68, using underscores enhances readability.


459-462: LGTM! Thread message keys set correctly.

The parentId and showReplyInChannel assignments follow the established pattern in replyToMessageInThread and related methods.

TestTools/StreamChatTestMockServer/Swifter/WebSockets.swift (5)

42-42: LGTM: Idiomatic empty check.

The change from payload.count > 0 to !payload.isEmpty is semantically equivalent and follows Swift best practices. The logic correctly checks for non-empty payloads in fragmented frame handling.

Also applies to: 62-62


150-150: LGTM: Lowercase hex literals.

The OpCode enum raw values are now consistently lowercase hex (0x0a instead of 0x0A), which aligns with common Swift conventions.


208-220: LGTM: Consistent hex formatting in length encoding.

The lowercase hex literals (0x7e, 0x7f, 0xff) are now consistent throughout the length encoding logic. The byte-shift operations remain correct.


261-262: LGTM: Length decoding hex literals normalized.

The lowercase hex literals (0x7e, 0x7f) in the length decoding logic are now consistent with the encoding logic. The conditional checks remain correct for WebSocket frame length encoding as per RFC 6455.

Also applies to: 266-266


120-135: Error handling covers all WebSocketSession error cases.
Switch explicitly handles Control.close and all four WsError cases; default covers any other errors.

TestTools/StreamChatTestMockServer/Swifter/HttpRouter.swift (1)

122-122: LGTM: Idiomatic empty check for route parameters.

The change from tail.count > 0 to !tail.isEmpty is semantically equivalent and follows Swift best practices. This correctly checks whether there are additional path segments to append to the variable route parameter value.

TestTools/StreamChatTestMockServer/Swifter/HttpParser.swift (2)

31-33: Excellent security improvement: Prevent buffer overflow.

The guard for negative Content-Length values prevents a potential buffer overflow and runtime error when creating an UnsafeMutableBufferPointer. This is a critical safety check that aligns with defensive programming practices.


56-56: Minor: Comparison reordered but semantically equivalent.

The change from "keep-alive" == value.trimmingCharacters(...) to value.trimmingCharacters(...) == "keep-alive" is semantically equivalent. The current form (variable == literal) is more conventional in Swift.

TestTools/StreamChatTestMockServer/Swifter/HttpServer.swift (1)

20-20: LGTM: Init signature follows common convention.

The change from public override init() to override public init() follows the more common Swift convention of placing access modifiers before override keywords.

TestTools/StreamChatTestMockServer/Swifter/HttpRequest.swift (4)

22-22: LGTM: Idiomatic empty check for token filtering.

The change from .filter(...).count > 0 to !.filter(...).isEmpty is semantically equivalent and follows Swift best practices. This correctly checks whether any matching tokens exist in the header value.


93-93: LGTM: Idiomatic empty check for boundary.

The change from boundary.utf8.count > 0 to !boundary.utf8.isEmpty is semantically equivalent and follows Swift best practices for checking non-empty UTF-8 sequences.


114-114: LGTM: Blank identifier for intentionally ignored value.

The change from a placeholder comment to /* ignore */ _ = nextUTF8MultiPartLine(&generator) uses Swift's blank identifier _ convention to explicitly indicate the return value is intentionally ignored in the non-first multipart case.


151-151: LGTM: Formatting consistency.

The ternary operator and range expressions have been reformatted for consistency, with no behavioral changes. The multipart body parsing logic remains correct.

Also applies to: 155-155, 157-157

Comment on lines +81 to +83
title: "Truncate channel w/o message",
style: .default,
handler: { _ in
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Spell out “without” to keep UI tests/readability stable.

Abbreviation “w/o” may not match test locators and is less clear.

-                    title: "Truncate channel w/o message",
+                    title: "Truncate channel without message",

Run to verify test expectations vs labels:


🏁 Script executed:

#!/bin/bash
set -euo pipefail
rg -n -C2 -P 'Truncate channel (w/o|without) message|truncateWithoutMessage|truncateWithMessage|debugAlert\.truncateWithoutMessage|debugAlert\.truncateWithMessage'

Length of output: 2177


Sync “without” spelling across UI and tests
Update all literal titles and locators:

  • StreamChatUITestsApp/DebugMenu.swift line 81:
    title: "Truncate channel w/o message""Truncate channel without message"
  • StreamChatUITestsAppUITests/Pages/MessageListPage.swift line 73:
    alert.buttons["Truncate channel w/o message"]alert.buttons["Truncate channel without message"]
  • DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift line 577:
    .init(title: "Truncate channel w/o message", …).init(title: "Truncate channel without message", …)
🤖 Prompt for AI Agents
In StreamChatUITestsApp/DebugMenu.swift around lines 81–83,
StreamChatUITestsAppUITests/Pages/MessageListPage.swift around line 73, and
DemoApp/StreamChat/Components/DemoChatChannelListRouter.swift around line 577,
the literal title/locator uses "Truncate channel w/o message"; update each
occurrence to use the full word "without" so change "Truncate channel w/o
message" → "Truncate channel without message" in DebugMenu.swift and
DemoChatChannelListRouter.swift, and update the UI test locator
alert.buttons["Truncate channel w/o message"] to alert.buttons["Truncate channel
without message"] in MessageListPage.swift to keep spelling consistent across UI
and tests.

Comment on lines +28 to +37
let minExpectedCount = index + 1
let cells = cells.waitCount(index)
XCTAssertGreaterThanOrEqual(
cells.count,
minExpectedCount,
"Message cell is not found at index #\(index)",
file: file,
line: line
)
return channelCells.element(boundBy: index)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix channel cell lookup to use ChannelList cells.

cells.waitCount(index) is invoking the message-list query (MessageListPage.cells), so the guard never waits on the channel list and the subsequent XCTAssertGreaterThanOrEqual compares the wrong collection. This now fails whenever the channel list is longer than the message list (e.g., opening the app before loading any messages). Switch the wait/count logic to ChannelListPage.cells and use minExpectedCount for the wait.

Apply this diff:

         let minExpectedCount = index + 1
-        let cells = cells.waitCount(index)
+        let channelCellsQuery = channelCells.waitCount(minExpectedCount)
         XCTAssertGreaterThanOrEqual(
-            cells.count,
+            channelCellsQuery.count,
             minExpectedCount,
             "Message cell is not found at index #\(index)",
             file: file,
             line: line
         )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let minExpectedCount = index + 1
let cells = cells.waitCount(index)
XCTAssertGreaterThanOrEqual(
cells.count,
minExpectedCount,
"Message cell is not found at index #\(index)",
file: file,
line: line
)
return channelCells.element(boundBy: index)
let minExpectedCount = index + 1
let channelCellsQuery = channelCells.waitCount(minExpectedCount)
XCTAssertGreaterThanOrEqual(
channelCellsQuery.count,
minExpectedCount,
"Message cell is not found at index #\(index)",
file: file,
line: line
)
return channelCells.element(boundBy: index)
🤖 Prompt for AI Agents
In StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift around lines 28 to
37, the code is waiting on the message-list cells but then asserting against the
channel list; change the wait to use ChannelListPage.cells and pass
minExpectedCount to the wait, then perform the XCTAssert on that channel cells
collection. Concretely: call ChannelListPage.cells.waitCount(minExpectedCount)
(or assign channelCells = ChannelListPage.cells.waitCount(minExpectedCount) /
wait helper as appropriate), use channelCells.count in the
XCTAssertGreaterThanOrEqual against minExpectedCount, and finally return
channelCells.element(boundBy: index).

Comment on lines +14 to +17
let readResult = fread(&buffer, 1, buffer.count, source)
guard readResult > 0 else {
return Int32(readResult)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Handling fread errors correctly

When fread fails it also returns 0, so this guard treats the failure as EOF and reports success to the caller. That silently truncates the response and hides the underlying error (e.g. disk I/O fault). Please check ferror(source) (and clear the stream if needed) and return -1 so the caller can surface SocketError.writeFailed.

-        guard readResult > 0 else {
-            return Int32(readResult)
-        }
+        guard readResult > 0 else {
+            if ferror(source) != 0 {
+                clearerr(source)
+                return -1
+            }
+            return 0
+        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let readResult = fread(&buffer, 1, buffer.count, source)
guard readResult > 0 else {
return Int32(readResult)
}
let readResult = fread(&buffer, 1, buffer.count, source)
guard readResult > 0 else {
if ferror(source) != 0 {
clearerr(source)
return -1
}
return 0
}
🤖 Prompt for AI Agents
In TestTools/StreamChatTestMockServer/Swifter/Socket+File.swift around lines 14
to 17, the current guard treats fread returning 0 as EOF and returns 0, which
masks real read errors; change the logic to call ferror(source) when readResult
== 0, and if ferror(source) is non-zero then call clearerr(source) if desired
and return -1 so the caller can surface SocketError.writeFailed; only treat true
EOF (feof(source) && !ferror(source)) as a successful zero-length/EOF condition.

Comment on lines +30 to 33
let padBytesCount = (message.count + 8) % 64

message.append(contentsOf: [UInt8](repeating: 0, count: 64 - padBytesCount))

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Restore correct SHA‑1 padding when length mod 64 == 55.

The new padding math appends 64 zero bytes whenever (message.count + 8) % 64 == 0 (i.e., original input length ≡ 55 mod 64). Spec requires the minimal k with 0 ≤ k < 512; in this case k must be 0. Adding 64 zero bytes shifts the 64‑bit length field into a second block, so the digest diverges from the SHA‑1 standard for those inputs.

Use the minimal-padding formula instead:

-        let padBytesCount = (message.count + 8) % 64
-        message.append(contentsOf: [UInt8](repeating: 0, count: 64 - padBytesCount))
+        let padBytesCount = (56 - (message.count % 64) + 64) % 64
+        message.append(contentsOf: [UInt8](repeating: 0, count: padBytesCount))
🤖 Prompt for AI Agents
In TestTools/StreamChatTestMockServer/Swifter/String+SHA1.swift around lines
30-33, the padding math currently appends 64 zero bytes when (message.count + 8)
% 64 == 0, which is incorrect for inputs with length ≡ 55 (mod 64); replace that
logic with the minimal-padding formula so you compute the number of zero pad
bytes as padBytesCount = (56 - (message.count % 64) + 64) % 64 and append
exactly that many zeros (after the required 0x80 byte has been added), ensuring
the 64-bit length field fits in the same block instead of forcing an extra
block.

Copy link

github-actions bot commented Oct 7, 2025

Public Interface

🚀 No changes affecting the public interface.

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)
StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (1)

28-37: Fix channel cell lookup to use ChannelList cells.

This critical bug was flagged in a previous review but remains unfixed. cells.waitCount(index) queries the message list (MessageListPage.cells) instead of the channel list, causing the assertion to compare the wrong collection. Switch to ChannelListPage.cells.

Apply this diff:

         let minExpectedCount = index + 1
-        let cells = cells.waitCount(index)
+        let channelCellsQuery = channelCells.waitCount(minExpectedCount)
         XCTAssertGreaterThanOrEqual(
-            cells.count,
+            channelCellsQuery.count,
             minExpectedCount,
             "Message cell is not found at index #\(index)",
             file: file,
             line: line
         )
🧹 Nitpick comments (1)
StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (1)

774-794: Clarify the new assertQuotedMessage overload to avoid ambiguity.

The new overload with replyText and quotedText parameters creates potential ambiguity with the existing assertQuotedMessage(_ text: String, ...) at lines 355-366. When calling assertQuotedMessage("someText", ...), the compiler may struggle to resolve which overload to use.

Consider one of these approaches:

  1. Rename the new overload to assertQuotedMessageWithReply to make the intent explicit.
  2. Deprecate the old overload and migrate all call sites to use the new signature.
  3. Add explicit external parameter labels to eliminate ambiguity (e.g., assertQuotedMessage(reply: String, quote: String, ...)).
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c2e9899 and f60dcb9.

📒 Files selected for processing (3)
  • .swiftformat (2 hunks)
  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (22 hunks)
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .swiftformat
🧰 Additional context used
📓 Path-based instructions (1)
**/*.swift

📄 CodeRabbit inference engine (AGENTS.md)

**/*.swift: Respect .swiftlint.yml rules; do not suppress SwiftLint rules broadly—scope and justify any exceptions
Adhere to the project’s zero warnings policy—fix new warnings and avoid introducing any

Files:

  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
🧠 Learnings (3)
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatUITests/**/*.swift : Ensure tests cover view controllers and UI behaviors of StreamChatUI

Applied to files:

  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/StreamChatTests/**/*.swift : Ensure tests cover core models and API surface of StreamChat

Applied to files:

  • StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift
  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
📚 Learning: 2025-09-18T10:00:24.878Z
Learnt from: CR
PR: GetStream/stream-chat-swift#0
File: AGENTS.md:0-0
Timestamp: 2025-09-18T10:00:24.878Z
Learning: Applies to Tests/{StreamChatTests,StreamChatUITests}/**/*.swift : Prefer using provided test fakes/mocks in tests when possible

Applied to files:

  • StreamChatUITestsAppUITests/Robots/UserRobot.swift
🧬 Code graph analysis (2)
StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (2)
StreamChatUITestsAppUITests/Pages/MessageListPage.swift (3)
  • text (183-185)
  • text (191-193)
  • threadReplyCountButton (171-173)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (1)
  • typeText (79-87)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (2)
TestTools/StreamChatTestMockServer/Robots/ParticipantRobot.swift (2)
  • sendMessage (98-146)
  • quoteMessage (233-252)
StreamChatUITestsAppUITests/Pages/MessageListPage.swift (2)
  • text (183-185)
  • text (191-193)
⏰ 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). (1)
  • GitHub Check: Build LLC + UI (Xcode 15)
🔇 Additional comments (2)
StreamChatUITestsAppUITests/Robots/UserRobot.swift (1)

7-7: LGTM! Formatting changes align with SwiftLint rule updates.

Import reordering, numeric literal formatting (1_000_000), and multi-line function signatures are cosmetic improvements with no functional impact.

Also applies to: 64-64, 90-96, 207-220, 295-301

StreamChatUITestsAppUITests/Robots/UserRobot+Asserts.swift (1)

7-8: LGTM! Formatting changes align with SwiftLint rule updates.

Import reordering, multi-line XCTAssert statements, function signature reformatting, and whitespace adjustments are cosmetic improvements with no functional impact.

Also applies to: 17-26, 50-55, 122-127, 135-140, 170-193, 238-257, 263-268, 280-286, 367-367, 434-440, 470-481, 497-506, 566-582, 601-621, 653-659, 772-772, 814-824, 872-902, 929-934, 994-1002, 1049-1066, 1071-1089

Copy link

sonarqubecloud bot commented Oct 8, 2025

@laevandus laevandus changed the title Remove trailing_whitespace from SwiftLint rules due to multi-line string issues Adjust linter rules and linted paths Oct 8, 2025
@laevandus laevandus enabled auto-merge (squash) October 8, 2025 08:59
@laevandus laevandus merged commit 3c26067 into develop Oct 8, 2025
23 of 24 checks passed
@laevandus laevandus deleted the ci/remove-trailing-whitespace branch October 8, 2025 10:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🤖 CI/CD Any work related to CI/CD
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants