Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This pull request adds comprehensive integration tests to achieve feature parity with the stream-chat-ruby SDK. The PR introduces eight new test specification files covering video, chat users, reactions, polls, moderation, miscellaneous features, messages, and channels, along with a shared test helpers module.
Changes:
- Added
chat_test_helpers.rbmodule providing shared utilities for test setup, user/channel creation, and resource cleanup - Added comprehensive integration tests for video operations (call types, calls, external storage, recording/transcription)
- Added integration tests for chat functionality covering users, channels, messages, reactions, polls, and moderation features
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 16 comments.
Show a summary per file
| File | Description |
|---|---|
| spec/integration/chat_test_helpers.rb | Shared helper module for integration tests with setup/teardown and common operations |
| spec/integration/video_integration_spec.rb | Tests for video call types, calls, permissions, blocking, muting, external storage, and deletion |
| spec/integration/chat_user_integration_spec.rb | Tests for user CRUD, blocking, deactivation, privacy settings, teams, and custom data |
| spec/integration/chat_reaction_integration_spec.rb | Tests for sending, retrieving, deleting, and enforcing unique reactions |
| spec/integration/chat_polls_integration_spec.rb | Tests for poll creation, querying, voting, and verification |
| spec/integration/chat_moderation_integration_spec.rb | Tests for banning, muting, and flagging users and messages |
| spec/integration/chat_misc_integration_spec.rb | Tests for devices, blocklists, commands, channel types, permissions, roles, threads, reminders, and exports |
| spec/integration/chat_message_integration_spec.rb | Tests for message CRUD, pinning, translation, threads, search, pending messages, and history |
| spec/integration/chat_channel_integration_spec.rb | Tests for channel CRUD, members, roles, hiding/showing, truncation, freezing, muting, file uploads |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @client.common.create_block_list( | ||
| GetStream::Generated::Models::CreateBlockListRequest.new( | ||
| name: del_name, | ||
| words: %w[word1] | ||
| ) | ||
| ) | ||
| @client.common.delete_block_list(del_name) |
There was a problem hiding this comment.
The test creates a separate resource (del_name) just to test deletion, which is good for isolation. However, this resource is never added to @created_blocklist_names before deletion, so if the deletion fails, it won't be cleaned up in the after(:all) block. Consider adding it to the tracking array before attempting deletion, or wrapping in a begin-ensure block.
| @client.common.create_block_list( | |
| GetStream::Generated::Models::CreateBlockListRequest.new( | |
| name: del_name, | |
| words: %w[word1] | |
| ) | |
| ) | |
| @client.common.delete_block_list(del_name) | |
| created = false | |
| begin | |
| @client.common.create_block_list( | |
| GetStream::Generated::Models::CreateBlockListRequest.new( | |
| name: del_name, | |
| words: %w[word1] | |
| ) | |
| ) | |
| created = true | |
| @client.common.delete_block_list(del_name) | |
| rescue StandardError | |
| @created_blocklist_names << del_name if created | |
| raise | |
| end |
| @created_call_ids&.each do |call_type, call_id| | ||
| @client.make_request( | ||
| :post, | ||
| "/api/v2/video/call/#{call_type}/#{call_id}/delete", | ||
| body: {} | ||
| ) | ||
| rescue StandardError => e | ||
| puts "Warning: Failed to delete call #{call_type}:#{call_id}: #{e.message}" | ||
| end | ||
|
|
There was a problem hiding this comment.
The cleanup logic in the after(:all) block uses @created_call_ids&.each with a rescue block that only prints a warning but doesn't track failures. If the API call to delete a call fails consistently (e.g., due to permissions or a missing call), this could lead to orphaned resources and test pollution. Consider logging failures to a list and raising an error after all cleanup attempts, or implementing exponential backoff retry logic similar to other cleanup operations in the codebase.
| @created_call_ids&.each do |call_type, call_id| | |
| @client.make_request( | |
| :post, | |
| "/api/v2/video/call/#{call_type}/#{call_id}/delete", | |
| body: {} | |
| ) | |
| rescue StandardError => e | |
| puts "Warning: Failed to delete call #{call_type}:#{call_id}: #{e.message}" | |
| end | |
| failed_call_deletions = [] | |
| @created_call_ids&.each do |call_type, call_id| | |
| attempts = 0 | |
| begin | |
| attempts += 1 | |
| @client.make_request( | |
| :post, | |
| "/api/v2/video/call/#{call_type}/#{call_id}/delete", | |
| body: {} | |
| ) | |
| rescue StandardError => e | |
| if attempts < 3 | |
| sleep(2**(attempts - 1)) | |
| retry | |
| else | |
| puts "Warning: Failed to delete call #{call_type}:#{call_id} after #{attempts} attempts: #{e.message}" | |
| failed_call_deletions << [call_type, call_id, e] | |
| end | |
| end | |
| end | |
| unless failed_call_deletions.empty? | |
| failed_descriptions = failed_call_deletions.map { |type, id, error| "#{type}:#{id} (#{error.class}: #{error.message})" } | |
| raise "Failed to delete calls during cleanup: #{failed_descriptions.join(', ')}" | |
| end |
| break | ||
| rescue GetStreamRuby::APIError => e | ||
| raise if i == 2 | ||
|
|
||
| sleep(5) | ||
| end |
There was a problem hiding this comment.
The error variable e is captured but never used in the rescue block. Either remove the unused variable by using rescue GetStreamRuby::APIError without capturing it, or use the error for logging/debugging purposes before re-raising on the final attempt.
| resp = query_users_with_filter({ 'id' => uid }) | ||
| user = resp.users.first | ||
| user_h = user.to_h | ||
| # Custom fields may be at top-level or under 'custom' | ||
| country = user_h['custom'].is_a?(Hash) ? user_h['custom']['country'] : user_h['country'] | ||
| expect(country).to eq('NL') | ||
|
|
There was a problem hiding this comment.
The helper method converts responses to hashes and uses dig to extract nested values, but doesn't handle cases where intermediate keys might be missing. While dig returns nil for missing keys (which is safe), the test expectations immediately follow. Consider adding nil checks or more descriptive error messages if the response structure is unexpectedly missing required fields.
| # Verify unblocked (with retry for eventual consistency) | ||
| unblocked = false | ||
| 6.times do |i| | ||
| sleep(2) | ||
| resp2 = get_call('default', call_id) | ||
| call_h2 = resp2.to_h | ||
| blocked_ids2 = call_h2.dig('call', 'blocked_user_ids') || [] | ||
| unless blocked_ids2.include?(@user2) | ||
| unblocked = true | ||
| break | ||
| end | ||
| end | ||
| expect(unblocked).to be(true), 'Expected user to be unblocked after unblock call' |
There was a problem hiding this comment.
The polling loop for verifying the unblock operation retries 6 times with 2-second sleeps (total 12 seconds). This hardcoded polling logic is duplicated in multiple tests. Consider extracting a reusable wait_until helper that accepts a condition lambda and timeout parameters to reduce code duplication and make timeouts more consistent across tests.
Adding test cases to cover feature parity with https://github.com/GetStream/stream-chat-ruby