cartodb-4.42/spec/requests/carto/api/vizjson3_presenter_spec.rb

385 lines
14 KiB
Ruby
Raw Normal View History

2024-04-06 13:25:13 +08:00
require 'spec_helper_min'
require 'mock_redis'
require 'carto/api/vizjson3_presenter'
require 'carto/api/vizjson_presenter'
describe Carto::Api::VizJSON3Presenter do
include Carto::Factories::Visualizations
include_context 'visualization creation helpers'
before(:all) do
@user1 = FactoryGirl.create(:carto_user, private_tables_enabled: true)
end
after(:all) do
@user1.destroy
end
let(:redis_mock) do
MockRedis.new
end
shared_context 'full visualization' do
before(:all) do
bypass_named_maps
@map, @table, @table_visualization, @visualization = create_full_visualization(Carto::User.find(@user1.id))
@table.update_attribute(:privacy, Carto::UserTable::PRIVACY_PUBLIC)
end
after(:all) do
destroy_full_visualization(@map, @table, @table_visualization, @visualization)
end
let(:viewer_user) { @visualization.user }
end
describe 'caching' do
include_context 'full visualization'
let(:fake_vizjson) { { fake: 'sure!', layers: [] } }
it 'to_vizjson uses the redis vizjson cache' do
cache_mock = mock
cache_mock.expects(:cached).with(@visualization.id, false, 3).twice.returns(fake_vizjson)
presenter = Carto::Api::VizJSON3Presenter.new(@visualization, cache_mock)
v1 = presenter.to_vizjson
v2 = presenter.to_vizjson
v1.should eq fake_vizjson
v1.should eq v2
end
it 'every call to_vizjson uses calculate_vizjson if no cache is provided' do
presenter = Carto::Api::VizJSON3Presenter.new(@visualization, nil)
presenter.expects(:calculate_vizjson).twice.returns(fake_vizjson)
presenter.to_vizjson
presenter.to_vizjson
end
it 'to_vizjson is not overriden by v2 caching or to_named_map_vizjson' do
v2_presenter = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata)
v3_presenter = Carto::Api::VizJSON3Presenter.new(@visualization)
v2_vizjson = v2_presenter.to_vizjson
v3_vizjson = v3_presenter.to_vizjson
v3n_vizjson = v3_presenter.to_named_map_vizjson
v3_vizjson.should_not eq v2_vizjson
v2_vizjson[:version].should eq '0.1.0'
v3_vizjson[:version].should eq '3.0.0'
v3n_vizjson[:version].should eq '3.0.0'
end
it 'to_vizjson does not override v2 caching or named map vizjson' do
v2_presenter = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata)
v3_presenter = Carto::Api::VizJSON3Presenter.new(@visualization)
v3_vizjson = v3_presenter.to_vizjson
v2_vizjson = v2_presenter.to_vizjson
v3n_vizjson = v3_presenter.to_named_map_vizjson
v2_vizjson.should_not eq v3_vizjson
v3n_vizjson.should_not eq v3_vizjson
v2_vizjson[:version].should eq '0.1.0'
v3_vizjson[:version].should eq '3.0.0'
v3n_vizjson[:version].should eq '3.0.0'
end
it 'to_named_map_vizjson uses the redis vizjson cache' do
fake_vizjson = { fake: 'sure!', layers: [] }
cache_mock = mock
cache_mock.expects(:cached).with(@visualization.id, false, anything).returns(fake_vizjson).twice
presenter = Carto::Api::VizJSON3Presenter.new(@visualization, cache_mock)
v1 = presenter.to_named_map_vizjson
v2 = presenter.to_named_map_vizjson
v1.should eq fake_vizjson
v1.should eq v2
end
end
describe '#to_vizjson (without caching)' do
include_context 'full visualization'
it 'returns map bounds' do
presenter = Carto::Api::VizJSON3Presenter.new(@visualization, nil)
presenter.to_vizjson[:bounds].should eq [[-85.0511, -179], [85.0511, 179]]
end
it 'returns nil map bounds if map bounds are not set' do
@visualization.map.view_bounds_sw = nil
@visualization.map.view_bounds_ne = nil
Carto::Api::VizJSON3Presenter.new(@visualization, nil).to_vizjson[:bounds].should be_nil
end
end
describe '#to_named_map_vizjson' do
include_context 'full visualization'
it 'generates the vizjson of visualizations that have not named map as if they had' do
@table.privacy = Carto::UserTable::PRIVACY_PUBLIC
@table.save
@visualization = Carto::Visualization.find(@visualization.id)
v3_presenter = Carto::Api::VizJSON3Presenter.new(@visualization, nil)
original_vizjson = v3_presenter.to_vizjson.reject { |k, _| k == :updated_at }
original_named_vizjson = v3_presenter.to_named_map_vizjson.reject { |k, _| k == :updated_at }
original_vizjson.should_not eq original_named_vizjson
@table.privacy = Carto::UserTable::PRIVACY_PRIVATE
@table.save!
@visualization = Carto::Visualization.find(@visualization.id)
v3_presenter = Carto::Api::VizJSON3Presenter.new(@visualization, nil)
named_vizjson = v3_presenter.to_vizjson.reject { |k, _| k == :updated_at }
original_named_vizjson.should eq named_vizjson
named_named_vizjson = v3_presenter.to_vizjson.reject { |k, _| k == :updated_at }
named_named_vizjson.should eq named_vizjson
end
it 'includes analyses information without including sources parameters' do
analysis = FactoryGirl.create(:analysis_with_source, visualization: @visualization, user: @user1)
analysis.analysis_definition[:params].should_not be_nil
@visualization.reload
v3_presenter = Carto::Api::VizJSON3Presenter.new(@visualization, nil)
named_vizjson = v3_presenter.to_vizjson
analyses_json = named_vizjson[:analyses]
analyses_json.should_not be_nil
source_analysis_definition = analyses_json[0][:params][:source]
source_analysis_definition[:type].should eq 'source'
source_analysis_definition[:params].should be_nil
end
it 'allows whitespace layer names' do
layer = @visualization.data_layers.first
layer.options['table_name_alias'] = ' '
layer.save
@visualization.reload
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send :calculate_vizjson
v3_vizjson[:layers][1][:options][:layer_name].should eq ' '
end
it 'includes source at layers options' do
source = 'a1'
layer = @visualization.data_layers.first
layer.options['source'] = source
layer.save
@table.privacy = Carto::UserTable::PRIVACY_PRIVATE
@table.save!
@visualization.reload
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send :calculate_vizjson
v3_vizjson[:layers][1][:options][:source].should eq source
end
it 'includes cartocss at layers options' do
cartocss = '#layer { marker-fill: #fabada; }'
layer = @visualization.data_layers.first
layer.options['tile_style'] = cartocss
layer.save
@table.privacy = Carto::UserTable::PRIVACY_PRIVATE
@table.save!
@visualization.reload
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send :calculate_vizjson
v3_vizjson[:layers][1][:options][:cartocss].should eq cartocss
end
end
describe 'analyses' do
include_context 'full visualization'
it 'sends `source` at layer options instead of sql if source is set for named maps' do
query = "select * from #{@table.name}"
layer = @visualization.data_layers.first
layer.options['source'].should eq nil
layer.options['query'] = query
layer.save
# INFO: send :calculate_vizjson won't use cache
v2_vizjson = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata).send(:calculate_vizjson)
nm_vizjson = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata).send(:calculate_vizjson, for_named_map: true)
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send(:calculate_vizjson)
v2_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:sql].should eq query
v2_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:source].should be_nil
nm_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:sql].should eq query
nm_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:source].should be_nil
v3_vizjson[:layers][1][:options][:sql].should eq query
v3_vizjson[:layers][1][:options][:source].should be_nil
source = 'a1'
layer.options['source'] = source
layer.save
@visualization.reload
v2_vizjson = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata).send(:calculate_vizjson)
nm_vizjson = Carto::Api::VizJSONPresenter.new(@visualization, $tables_metadata).send(:calculate_vizjson, for_named_map: true)
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send(:calculate_vizjson)
v2_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:sql].should eq query
v2_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:source].should be_nil
nm_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:sql].should be_nil
nm_vizjson[:layers][1][:options][:layer_definition][:layers][0][:options][:source].should eq(id: source)
v3_vizjson[:layers][1][:options][:sql].should be_nil
v3_vizjson[:layers][1][:options][:source].should eq source
end
end
describe 'anonymous_vizjson' do
include_context 'full visualization'
it 'v3 should include sql_wrap' do
v3_vizjson = Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user).send(:calculate_vizjson)
v3_vizjson[:layers][1][:options][:sql_wrap].should eq "select * from (<%= sql %>) __wrap"
end
end
describe 'layers' do
include_context 'full visualization'
before(:all) do
@data_layer = @map.data_layers.first
@data_layer.options[:attribution] = 'CARTO attribution'
@data_layer.save
@torque_layer = FactoryGirl.create(:carto_layer, kind: 'torque', maps: [@map])
@torque_layer.options[:table_name] = 'wadus'
@torque_layer.save
@visualization.reload
end
shared_examples 'common layer checks' do
it 'should not include layergroup layers' do
vizjson[:layers].map { |l| l[:type] }.should_not include 'layergroup'
end
it 'should not include namedmap layers' do
vizjson[:layers].map { |l| l[:type] }.should_not include 'namedmap'
end
it 'should have exactly three layers: tiled, CartoDB and torque' do
vizjson[:layers].map { |l| l[:type] }.should eq %w(tiled CartoDB torque)
end
it 'should include attribution for all layers' do
vizjson[:layers].each { |l| l[:options].should include :attribution }
end
it 'should not include named map options in any layer' do
vizjson[:layers].each do |l|
options = l[:options]
options.should_not include :stat_tag
options.should_not include :maps_api_template
options.should_not include :sql_api_template
options.should_not include :named_map
end
end
it 'should not include interactivity in any layer' do
vizjson[:layers].each do |l|
l.should_not include :interactivity
l[:options].should_not include :interactivity
end
end
it 'should not include infowindow nor tooltip in basemaps' do
vizjson[:layers].each do |l|
if l[:type] == 'tiled'
l.should_not include :infowindow
l.should_not include :tooltip
end
end
end
it 'should not include order in any layer' do
vizjson[:layers].each do |l|
l.should_not include :order
end
end
it 'should include layer_name in options for data layers' do
vizjson[:layers].each do |layer|
unless layer[:type] == 'tiled'
layer.should_not include :layer_name
layer[:options][:layer_name].should be
end
end
end
it 'should not include Odyssey options' do
vizjson.should_not include :prev
vizjson.should_not include :next
vizjson.should_not include :transition_options
end
end
describe 'in namedmap vizjson' do
let(:vizjson) do
Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user)
.send(:calculate_vizjson, forced_privacy_version: :force_named)
end
include_examples 'common layer checks'
it 'should not include sql field in data layers' do
data_layer_options = vizjson[:layers][1][:options]
data_layer_options.should_not include :sql
end
it 'should include cartocss but not sql in torque layers' do
torque_layer = vizjson[:layers][2]
torque_layer.should_not include :sql
torque_layer[:cartocss].should be
torque_layer[:cartocss_version].should be
end
end
describe 'in anonymous vizjson' do
let(:vizjson) do
Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user)
.send(:calculate_vizjson, forced_privacy_version: :force_anonymous)
end
include_examples 'common layer checks'
it 'should include sql and cartocss fields in data layers' do
data_layer_options = vizjson[:layers][1][:options]
data_layer_options[:sql].should be
data_layer_options[:cartocss].should be
data_layer_options[:cartocss_version].should be
end
it 'should include sql and cartocss fields in torque layers' do
torque_layer = vizjson[:layers][2]
torque_layer[:sql].should be
torque_layer[:cartocss].should be
torque_layer[:cartocss_version].should be
end
end
describe 'overlays' do
include_context 'full visualization'
def vizjson
Carto::Api::VizJSON3Presenter.new(@visualization, viewer_user)
.send(:calculate_vizjson, forced_privacy_version: :force_anonymous)
end
it 'enables map layer_selector option if there is a layer_selector overlay' do
vizjson[:options]['layer_selector'].should eq false
@visualization.overlays << Carto::Overlay.new(type: 'layer_selector')
vizjson[:options]['layer_selector'].should eq true
end
it 'removes layer selector overlay ' do
@visualization.overlays << Carto::Overlay.new(type: 'layer_selector')
vizjson[:overlays].any? { |o| o[:type] == 'layer_selector' }.should be_false
end
end
end
end