require 'rails_helper' RSpec.describe MaterialSyncRunner do let(:user) { create(:user, :member) } let(:source) do MaterialSyncSource.create!( name: 'Drive source', source_kind: 'google_drive_path', source_file_id: 'folder-123', profile: 'legacy_drive', created_by_user: user, updated_by_user: user) end let(:drive_client) { instance_double(GoogleDrive::ApiClient) } describe '#sync!' do it 'imports google drive path candidates as they are yielded' do first_entry = { id: 'file-1', name: 'a.png', mime_type: 'image/png', relative_path: '素材/a.png', sha256_checksum: 'sha-a', web_view_link: 'https://drive.google.com/file/d/file-1/view', web_content_link: nil } second_entry = { id: 'file-2', name: 'b.png', mime_type: 'image/png', relative_path: '素材/b.png', sha256_checksum: 'sha-b', web_view_link: 'https://drive.google.com/file/d/file-2/view', web_content_link: nil } yielded = [] allow(GoogleDrive::ApiClient).to receive(:new).and_return(drive_client) allow(drive_client).to receive(:each_material_file_under_folder) do |folder_id, &block| expect(folder_id).to eq('folder-123') block.call(first_entry) expect(yielded).to eq(['素材/a.png']) block.call(second_entry) end allow(MaterialSyncImporter).to receive(:import!) do |candidate| yielded << candidate.fetch(:source_path) instance_double(MaterialSyncImporter::Result, action: yielded.last == '素材/a.png' ? :imported : :updated) end result = described_class.new(source).sync! expect(yielded).to eq(['素材/a.png', '素材/b.png']) expect(result.imported).to eq(1) expect(result.updated).to eq(1) expect(result.unchanged).to eq(0) expect(source.reload.last_synced_at).to be_present end it 'logs google drive path progress at first item and summary' do entry = { id: 'file-1', name: 'a.png', mime_type: 'image/png', relative_path: '素材/a.png', sha256_checksum: 'sha-a', web_view_link: 'https://drive.google.com/file/d/file-1/view', web_content_link: nil } logged = [] allow(GoogleDrive::ApiClient).to receive(:new).and_return(drive_client) allow(drive_client).to receive(:each_material_file_under_folder) do |_folder_id, &block| block.call(entry) end allow(MaterialSyncImporter).to receive(:import!) .and_return(instance_double(MaterialSyncImporter::Result, action: :imported)) allow(Rails.logger).to receive(:info) { |message| logged << JSON.parse(message) } described_class.new(source).sync! progress_logs = logged.select { |row| row['folder_id'] == 'folder-123' } expect(progress_logs.map { |row| row['progress'] }).to eq(['scan', 'summary']) expect(progress_logs.last).to include( 'material_sync_source_id' => source.id, 'material_sync_source_name' => 'Drive source', 'scanned_count' => 1, 'imported' => 1, 'updated' => 0, 'unchanged' => 0, 'suppressed' => 0, 'failed' => 0) end end end