require 'rails_helper' RSpec.describe Youtube::ApiClient do let(:api_key) { 'test-api-key' } let(:client) { described_class.new(api_key:) } describe '#search_videos' do it 'calls YouTube search API with expected params' do published_after = Time.zone.parse('2026-05-01 00:00:00') published_before = Time.zone.parse('2026-05-02 00:00:00') expect(client).to receive(:get_json).with( '/search', { part: 'snippet', type: 'video', q: 'ぼざろクリーチャー', order: 'date', maxResults: 50, regionCode: 'JP', relevanceLanguage: 'ja', publishedAfter: published_after.iso8601, publishedBefore: published_before.iso8601, pageToken: 'NEXT' } ).and_return({ 'items' => [] }) client.search_videos( q: 'ぼざろクリーチャー', published_after:, published_before:, page_token: 'NEXT' ) end it 'omits nil optional params' do expect(client).to receive(:get_json).with( '/search', hash_excluding(:publishedAfter, :publishedBefore, :pageToken) ).and_return({ 'items' => [] }) client.search_videos(q: 'ぼざろクリーチャー') end end describe '#videos' do it 'returns empty items when ids are empty' do expect(client).not_to receive(:get_json) expect(client.videos([])).to eq({ 'items' => [] }) end it 'calls videos API with comma separated ids' do expect(client).to receive(:get_json).with( '/videos', { part: 'snippet,status,contentDetails', id: 'video-1,video-2' } ).and_return({ 'items' => [] }) client.videos(['video-1', 'video-2']) end end describe '#playlist_items' do it 'calls playlistItems API with page token' do expect(client).to receive(:get_json).with( '/playlistItems', { part: 'snippet,contentDetails,status', playlistId: 'PL123', maxResults: 50, pageToken: 'NEXT' } ).and_return({ 'items' => [] }) client.playlist_items(playlist_id: 'PL123', page_token: 'NEXT') end it 'omits page token when nil' do expect(client).to receive(:get_json).with( '/playlistItems', { part: 'snippet,contentDetails,status', playlistId: 'PL123', maxResults: 50 } ).and_return({ 'items' => [] }) client.playlist_items(playlist_id: 'PL123') end end describe '#channel' do it 'calls channels API by id' do expect(client).to receive(:get_json).with( '/channels', { part: 'snippet,contentDetails', id: 'UC123' } ).and_return({ 'items' => [] }) client.channel(id: 'UC123') end it 'calls channels API by handle' do expect(client).to receive(:get_json).with( '/channels', { part: 'snippet,contentDetails', forHandle: '@some_handle' } ).and_return({ 'items' => [] }) client.channel(handle: '@some_handle') end it 'raises when neither id nor handle is given' do expect { client.channel }.to raise_error(ArgumentError, 'id or handle is required') end it 'raises when both id and handle are given' do expect do client.channel(id: 'UC123', handle: '@some_handle') end.to raise_error(ArgumentError, 'id or handle is required') end end end