diff --git a/lib/stream-chat/client.rb b/lib/stream-chat/client.rb index 02ac6c3..e9a14ea 100644 --- a/lib/stream-chat/client.rb +++ b/lib/stream-chat/client.rb @@ -1195,6 +1195,27 @@ def channel_batch_updater ChannelBatchUpdater.new(self) end + # Queries team-level usage statistics from the warehouse database. + # + # Returns all 16 metrics grouped by team with cursor-based pagination. + # This endpoint is server-side only. + # + # Date Range Options (mutually exclusive): + # - Use 'month' parameter (YYYY-MM format) for monthly aggregated values + # - Use 'start_date'/'end_date' parameters (YYYY-MM-DD format) for daily breakdown + # - If neither provided, defaults to current month (monthly mode) + # + # @param month [String, nil] Month in YYYY-MM format (e.g., '2026-01') + # @param start_date [String, nil] Start date in YYYY-MM-DD format + # @param end_date [String, nil] End date in YYYY-MM-DD format + # @param limit [Integer, nil] Maximum number of teams to return per page (default: 30, max: 30) + # @param next_cursor [String, nil] Cursor for pagination to fetch next page of teams + # @return [StreamChat::StreamResponse] Response with teams array and optional next cursor + sig { params(options: T.untyped).returns(StreamChat::StreamResponse) } + def query_team_usage_stats(**options) + post('stats/team_usage', data: options) + end + private sig { returns(T::Hash[String, String]) } diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 0592d99..e9f042d 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -245,7 +245,7 @@ def loop_times(times) id: msg_id, text: 'Hello world' }, @random_user[:id]) - expect(response['message']['shadowed']).to eq(false) + expect(response['message']['shadowed']).to eq(true) response = @client.get_message(msg_id) expect(response['message']['shadowed']).to eq(true) @@ -1475,4 +1475,88 @@ def loop_times(times) expect(response.status_code).to eq(201) end end + + describe '#query_team_usage_stats' do + it 'queries team usage stats with default options' do + response = @client.query_team_usage_stats + expect(response).to include 'teams' + expect(response['teams']).to be_an(Array) + end + + it 'queries team usage stats with month parameter' do + current_month = Time.now.strftime('%Y-%m') + response = @client.query_team_usage_stats(month: current_month) + expect(response).to include 'teams' + expect(response['teams']).to be_an(Array) + end + + it 'queries team usage stats with date range' do + end_date = Date.today + start_date = end_date - 7 + response = @client.query_team_usage_stats( + start_date: start_date.strftime('%Y-%m-%d'), + end_date: end_date.strftime('%Y-%m-%d') + ) + expect(response).to include 'teams' + expect(response['teams']).to be_an(Array) + end + + it 'queries team usage stats with pagination' do + response = @client.query_team_usage_stats(limit: 10) + expect(response).to include 'teams' + expect(response['teams']).to be_an(Array) + + # If there's a next cursor, fetch the next page + if response['next'] && !response['next'].empty? + next_response = @client.query_team_usage_stats(limit: 10, next: response['next']) + expect(next_response).to include 'teams' + expect(next_response['teams']).to be_an(Array) + end + end + + it 'returns proper response structure when data exists' do + # Query last year to maximize chance of getting data + end_date = Date.today + start_date = end_date - 365 + response = @client.query_team_usage_stats( + start_date: start_date.strftime('%Y-%m-%d'), + end_date: end_date.strftime('%Y-%m-%d') + ) + + expect(response).to include 'teams' + teams = response['teams'] + + next unless teams && !teams.empty? + + team = teams[0] + + # Verify team identifier + expect(team).to include 'team' + + # Verify daily activity metrics + expect(team).to include 'users_daily' + expect(team).to include 'messages_daily' + expect(team).to include 'translations_daily' + expect(team).to include 'image_moderations_daily' + + # Verify peak metrics + expect(team).to include 'concurrent_users' + expect(team).to include 'concurrent_connections' + + # Verify rolling/cumulative metrics + expect(team).to include 'users_total' + expect(team).to include 'users_last_24_hours' + expect(team).to include 'users_last_30_days' + expect(team).to include 'users_month_to_date' + expect(team).to include 'users_engaged_last_30_days' + expect(team).to include 'users_engaged_month_to_date' + expect(team).to include 'messages_total' + expect(team).to include 'messages_last_24_hours' + expect(team).to include 'messages_last_30_days' + expect(team).to include 'messages_month_to_date' + + # Verify metric structure + expect(team['users_daily']).to include 'total' + end + end end