diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 578003d..506d6a3 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1 +1 @@ -* @JimmyPettersson85 @xernobyl @itsmeadi +* @JimmyPettersson85 @itsmeadi diff --git a/.rubocop.yml b/.rubocop.yml index 59d2e8a..1fb395e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -31,6 +31,8 @@ Metrics/PerceivedComplexity: Naming/AccessorMethodName: Enabled: false +Naming/PredicateMethod: + Enabled: false Style/AccessorGrouping: Enabled: false diff --git a/lib/stream/activities.rb b/lib/stream/activities.rb index c0b6567..54f01ff 100644 --- a/lib/stream/activities.rb +++ b/lib/stream/activities.rb @@ -53,6 +53,9 @@ def get_activities(params = {}) end %i[enrich reactions].each { |k| params.delete(k) } + # Handle multiple IDs by joining with commas + params[:ids] = params[:ids].join(',') if params[:ids]&.is_a?(Array) + signature = Stream::Signer.create_jwt_token('activities', '*', @api_secret, '*') make_request(:get, uri, signature, params) end diff --git a/lib/stream/client.rb b/lib/stream/client.rb index a366355..95cc47f 100644 --- a/lib/stream/client.rb +++ b/lib/stream/client.rb @@ -214,7 +214,7 @@ def call(env) end def initialize(app) - super app + super @parser = nil end diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 732900c..f8b1936 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -139,4 +139,64 @@ http_client = client.get_http_client expect(http_client.conn.options[:timeout]).to eq 5 end + + describe 'get_activities' do + before do + @client = Stream::Client.new('key', 'secret', 'app_id') + @captured_requests = [] + + # Mock the HTTP client to capture requests + allow_any_instance_of(Stream::StreamHTTPClient).to receive(:make_http_request) do |_instance, method, relative_url, params, data, headers| + @captured_requests << { + method: method, + url: relative_url, + params: params, + data: data, + headers: headers + } + + # Return mock response + { + 'results' => [], + 'duration' => '10ms' + } + end + end + + it 'should encode multiple activity IDs as comma-separated values' do + ids = %w[id1 id2 id3] + + @client.get_activities(ids: ids) + + expect(@captured_requests.length).to eq(1) + request = @captured_requests.first + + # Verify the IDs are joined with commas, not passed as an array + expect(request[:params][:ids]).to eq('id1,id2,id3') + expect(request[:params][:ids]).not_to be_a(Array) + expect(request[:url]).to eq('/activities/') + end + + it 'should handle single ID without comma separation' do + @client.get_activities(ids: ['single-id']) + + expect(@captured_requests.length).to eq(1) + request = @captured_requests.first + + # Single ID should still be encoded correctly + expect(request[:params][:ids]).to eq('single-id') + expect(request[:params][:ids]).not_to be_a(Array) + end + + it 'should preserve other parameters when encoding IDs' do + @client.get_activities(ids: %w[id1 id2], limit: 10, offset: 20) + + expect(@captured_requests.length).to eq(1) + request = @captured_requests.first + + expect(request[:params][:ids]).to eq('id1,id2') + expect(request[:params][:limit]).to eq(10) + expect(request[:params][:offset]).to eq(20) + end + end end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 64be05d..1ff1e89 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -179,7 +179,7 @@ expect(results[0]['id']).to eq response['id'] feed.remove_activity(response['id']) results = feed.get(limit: 1)['results'] - expect(results[0]['id']).not_to eq response['id'] if results.count > 0 + expect(results[0]['id']).not_to eq response['id'] if results.any? end example 'removing an activity by foreign_id' do @@ -675,6 +675,56 @@ response = @client.get_activities(ids: [activity['id']], reactions: { own: true }) expect(response['results'][0]['own_reactions']['like'][0]).to eq reaction end + example 'get multiple activities by IDs' do + # Create two different activities + activity1 = @feed42.add_activity( + actor: 'alice', + verb: 'tweet', + object: 'message1', + foreign_id: "tweet-#{Time.now.to_i}-1" + ) + + activity2 = @feed42.add_activity( + actor: 'bob', + verb: 'like', + object: 'post1', + foreign_id: "like-#{Time.now.to_i}-2" + ) + + # Remove duration from comparison since it varies + activity1.delete('duration') + activity2.delete('duration') + + # Wait a moment for activities to be indexed + sleep(2) + + # Test: Get both activities by their IDs in a single call + response = @client.get_activities( + ids: [activity1['id'], activity2['id']] + ) + + expect(response).to include('duration', 'results') + expect(response['results'].count).to be 2 + + # Verify both activities are returned + returned_ids = response['results'].map { |a| a['id'] } + expect(returned_ids).to include(activity1['id']) + expect(returned_ids).to include(activity2['id']) + + # Verify the returned activities match the original activities + response['results'].each do |returned_activity| + returned_activity.delete('duration') + + if returned_activity['id'] == activity1['id'] + expect(returned_activity).to eq(activity1) + elsif returned_activity['id'] == activity2['id'] + expect(returned_activity).to eq(activity2) + else + raise "Unexpected activity ID: #{returned_activity['id']}" + end + end + end + example 'activity recent reaction enrichment' do activity = @feed42.add_activity({ actor: 'jim', verb: 'buy', object: 'wallet' }) reaction = @client.reactions.add('dislike', activity['id'], 'jim')