From 9ad83ddff6664c092d26c543b79535f623fba997 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Fri, 17 Apr 2026 15:40:19 +0200 Subject: [PATCH 1/3] FEEDS-1413: add integration test for create_users on follow Covers the newly-merged auto-generate users flow for both the single follow endpoint and the batch get_or_create_follows upsert. Verifies that referenced source/target users are created server-side and registers them for suite cleanup. Made-with: Cursor --- spec/integration/feed_integration_spec.rb | 72 +++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/spec/integration/feed_integration_spec.rb b/spec/integration/feed_integration_spec.rb index 3831dc6d..b24b512c 100644 --- a/spec/integration/feed_integration_spec.rb +++ b/spec/integration/feed_integration_spec.rb @@ -617,6 +617,78 @@ end + it 'auto-generates users on follow with create_users: true' do + + puts "\n👤 Testing auto-generated users on follow..." + + # Use fresh user IDs that don't exist yet so we can verify that the + # server creates them via create_users: true. + alice_id = "autogen-alice-#{SecureRandom.hex(4)}" + bob_id = "autogen-bob-#{SecureRandom.hex(4)}" + charlie_id = "autogen-charlie-#{SecureRandom.hex(4)}" + + begin + # snippet-start: FollowCreateUsers + # Single follow with create_users: true auto-creates both the source + # (timeline:alice) and target (user:bob) users on the server. + follow_request = { + source: "timeline:#{alice_id}", + target: "user:#{bob_id}", + create_users: true, + } + + follow_response = client.feeds.follow(follow_request) + expect(follow_response).to be_a(GetStreamRuby::StreamResponse) + puts "✅ Follow created with auto-generated users: #{alice_id} -> #{bob_id}" + # snippet-stop: FollowCreateUsers + + # snippet-start: GetOrCreateFollowsCreateUsers + # Batch upsert with top-level create_users: true auto-creates any + # users referenced by source/target FIDs across the batch. + batch_response = client.feeds.get_or_create_follows( + GetStream::Generated::Models::FollowBatchRequest.new( + create_users: true, + follows: [ + GetStream::Generated::Models::FollowRequest.new( + source: "timeline:#{alice_id}", + target: "user:#{bob_id}", + ), + GetStream::Generated::Models::FollowRequest.new( + source: "timeline:#{alice_id}", + target: "user:#{charlie_id}", + ), + ], + ), + ) + expect(batch_response).to be_a(GetStreamRuby::StreamResponse) + puts "✅ Batch follow upsert with auto-generated users (targets: #{bob_id}, #{charlie_id})" + # snippet-stop: GetOrCreateFollowsCreateUsers + + # Verify the auto-generated users actually exist server-side by + # querying them back. + query_users_response = client.common.query_users( + GetStream::Generated::Models::QueryUsersPayload.new( + filter_conditions: { id: { '$in' => [alice_id, bob_id, charlie_id] } }, + ), + ) + expect(query_users_response).to be_a(GetStreamRuby::StreamResponse) + returned_ids = query_users_response.users.map(&:id) + expect(returned_ids).to include(alice_id, bob_id, charlie_id) + puts "✅ Verified auto-generated users exist: #{returned_ids.sort.join(', ')}" + + # Unfollow to clean up the follow edges + begin + client.feeds.unfollow("timeline:#{alice_id}", "user:#{bob_id}") + client.feeds.unfollow("timeline:#{alice_id}", "user:#{charlie_id}") + rescue StandardError => e + puts "⚠️ Unfollow cleanup warning: #{e.message}" + end + ensure + SuiteCleanup.register_users([alice_id, bob_id, charlie_id]) + end + + end + end describe 'Pin Operations' do From d48691b5bd845f996646a1eff806bec2631462f5 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Fri, 17 Apr 2026 15:53:50 +0200 Subject: [PATCH 2/3] FEEDS-1413: fix query_users invocation and gracefully skip follow test - query_users rides the payload on the query string, so the generated model was being stringified as Ruby's default Object#to_s. Switch to JSON.generate(...) per the convention used in chat_user_integration_spec and friends. - Handle users-as-hash response shape when extracting ids. - Rescue APIError to gracefully skip the test when the test app isn't provisioned with the required `timeline` / `user` feed groups, matching the sibling "creates and manages follows" test. Made-with: Cursor --- spec/integration/feed_integration_spec.rb | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/spec/integration/feed_integration_spec.rb b/spec/integration/feed_integration_spec.rb index b24b512c..0c113c5d 100644 --- a/spec/integration/feed_integration_spec.rb +++ b/spec/integration/feed_integration_spec.rb @@ -665,14 +665,15 @@ # snippet-stop: GetOrCreateFollowsCreateUsers # Verify the auto-generated users actually exist server-side by - # querying them back. + # querying them back. query_users expects the payload serialized as + # a JSON string (it rides on the query string, not the body). query_users_response = client.common.query_users( - GetStream::Generated::Models::QueryUsersPayload.new( - filter_conditions: { id: { '$in' => [alice_id, bob_id, charlie_id] } }, + JSON.generate( + filter_conditions: { 'id' => { '$in' => [alice_id, bob_id, charlie_id] } }, ), ) expect(query_users_response).to be_a(GetStreamRuby::StreamResponse) - returned_ids = query_users_response.users.map(&:id) + returned_ids = query_users_response.users.map { |u| u.to_h['id'] || u.id } expect(returned_ids).to include(alice_id, bob_id, charlie_id) puts "✅ Verified auto-generated users exist: #{returned_ids.sort.join(', ')}" @@ -683,6 +684,11 @@ rescue StandardError => e puts "⚠️ Unfollow cleanup warning: #{e.message}" end + rescue GetStreamRuby::APIError => e + # Matches the pattern used by the sibling follow test: if the test + # app isn't provisioned with the required feed groups (e.g. + # `timeline` / `user`), gracefully skip instead of hard-failing. + puts "⚠️ create_users follow test skipped: #{e.message}" ensure SuiteCleanup.register_users([alice_id, bob_id, charlie_id]) end From 69173ddc3ba5940f5f19145ceb2960881a2fcd15 Mon Sep 17 00:00:00 2001 From: Aditya Agarwal Date: Fri, 17 Apr 2026 15:56:32 +0200 Subject: [PATCH 3/3] FEEDS-1413: remove defensive rescue from create_users follow test Silent-skip on APIError masked real regressions. The test should fail loudly if the follow flow breaks; any missing feed-group provisioning on a given test app is an env issue to be fixed there, not hidden here. Made-with: Cursor --- spec/integration/feed_integration_spec.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/spec/integration/feed_integration_spec.rb b/spec/integration/feed_integration_spec.rb index 0c113c5d..f2c72fcf 100644 --- a/spec/integration/feed_integration_spec.rb +++ b/spec/integration/feed_integration_spec.rb @@ -684,11 +684,6 @@ rescue StandardError => e puts "⚠️ Unfollow cleanup warning: #{e.message}" end - rescue GetStreamRuby::APIError => e - # Matches the pattern used by the sibling follow test: if the test - # app isn't provisioned with the required feed groups (e.g. - # `timeline` / `user`), gracefully skip instead of hard-failing. - puts "⚠️ create_users follow test skipped: #{e.message}" ensure SuiteCleanup.register_users([alice_id, bob_id, charlie_id]) end