131 行
5.4 KiB
Ruby
131 行
5.4 KiB
Ruby
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 'groups created and updated materials across sync sources into one event' do
|
|
existing = Material.create!(
|
|
source_kind: 'google_drive_file', source_file_id: 'existing-file',
|
|
source_path: 'old.png', url: 'https://example.com/existing',
|
|
created_by_user: user, updated_by_user: user)
|
|
source
|
|
MaterialSyncSource.create!(
|
|
name: 'Second Drive source', source_kind: 'google_drive_path',
|
|
source_file_id: 'folder-456', profile: 'legacy_drive',
|
|
created_by_user: user, updated_by_user: user)
|
|
allow(GoogleDrive::ApiClient).to receive(:new).and_return(drive_client)
|
|
allow(drive_client).to receive(:each_material_file_under_folder) do |folder_id, &block|
|
|
id = folder_id == 'folder-123' ? 'existing-file' : 'new-file'
|
|
block.call(id:, name: "#{ id }.png", mime_type: 'image/png',
|
|
relative_path: "素材/#{ id }.png", sha256_checksum: nil,
|
|
web_view_link: "https://drive.google.com/file/d/#{ id }/view")
|
|
end
|
|
allow(drive_client).to receive(:download_to_tempfile) do |id, **|
|
|
Tempfile.new(['sync-event', '.png']).tap do |file|
|
|
file.binmode
|
|
file.write(id)
|
|
file.rewind
|
|
end
|
|
end
|
|
allow(MaterialThumbnailGenerator).to receive(:generate!)
|
|
previous_ids = MaterialVersion.pluck(:id)
|
|
|
|
result = nil
|
|
expect { result = described_class.sync_enabled! }
|
|
.to change { event_rows.length }.by(1)
|
|
|
|
expect(result).to have_attributes(imported: 1, updated: 1, failed: 0)
|
|
event = event_rows.last
|
|
expect(event.fetch('event_type')).to eq('materials.sync')
|
|
created = Material.find_by!(source_file_id: 'new-file')
|
|
versions = MaterialVersion.where.not(id: previous_ids)
|
|
expect(versions.pluck(:material_id).uniq).to contain_exactly(existing.id, created.id)
|
|
expect(versions.pluck(:event_type)).to include('create', 'update')
|
|
expect(versions.pluck(:event_id).uniq).to eq([event.fetch('id')])
|
|
end
|
|
|
|
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
|