require 'spec_helper_min' require 'support/helpers' require 'factories/carto_visualizations' module Carto module Api describe Carto::Api::LegendsController do include Carto::Factories::Visualizations, HelperMethods let(:category_legend_payload) do { pre_html: "

Es acaso

", post_html: "

el mejor artista del mundo?

", title: "La verdad", type: "category", conf: { columns: ['manolo', 'escobar'] }, definition: {} } end let(:custom_legend_payload) do { pre_html: "

Es acaso

", post_html: "

el mejor artista del mundo?

", title: "La verdad", type: "custom", conf: { columns: ['manolo', 'escobar'] }, definition: { categories: [ { title: 'Manolo Escobar' }, { title: 'Manolo Escobar', color: '#fff' }, { title: 'Manolo Escobar', icon: 'super.png' }, { title: 'Manolo Escobar', icon: 'super.png', color: '#FFF' } ] } } end let(:bubble_legend_payload) do { pre_html: "

Es acaso

", post_html: "

el mejor artista del mundo?

", title: "La verdad", type: "bubble", conf: { columns: ['manolo', 'escobar'] }, definition: { color: '#fff' } } end let(:choropleth_legend_payload) do { pre_html: "

Es acaso

", post_html: "

el mejor artista del mundo?

", title: "La verdad", type: "choropleth", conf: { columns: ['manolo', 'escobar'] }, definition: { prefix: "123", suffix: "foo" } } end let(:custom_choropleth_legend_payload) do { pre_html: "

Es acaso

", post_html: "

el mejor artista del mundo?

", title: "La verdad", type: "custom_choropleth", conf: { columns: ['manolo', 'escobar'] }, definition: { prefix: "123", suffix: "foo", colors: [ { color: '#fff' }, { color: '#fabada' }, { color: '#CCC' } ] } } end let(:fake_uuid) { 'aaaaaaaa-0000-bbbb-1111-cccccccccccc' } before(:all) do @user = FactoryGirl.create(:carto_user) @intruder = FactoryGirl.create(:carto_user) @map, @table, @table_visualization, @visualization = create_full_visualization(@user) @layer = @visualization.data_layers.first end after(:all) do destroy_full_visualization(@map, @table, @table_visualization, @visualization) @user.destroy @intruder.destroy @layer = nil end before(:each) do bypass_named_maps end def legend_is_correct(legend) legend = legend.deep_symbolize_keys saved_legend = LegendPresenter.new(Legend.find(legend[:id])).to_hash pruned_legend = prune_legend(legend) pruned_saved_legend = prune_legend(saved_legend) legend_definition = legend[:definition].with_indifferent_access saved_legend_definition = saved_legend[:definition] .with_indifferent_access conf = legend[:conf].with_indifferent_access saved_conf = saved_legend[:conf].with_indifferent_access pruned_legend.should eq pruned_saved_legend legend_definition.should eq saved_legend_definition conf.should eq saved_conf end def prune_legend(legend) legend.except(:created_at, :updated_at, :definition, :conf) end describe '#create' do after(:each) { @layer.reload.legends.map(&:destroy) } def create_legend_url(user: @user, visualization: @visualization, layer: @layer) legends_url(user_domain: user.subdomain, visualization_id: visualization.id, layer_id: layer.id, api_key: user.api_key) end it 'should reject non visualization owners' do post_json create_legend_url(user: @intruder), {} do |response| response.status.should eq 403 end end it 'should reject non data layers' do base_layer = @visualization.layers.first post_json create_legend_url(layer: base_layer), custom_legend_payload do |response| response.status.should eq 422 response.body[:errors].should include("'#{base_layer.kind}' layers can't have legends") end end it 'should return a validation errors' do post_json create_legend_url, {} do |response| response.status.should eq 422 response.body[:errors].should_not be_nil end end describe 'with valid definitions' do after(:each) do post_json create_legend_url, @payload do |response| response.status.should eq 201 legend_is_correct(response.body) end end after(:all) do @payload = nil end it 'for category' do @payload = category_legend_payload end it 'for custom' do @payload = custom_legend_payload end it 'for bubble' do @payload = bubble_legend_payload end it 'for choropleth' do @payload = choropleth_legend_payload end it 'for custom_choropleth' do @payload = custom_choropleth_legend_payload end end describe 'with spammy definitions' do after(:each) do spammy_definition = @payload[:definition].merge(spam: 'hell') @payload[:definition] = spammy_definition post_json create_legend_url, @payload do |response| response.status.should eq 422 end end after(:all) do @payload = nil end it 'banned for category' do @payload = category_legend_payload end it 'banned for custom' do @payload = custom_legend_payload end it 'banned for bubble' do @payload = bubble_legend_payload end it 'banned for choropleth' do @payload = choropleth_legend_payload end it 'banned for custom_choropleth' do @payload = custom_choropleth_legend_payload end end describe 'with spammy conf' do after(:each) do spammy_definition = @payload[:conf].merge(spam: 'hell') @payload[:conf] = spammy_definition post_json create_legend_url, @payload do |response| response.status.should eq 422 end end after(:all) do @payload = nil end it 'banned for category' do @payload = category_legend_payload end it 'banned for custom' do @payload = custom_legend_payload end it 'banned for bubble' do @payload = bubble_legend_payload end it 'banned for choropleth' do @payload = choropleth_legend_payload end it 'banned for custom_choropleth' do @payload = custom_choropleth_legend_payload end end describe 'with wrong conf type' do after(:each) do @payload[:conf] = { columns: { not: 'an_array' } } post_json create_legend_url, @payload do |response| response.status.should eq 422 end end after(:all) do @payload = nil end it 'banned for category' do @payload = category_legend_payload end it 'banned for custom' do @payload = custom_legend_payload end it 'banned for bubble' do @payload = bubble_legend_payload end it 'banned for choropleth' do @payload = choropleth_legend_payload end it 'banned for custom_choropleth' do @payload = custom_choropleth_legend_payload end end describe 'with wrong conf columns type' do after(:each) do @payload[:conf] = ['manolo', 'escobar', 2] post_json create_legend_url, @payload do |response| response.status.should eq 422 end end after(:all) do @payload = nil end it 'banned for category' do @payload = category_legend_payload end it 'banned for custom' do @payload = custom_legend_payload end it 'banned for bubble' do @payload = bubble_legend_payload end it 'banned for choropleth' do @payload = choropleth_legend_payload end it 'banned for custom_choropleth' do @payload = custom_choropleth_legend_payload end end it 'handles bad layer_id' do url = legends_url(user_domain: @user.subdomain, visualization_id: @visualization.id, layer_id: fake_uuid, api_key: @user.api_key) post_json url, {} do |response| response.status.should eq 404 response.body[:errors].should include('Layer not found') end end it 'handles bad visualization_id' do url = legends_url(user_domain: @user.subdomain, visualization_id: fake_uuid, layer_id: @layer.id, api_key: @user.api_key) post_json url, {} do |response| response.status.should eq 404 response.body[:errors].should include('Visualization not found') end end describe 'multiple legends per layer' do it 'can create a color layer and a size layer' do post_json create_legend_url, category_legend_payload do |response| response.status.should eq 201 end post_json create_legend_url, bubble_legend_payload do |response| response.status.should eq 201 end end it 'cannot create two color layers' do post_json create_legend_url, category_legend_payload do |response| response.status.should eq 201 end post_json create_legend_url, custom_legend_payload do |response| response.status.should eq 422 response.body[:errors].should include('Only one color legend per layer allowed') end end it 'cannot create two size layers' do post_json create_legend_url, bubble_legend_payload do |response| response.status.should eq 201 end post_json create_legend_url, bubble_legend_payload do |response| response.status.should eq 422 response.body[:errors].should include('Only one size legend per layer allowed') end end end end describe '#show' do before (:all) { @legend = Legend.create!(custom_legend_payload.merge(layer_id: @layer.id)) } after (:all) { @legend.destroy } def show_legend_url(user: @user, visualization: @visualization, layer: @layer, legend: @legend) legend_url(user_domain: user.subdomain, visualization_id: visualization.id, layer_id: layer.id, id: legend.id, api_key: user.api_key) end it 'should show a legend' do get_json show_legend_url, {} do |response| response.status.should eq 200 legend_is_correct(response.body) end end it 'should not show a legend to others' do get_json show_legend_url(user: @intruder), {} do |response| response.status.should eq 403 end end it 'handles bad legend_id' do url = legend_url(user_domain: @user.subdomain, visualization_id: @visualization.id, layer_id: @layer.id, id: fake_uuid, api_key: @user.api_key) get_json url, {} do |response| response.status.should eq 404 response.body[:errors].should include('Legend not found') end end end describe '#update' do before (:all) { @legend = Legend.create!(custom_legend_payload.merge(layer_id: @layer.id)) } after (:all) { @legend.destroy } def update_legend_url(user: @user, visualization: @visualization, layer: @layer, legend: @legend) legend_url(user_domain: user.subdomain, visualization_id: visualization.id, layer_id: layer.id, id: legend.id, api_key: user.api_key) end it 'updates a legend' do custom_legend_payload[:definition][:html] = '

modified

' put_json update_legend_url, custom_legend_payload do |response| response.status.should eq 200 legend_is_correct(response.body) end end it 'updates a legend when max legends reached' do Legend.create!(bubble_legend_payload.merge(layer_id: @layer.id)) custom_legend_payload[:definition][:html] = '

modified

' put_json update_legend_url, custom_legend_payload do |response| response.status.should eq 200 legend_is_correct(response.body) end @layer.reload.legends.map(&:destroy) @legend = Legend.create!(custom_legend_payload.merge(layer_id: @layer.id)) end it 'should let others update a legend' do put_json update_legend_url(user: @intruder), {} do |response| response.status.should eq 403 end end it 'handles bad legend_id' do url = legend_url(user_domain: @user.subdomain, visualization_id: @visualization.id, layer_id: @layer.id, id: fake_uuid, api_key: @user.api_key) put_json url, {} do |response| response.status.should eq 404 response.body[:errors].should include('Legend not found') end end end describe '#index' do before(:all) do @layer.reload.legends.map(&:destroy) Legend.create!(custom_legend_payload.merge(layer_id: @layer.id)) Legend.create!(bubble_legend_payload.merge(layer_id: @layer.id)) end after(:all) do @layer.reload.legends.map(&:destroy) end def index_legend_url(user: @user, visualization: @visualization, layer: @layer) legends_url(user_domain: user.subdomain, visualization_id: visualization.id, layer_id: layer.id, api_key: user.api_key) end it 'indexes legends' do get_json index_legend_url, {} do |response| response.status.should eq 200 response.body.each do |legend| legend_is_correct(legend) end end end it 'should not index legends to others' do get_json index_legend_url(user: @intruder), {} do |response| response.status.should eq 403 end end end describe '#delete' do before (:each) { @legend = Legend.create!(custom_legend_payload.merge(layer_id: @layer.id)) } after (:each) { @legend.destroy } def delete_legend_url(user: @user, visualization: @visualization, layer: @layer, legend: @legend) legend_url(user_domain: user.subdomain, visualization_id: visualization.id, layer_id: layer.id, id: legend.id, api_key: user.api_key) end it 'should delete a legend' do delete_json delete_legend_url, {} do |response| response.status.should eq 204 response.body.should be_empty end Legend.exists?(@legend.id).should be_false end it 'should not delete another user\'s legend' do delete_json delete_legend_url(user: @intruder), {} do |response| response.status.should eq 403 end Legend.exists?(@legend.id).should be_true end it 'handles bad legend_id' do url = legend_url(user_domain: @user.subdomain, visualization_id: @visualization.id, layer_id: @layer.id, id: fake_uuid, api_key: @user.api_key) delete_json url, {} do |response| response.status.should eq 404 response.body[:errors].should include('Legend not found') end end end end end end