251 lines
8.1 KiB
Ruby
251 lines
8.1 KiB
Ruby
|
require_relative '../../spec_helper'
|
||
|
|
||
|
require_relative '../../../services/data-repository/backend/sequel'
|
||
|
require_relative '../../../services/data-repository/repository'
|
||
|
require_relative '../../../app/models/synchronization/member'
|
||
|
require 'helpers/unique_names_helper'
|
||
|
require 'helpers/file_server_helper'
|
||
|
|
||
|
include UniqueNamesHelper
|
||
|
include CartoDB
|
||
|
|
||
|
describe Synchronization::Member do
|
||
|
describe 'Basic actions' do
|
||
|
it 'assigns an id by default' do
|
||
|
member = Synchronization::Member.new
|
||
|
member.should be_an_instance_of Synchronization::Member
|
||
|
member.id.should_not be_nil
|
||
|
end
|
||
|
|
||
|
it 'persists attributes to the repository' do
|
||
|
attributes = random_attributes
|
||
|
member = Synchronization::Member.new(attributes)
|
||
|
member.store
|
||
|
|
||
|
member = Synchronization::Member.new(id: member.id)
|
||
|
member.name.should be_nil
|
||
|
|
||
|
member.fetch
|
||
|
member.name .should == attributes.fetch(:name)
|
||
|
end
|
||
|
|
||
|
it 'fetches attributes from the repository' do
|
||
|
attributes = random_attributes
|
||
|
member = Synchronization::Member.new(attributes).store
|
||
|
member = Synchronization::Member.new(id: member.id)
|
||
|
member.name = 'changed'
|
||
|
member.fetch
|
||
|
member.name.should == attributes.fetch(:name)
|
||
|
end
|
||
|
|
||
|
it 'deletes this member from the repository' do
|
||
|
member = Synchronization::Member.new(random_attributes).store
|
||
|
member.fetch
|
||
|
member.name.should_not be_nil
|
||
|
|
||
|
member.delete
|
||
|
|
||
|
member.name.should be_nil
|
||
|
lambda { member.fetch }.should raise_error KeyError
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "synchronizations" do
|
||
|
before(:all) do
|
||
|
@user1 = create_user(sync_tables_enabled: true)
|
||
|
@user2 = create_user(sync_tables_enabled: true)
|
||
|
end
|
||
|
|
||
|
before(:each) do
|
||
|
bypass_named_maps
|
||
|
::Hubspot::EventsAPI.any_instance.stubs(:enabled?).returns(false)
|
||
|
end
|
||
|
|
||
|
after(:all) do
|
||
|
@user1.destroy
|
||
|
@user2.destroy
|
||
|
end
|
||
|
|
||
|
describe 'external sources' do
|
||
|
it "Authorizes to sync always if from an external source" do
|
||
|
member = Synchronization::Member.new(random_attributes(user_id: @user1.id)).store
|
||
|
member.fetch
|
||
|
|
||
|
member.expects(:from_external_source?).returns(true)
|
||
|
|
||
|
@user1.sync_tables_enabled = true
|
||
|
@user2.sync_tables_enabled = true
|
||
|
|
||
|
member.authorize?(@user1).should eq true
|
||
|
member.authorize?(@user2).should eq false
|
||
|
|
||
|
@user1.sync_tables_enabled = false
|
||
|
@user2.sync_tables_enabled = false
|
||
|
|
||
|
member.authorize?(@user1).should eq true
|
||
|
end
|
||
|
end
|
||
|
|
||
|
describe "synchronization" do
|
||
|
it 'fails if user is inactive' do
|
||
|
url = 'https://wadus.com/guess_country.csv'
|
||
|
|
||
|
path = fake_data_path('guess_country.csv')
|
||
|
stub_download(url: url, filepath: path, content_disposition: false)
|
||
|
|
||
|
attrs = random_attributes(user_id: @user1.id).merge(service_item_id: url, url: url, name: 'guess_country')
|
||
|
member = Synchronization::Member.new(attrs).store
|
||
|
|
||
|
DataImport.create(
|
||
|
user_id: @user1.id,
|
||
|
data_source: fake_data_path('guess_country.csv'),
|
||
|
synchronization_id: member.id,
|
||
|
service_name: 'public_url',
|
||
|
service_item_id: url,
|
||
|
updated_at: Time.now
|
||
|
).run_import!
|
||
|
@user1.state = Carto::User::STATE_LOCKED
|
||
|
@user1.save
|
||
|
|
||
|
Rails.logger.expects(:error).once
|
||
|
|
||
|
member.fetch.run
|
||
|
|
||
|
member.log.entries.should match /Can't run a synchronization for inactive user/
|
||
|
expect(member.state).to eq 'failure'
|
||
|
|
||
|
@user1.state = Carto::User::STATE_ACTIVE
|
||
|
@user1.sync_tables_enabled = true
|
||
|
@user1.save
|
||
|
@user1.reload
|
||
|
end
|
||
|
|
||
|
it 'fails to overwrite tables with views by replacement' do
|
||
|
url = 'https://wadus.com/guess_country.csv'
|
||
|
|
||
|
path = fake_data_path('guess_country.csv')
|
||
|
stub_download(url: url, filepath: path, content_disposition: false)
|
||
|
|
||
|
attrs = random_attributes(user_id: @user2.id).merge(service_item_id: url, url: url, name: 'guess_country')
|
||
|
member = Synchronization::Member.new(attrs).store
|
||
|
|
||
|
DataImport.create(
|
||
|
user_id: @user2.id,
|
||
|
data_source: path,
|
||
|
synchronization_id: member.id,
|
||
|
service_name: 'public_url',
|
||
|
service_item_id: url,
|
||
|
updated_at: Time.now
|
||
|
).run_import!
|
||
|
|
||
|
@user2.in_database.execute('CREATE VIEW wadus AS SELECT * FROM guess_country')
|
||
|
|
||
|
member.run
|
||
|
expect(member.state).to eq 'failure'
|
||
|
expect(member.error_code).to eq 2013
|
||
|
end
|
||
|
|
||
|
it 'it can overwrite tables with views by sync' do
|
||
|
url = 'https://wadus.com/guess_country_geocoded.csv'
|
||
|
|
||
|
path = fake_data_path('guess_country_geocoded.csv')
|
||
|
stub_download(url: url, filepath: path, content_disposition: false)
|
||
|
|
||
|
attrs = random_attributes(user_id: @user2.id).merge(service_item_id: url, url: url, name: 'guess_country_geocoded')
|
||
|
member = Synchronization::Member.new(attrs).store
|
||
|
|
||
|
DataImport.create(
|
||
|
user_id: @user2.id,
|
||
|
data_source: path,
|
||
|
synchronization_id: member.id,
|
||
|
service_name: 'public_url',
|
||
|
service_item_id: url,
|
||
|
updated_at: Time.now
|
||
|
).run_import!
|
||
|
|
||
|
@user2.in_database.execute('CREATE VIEW wadus_geocoded AS SELECT * FROM guess_country_geocoded')
|
||
|
|
||
|
member.run
|
||
|
expect(member.state).to eq 'success'
|
||
|
end
|
||
|
|
||
|
it 'should sync files with missing ogc_fid' do
|
||
|
stub_arcgis_response_with_file(
|
||
|
File.expand_path('spec/fixtures/arcgis_response_missing_ogc_fid.json'),
|
||
|
File.expand_path('spec/fixtures/arcgis_metadata_ogc_fid.json')
|
||
|
)
|
||
|
|
||
|
url = 'https://wtf.com/arcgis/rest/services/Planning/EPI_Primary_Planning_Layers/MapServer/2'
|
||
|
|
||
|
attrs = random_attributes(user_id: @user1.id)
|
||
|
.merge(service_item_id: url, url: url, name: 'land_zoning')
|
||
|
member = Synchronization::Member.new(attrs).store
|
||
|
|
||
|
data_import = DataImport.create(
|
||
|
user_id: @user1.id,
|
||
|
synchronization_id: member.id,
|
||
|
service_name: 'arcgis',
|
||
|
service_item_id: url,
|
||
|
updated_at: Time.now
|
||
|
)
|
||
|
|
||
|
data_import.run_import!
|
||
|
expect(data_import.state).to eq 'complete'
|
||
|
|
||
|
source_file = CartoDB::Importer2::SourceFile.new(
|
||
|
File.expand_path('spec/fixtures/arcgis_response_missing_ogc_fid.json'),
|
||
|
'arcgis_response_missing_ogc_fid.json'
|
||
|
)
|
||
|
CartoDB::Importer2::Downloader.any_instance.stubs(:download_and_store).returns(source_file)
|
||
|
CartoDB::Importer2::Downloader.any_instance.stubs(:source_file).returns(source_file)
|
||
|
member.run
|
||
|
expect(member.state).to eq 'success'
|
||
|
end
|
||
|
|
||
|
it 'keeps indices' do
|
||
|
url = 'https://wadus.com/clubbing.csv'
|
||
|
|
||
|
path = fake_data_path('clubbing.csv')
|
||
|
stub_download(url: url, filepath: path, content_disposition: false)
|
||
|
|
||
|
attrs = random_attributes(user_id: @user2.id).merge(service_item_id: url, url: url, name: 'clubbing')
|
||
|
member = Synchronization::Member.new(attrs).store
|
||
|
|
||
|
# Create table with index
|
||
|
DataImport.create(
|
||
|
user_id: @user2.id,
|
||
|
data_source: path,
|
||
|
synchronization_id: member.id,
|
||
|
service_name: 'public_url',
|
||
|
service_item_id: url,
|
||
|
updated_at: Time.now
|
||
|
).run_import!
|
||
|
@user2.in_database.execute('CREATE INDEX ON clubbing (nombre)')
|
||
|
|
||
|
# Sync the table
|
||
|
member.run
|
||
|
expect(member.state).to eq 'success'
|
||
|
|
||
|
# Expect custom and default indices to still exist
|
||
|
table = UserTable.where(user: @user2, name: 'clubbing').first
|
||
|
indexed_columns = table.service.pg_indexes.map { |x| x[:column] }
|
||
|
expected_indices = ['cartodb_id', 'the_geom', 'the_geom_webmercator', 'nombre']
|
||
|
|
||
|
expect(indexed_columns.sort).to eq(expected_indices.sort)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
private
|
||
|
|
||
|
def random_attributes(attributes={})
|
||
|
random = unique_integer
|
||
|
{
|
||
|
name: attributes.fetch(:name, "name#{random}"),
|
||
|
interval: attributes.fetch(:interval, 15 * 60 + random),
|
||
|
state: attributes.fetch(:state, 'enabled'),
|
||
|
user_id: attributes.fetch(:user_id, nil)
|
||
|
}
|
||
|
end
|
||
|
end
|