cartodb-4.42/spec/requests/carto/api/geocodings_controller_spec.rb
2024-04-06 05:25:13 +00:00

311 lines
13 KiB
Ruby

require_relative '../../../spec_helper'
require_relative '../../api/json/geocodings_controller_shared_examples'
require_relative '../../../../app/controllers/carto/api/geocodings_controller'
require 'mock_redis'
describe Carto::Api::GeocodingsController do
it_behaves_like 'geocoding controllers' do
end
describe 'legacy behaviour tests' do
let(:params) { { :api_key => @user.api_key } }
before(:all) do
@user = create_user
end
before(:each) do
bypass_named_maps
delete_user_data @user
host! "#{@user.username}.localhost.lan"
login_as(@user, scope: @user.username)
end
after(:all) do
bypass_named_maps
@user.destroy
end
describe 'GET /api/v1/geocodings' do
it 'returns every geocoding belonging to current_user' do
FactoryGirl.create(:geocoding, table_name: 'a', formatter: 'b', user: @user, state: 'wadus')
FactoryGirl.create(:geocoding, table_name: 'a', formatter: 'b', user_id: Carto::UUIDHelper.random_uuid)
get_json api_v1_geocodings_index_url(params) do |response|
response.status.should be_success
response.body[:geocodings].size.should == 1
end
end
end
describe 'GET /api/v1/geocodings/:id' do
it 'returns a geocoding' do
@user.geocoder_provider = 'heremaps'
@user.save.reload
redis_mock = MockRedis.new
user_geocoder_metrics = CartoDB::GeocoderUsageMetrics.new(@user.username, _orgname = nil, _redis = redis_mock)
CartoDB::GeocoderUsageMetrics.stubs(:new).returns(user_geocoder_metrics)
user_geocoder_metrics.incr(:geocoder_here, :success_responses, 100)
geocoding = FactoryGirl.create(:geocoding, table_id: Carto::UUIDHelper.random_uuid, formatter: 'b', user: @user, used_credits: 100, processed_rows: 100, kind: 'high-resolution')
get_json api_v1_geocodings_show_url(params.merge(id: geocoding.id)) do |response|
response.status.should be_success
response.body[:id].should eq geocoding.id
response.body[:used_credits].should eq 100
response.body[:price].should eq 150
response.body[:remaining_quota].should eq 900
end
end
it 'does not return a geocoding owned by another user' do
geocoding = FactoryGirl.create(:geocoding, table_id: Carto::UUIDHelper.random_uuid, formatter: 'b', user_id: Carto::UUIDHelper.random_uuid)
get_json api_v1_geocodings_show_url(params.merge(id: geocoding.id)) do |response|
response.status.should eq 404
end
end
end
describe 'GET /api/v1/geocodings/estimation_for' do
it 'returns the estimated geocoding cost for the specified table' do
table = create_table(user_id: @user.id)
Geocoding.stubs(:processable_rows).returns(2)
Carto::Geocoding.stubs(:processable_rows).returns(2)
get_json api_v1_geocodings_estimation_url(params.merge(table_name: table.name)) do |response|
response.status.should be_success
response.body.should == {:rows=>2, :estimation=>0}
end
Geocoding.stubs(:processable_rows).returns(1400)
Carto::Geocoding.stubs(:processable_rows).returns(1400)
get_json api_v1_geocodings_estimation_url(params.merge(table_name: table.name)) do |response|
response.status.should be_success
response.body.should == {:rows=>1400, :estimation=>600}
end
Geocoding.stubs(:processable_rows).returns(1001)
Carto::Geocoding.stubs(:processable_rows).returns(1001)
get_json api_v1_geocodings_estimation_url(params.merge(table_name: table.name)) do |response|
response.status.should be_success
response.body.should == {:rows=>1001, :estimation=>1.5}
end
end
it 'returns 500 if the table does not exist' do
get_json api_v1_geocodings_estimation_url(params.merge(table_name: 'me_not_exist')) do |response|
response.status.should eq 500
response.body[:description].should_not be_blank
end
end
it 'takes the parameter force_all_rows into consideration' do
@user.geocoding_quota = 0
@user.save
table = create_table(user_id: @user.id)
table.add_column!(name: 'cartodb_georef_status', type: 'bool')
table.insert_row!(cartodb_georef_status: nil)
table.insert_row!(cartodb_georef_status: true)
table.insert_row!(cartodb_georef_status: false)
expected_rows = 2
expected_estimation = expected_rows * @user.geocoding_block_price / Carto::Geocoding::GEOCODING_BLOCK_SIZE
get_json api_v1_geocodings_estimation_url(params.merge(table_name: table.name, force_all_rows: false)) do |response|
response.status.should be_success
response.body.should == {rows: expected_rows, estimation: expected_estimation}
end
expected_rows = 3
expected_estimation = expected_rows * @user.geocoding_block_price / Carto::Geocoding::GEOCODING_BLOCK_SIZE
get_json api_v1_geocodings_estimation_url(params.merge(table_name: table.name, force_all_rows: true)) do |response|
response.status.should be_success
response.body.should == {rows: expected_rows, estimation: expected_estimation}
end
end
end
end
describe 'available_geometries' do
include_context 'users helper'
include_context 'visualization creation helpers'
before(:each) do
login(@user1)
end
it 'returns 400 if kind is not admin1, namedplace or postalcode' do
get api_v1_geocodings_available_geometries_url, { kind: 'kk'}
last_response.status.should == 400
end
it 'returns "polygon" for "admin1" kind' do
get api_v1_geocodings_available_geometries_url, { kind: 'admin1'}
last_response.status.should == 200
JSON.parse(last_response.body).should eq ['polygon']
end
it 'returns "point" for "namedplace" kind' do
get api_v1_geocodings_available_geometries_url, { kind: 'namedplace'}
last_response.status.should == 200
JSON.parse(last_response.body).should eq ['point']
end
it 'returns 400 for postal code if "free_text" or "column_name" and "table_name" are not set' do
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode'}
last_response.status.should == 400
end
it 'returns empty json for postalcode if free text is empty or has non alphanumeric characters' do
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: ''}
last_response.status.should == 200
JSON.parse(last_response.body).should eq []
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: ' '}
last_response.status.should == 200
JSON.parse(last_response.body).should eq []
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: '--%'}
last_response.status.should == 200
JSON.parse(last_response.body).should eq []
end
it 'returns point and polygon if SQLApi says there are the same amount of points and polygons services, or the one with more data if they are not equal' do
# INFO: this expectation is bound to implementation because it's used in a refactor
CartoDB::SQLApi.any_instance.expects(:fetch).with("SELECT (admin0_available_services(Array['myfreetext'])).*").returns([ { 'postal_code_points' => 1, 'postal_code_polygons' => 1 }])
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: 'my free text'}
JSON.parse(last_response.body).should eq ['point', 'polygon']
CartoDB::SQLApi.any_instance.stubs(:fetch).returns([ { 'postal_code_points' => 1, 'postal_code_polygons' => 1 }, { 'postal_code_points' => 1 }])
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: 'my free text'}
JSON.parse(last_response.body).should eq ['point']
CartoDB::SQLApi.any_instance.stubs(:fetch).returns([ { 'postal_code_points' => 1, 'postal_code_polygons' => 1 }, { 'postal_code_polygons' => 1 }])
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', free_text: 'my free text'}
JSON.parse(last_response.body).should eq ['polygon']
end
it 'returns point from an input column if SQLApi says there is a point service for it' do
table = create_table(user_id: @user1.id)
table.add_column!(name: 'country', type: 'string')
table.insert_row!(country: 'Cote d\'Ivore')
CartoDB::SQLApi.any_instance.expects(:fetch).
with("SELECT (admin0_available_services(Array['Cote d''Ivore'])).*").
returns([{ 'postal_code_points' => 1, 'postal_code_polygons' => 0 }])
get api_v1_geocodings_available_geometries_url,
{ kind: 'postalcode', column_name: 'country', table_name: table.name }
last_response.status.should == 200
end
it 'returns 400 if table name does not exist' do
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', column_name: 'my_column', table_name: 'my_table'}
last_response.status.should eq 400
end
it 'Queries SQL API with table columns' do
cp = 12345
table = create_random_table(@user1)
table.insert_row!({name: cp})
# INFO: this expectation is bound to implementation because it's used in a refactor
CartoDB::SQLApi.any_instance.expects(:fetch).with("SELECT (admin0_available_services(Array['#{cp}'])).*").returns([ { 'postal_code_points' => 1, 'postal_code_polygons' => 1 }, { 'postal_code_polygons' => 1 }])
get api_v1_geocodings_available_geometries_url, { kind: 'postalcode', column_name: 'name', table_name: table.name}
end
end
describe 'estimation_for' do
include_context 'users helper'
include_context 'visualization creation helpers'
before(:each) do
login(@user1)
end
it 'returns estimation and price' do
table = create_random_table(@user1)
table.insert_row!({name: 'estimation'})
get api_v1_geocodings_estimation_url(table_name: table.name)
last_response.status.should eq 200
body = JSON.parse(last_response.body)
body.should == { 'rows' => 1, 'estimation' => 0 }
end
end
def remove_dates(geocoding_hash)
geocoding_hash.except('created_at', 'updated_at')
end
describe 'index' do
include_context 'users helper'
before(:each) do
login(@user1)
end
it 'returns started geocodings but not finished' do
geocoding1 = FactoryGirl.create(:geocoding, user: @user1, kind: 'high-resolution', created_at: Time.now,
processed_rows: 1, state: 'started', formatter: 'foo')
FactoryGirl.create(:geocoding, user: @user1, kind: 'high-resolution', created_at: Time.now,
processed_rows: 1, state: 'finished', formatter: 'foo')
get api_v1_geocodings_index_url
last_response.status.should eq 200
expected = {"geocodings"=>[{"table_name" => nil, "processed_rows" => 1, "remote_id" => nil, "formatter" => 'foo',
"geocoder_type" => nil, "state" => "started", "cache_hits" => 0,
"id" => geocoding1.id, "user_id" => @user1.id,"table_id" => nil,
"kind" => "high-resolution", "country_code" => nil,
"geometry_type" => nil, "processable_rows" => nil, "real_rows" => nil,
"used_credits" => nil, "country_column" => nil, "data_import_id" => nil,
"region_code" => nil, "region_column" => nil, "batched" => nil, "error_code" => nil,
"force_all_rows" => false, "log_id" => nil, "pid" => nil}]}
received_without_dates = {
'geocodings' => JSON.parse(last_response.body)['geocodings'].map { |g| remove_dates(g) }
}
received_without_dates.should == expected
end
end
describe 'show' do
include_context 'users helper'
before(:each) do
login(@user1)
end
it 'returns requested geocoding' do
geocoding = FactoryGirl.create(
:geocoding,
user: @user1,
kind: 'high-resolution',
created_at: Time.now,
processed_rows: 1,
state: 'started',
formatter: 'foo'
)
get api_v1_geocodings_show_url(id: geocoding.id)
last_response.status.should eq 200
expected = {"id" => geocoding.id, "table_id" => nil, "table_name" => nil, "state" => "started",
"kind" => "high-resolution", "country_code" => nil, "region_code" => nil, "formatter" => 'foo',
"geocoder_type" => nil, "geometry_type" => nil, "error" => {"title" => "Geocoding error",
"description" => ""}, "processed_rows" => 1, "cache_hits" => 0, "processable_rows" => nil,
"real_rows" => nil, "price" => 0, "used_credits" => nil, "remaining_quota" => 0,
"country_column" => nil, "region_column" => nil, "data_import_id" => nil, "error_code" => nil}
received_without_dates = remove_dates(JSON.parse(last_response.body))
received_without_dates.should == expected
end
end
include Rack::Test::Methods
include Warden::Test::Helpers
end