<commit_before># encoding: utf-8
require_relative '../../spec_helper'
require_relative '../../../services/data-repository/backend/sequel'
require_relative '../../../app/models/visualization/member'
require_relative '../../../app/models/visualization/collection'
require_relative '../../../app/models/visualization/migrator'
require_relative '../../../services/data-repository/repository'
require_relative '../../doubles/support_tables.rb'

include CartoDB

describe Visualization::Member do
  before do
    @db = Rails::Sequel.connection
    Sequel.extension(:pagination)

    Visualization.repository  = DataRepository::Backend::Sequel.new(@db, :visualizations)
    Overlay.repository        = DataRepository.new # In-memory storage
  end

  before(:each) do
    CartoDB::NamedMapsWrapper::NamedMaps.any_instance.stubs(:get => nil, :create => true, :update => true)

    # For relator->permission
    user_id = UUIDTools::UUID.timestamp_create.to_s
    user_name = 'whatever'
    user_apikey = '123'
    @user_mock = mock
    @user_mock.stubs(:id).returns(user_id)
    @user_mock.stubs(:username).returns(user_name)
    @user_mock.stubs(:api_key).returns(user_apikey)
    CartoDB::Visualization::Relator.any_instance.stubs(:user).returns(@user_mock)

    support_tables_mock = Doubles::Visualization::SupportTables.new
    Visualization::Relator.any_instance.stubs(:support_tables).returns(support_tables_mock)
  end

  describe '#initialize' do
    it 'assigns an id by default' do
      member = Visualization::Member.new
      member.should be_an_instance_of Visualization::Member
      member.id.should_not be_nil
    end
  end #initialize

  describe '#store' do

    it 'should fail if no user_id attribute present' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      attributes.delete(:user_id)
      member      = Visualization::Member.new(attributes)
      expect {
        member.store
      }.to raise_exception CartoDB::InvalidMember
    end

    it 'persists attributes to the data repository' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      member      = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.name.should be_nil

      member.fetch
      member.name             .should == attributes.fetch(:name)
      member.active_layer_id  .should == attributes.fetch(:active_layer_id)
      member.privacy          .should == attributes.fetch(:privacy)

      member.permission.should_not be nil
      member.permission.owner_id.should eq @user_mock.id
      member.permission.owner_username.should eq @user_mock.username
    end

    it 'persists tags as an array if the backend supports it' do
      relation_id = UUIDTools::UUID.timestamp_create.to_s

      Permission.any_instance.stubs(:update_shared_entities).returns(nil)

      db_config   = Rails.configuration.database_configuration[Rails.env]
      # Why not passing db_config directly to Sequel.postgres here ?
      # See https://github.com/CartoDB/cartodb/issues/421
      db          = Sequel.postgres(
                      host:     db_config.fetch('host'),
                      port:     db_config.fetch('port'),
                      database: db_config.fetch('database'),
                      username: db_config.fetch('username')
                    )
      relation    = "visualizations_#{relation_id}".to_sym
      repository  = DataRepository::Backend::Sequel.new(db, relation)
      Visualization::Migrator.new(db).migrate(relation)
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', 'tag 2'])
      member      = Visualization::Member.new(attributes, repository)
      member.store

      member      = Visualization::Member.new({ id: member.id }, repository)
      member.fetch
      member.tags.should include('tag 1')
      member.tags.should include('tag 2')

      Visualization::Migrator.new(db).drop(relation)
    end

    it 'persists tags as JSON if the backend does not support arrays' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', 'tag 2'])
      member      = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.fetch
      member.tags.should include('tag 1')
      member.tags.should include('tag 2')
    end

    it 'prevents empty tags from being created' do
      attributes = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', '', '   '])
      member = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.fetch
      member.tags.should eq ['tag 1']
    end

    it 'invalidates vizjson cache in varnish if name changed' do
      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      CartoDB::Visualization::NameChecker.any_instance.stubs(:available?).returns(true)

      member = Visualization::Member.new(id: member.id).fetch
      @user_mock.expects(:invalidate_varnish_cache)
      member.name = 'changed'
      member.store
    end

    it 'invalidates vizjson cache in varnish if privacy changed' do
      # Need to at least have this decorated in the user data or checks before becoming private will raise an error
      CartoDB::Visualization::Member.any_instance.stubs(:supports_private_maps?).returns(true)

      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      member = Visualization::Member.new(id: member.id).fetch
      @user_mock.expects(:invalidate_varnish_cache)
      member.privacy = Visualization::Member::PRIVACY_PRIVATE
      member.store
    end

    it 'invalidates vizjson cache in varnish if description changed' do
      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      member = Visualization::Member.new(id: member.id).fetch
      @user_mock.expects(:invalidate_varnish_cache)
      member.description = 'changed description'
      member.store
    end
  end #store

  describe '#fetch' do
    it 'fetches attributes from the data repository' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      member      = Visualization::Member.new(attributes).store
      member      = Visualization::Member.new(id: member.id)
      member.name = 'changed'
      member.fetch
      member.name.should == attributes.fetch(:name)
    end
  end #fetch

  describe '#delete' do
    it 'deletes this member data from the data repository' do
      CartoDB::Visualization::Relator.any_instance.stubs(:children).returns([])<commit_msg>#4008 spec stabilization<commit_after># encoding: utf-8
require_relative '../../spec_helper'
require_relative '../../../services/data-repository/backend/sequel'
require_relative '../../../app/models/visualization/member'
require_relative '../../../app/models/visualization/collection'
require_relative '../../../app/models/visualization/migrator'
require_relative '../../../services/data-repository/repository'
require_relative '../../doubles/support_tables.rb'

include CartoDB

describe Visualization::Member do
  before do
    @db = Rails::Sequel.connection
    Sequel.extension(:pagination)

    Visualization.repository  = DataRepository::Backend::Sequel.new(@db, :visualizations)
    Overlay.repository        = DataRepository.new # In-memory storage
  end

  before(:each) do
    CartoDB::NamedMapsWrapper::NamedMaps.any_instance.stubs(:get => nil, :create => true, :update => true)

    # For relator->permission
    user_id = UUIDTools::UUID.timestamp_create.to_s
    user_name = 'whatever'
    user_apikey = '123'
    @user_mock = mock
    @user_mock.stubs(:id).returns(user_id)
    @user_mock.stubs(:username).returns(user_name)
    @user_mock.stubs(:api_key).returns(user_apikey)
    CartoDB::Visualization::Relator.any_instance.stubs(:user).returns(@user_mock)

    support_tables_mock = Doubles::Visualization::SupportTables.new
    Visualization::Relator.any_instance.stubs(:support_tables).returns(support_tables_mock)
  end

  describe '#initialize' do
    it 'assigns an id by default' do
      member = Visualization::Member.new
      member.should be_an_instance_of Visualization::Member
      member.id.should_not be_nil
    end
  end #initialize

  describe '#store' do

    it 'should fail if no user_id attribute present' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      attributes.delete(:user_id)
      member      = Visualization::Member.new(attributes)
      expect {
        member.store
      }.to raise_exception CartoDB::InvalidMember
    end

    it 'persists attributes to the data repository' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      member      = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.name.should be_nil

      member.fetch
      member.name             .should == attributes.fetch(:name)
      member.active_layer_id  .should == attributes.fetch(:active_layer_id)
      member.privacy          .should == attributes.fetch(:privacy)

      member.permission.should_not be nil
      member.permission.owner_id.should eq @user_mock.id
      member.permission.owner_username.should eq @user_mock.username
    end

    it 'persists tags as an array if the backend supports it' do
      relation_id = UUIDTools::UUID.timestamp_create.to_s

      Permission.any_instance.stubs(:update_shared_entities).returns(nil)

      db_config   = Rails.configuration.database_configuration[Rails.env]
      # Why not passing db_config directly to Sequel.postgres here ?
      # See https://github.com/CartoDB/cartodb/issues/421
      db          = Sequel.postgres(
                      host:     db_config.fetch('host'),
                      port:     db_config.fetch('port'),
                      database: db_config.fetch('database'),
                      username: db_config.fetch('username')
                    )
      relation    = "visualizations_#{relation_id}".to_sym
      repository  = DataRepository::Backend::Sequel.new(db, relation)
      Visualization::Migrator.new(db).migrate(relation)
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', 'tag 2'])
      member      = Visualization::Member.new(attributes, repository)
      member.store

      member      = Visualization::Member.new({ id: member.id }, repository)
      member.fetch
      member.tags.should include('tag 1')
      member.tags.should include('tag 2')

      Visualization::Migrator.new(db).drop(relation)
    end

    it 'persists tags as JSON if the backend does not support arrays' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', 'tag 2'])
      member      = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.fetch
      member.tags.should include('tag 1')
      member.tags.should include('tag 2')
    end

    it 'prevents empty tags from being created' do
      attributes = random_attributes_for_vis_member(user_id: @user_mock.id, tags: ['tag 1', '', '   '])
      member = Visualization::Member.new(attributes)
      member.store

      member = Visualization::Member.new(id: member.id)
      member.fetch
      member.tags.should eq ['tag 1']
    end

    it 'invalidates vizjson cache in varnish if name changed' do
      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      CartoDB::Visualization::NameChecker.any_instance.stubs(:available?).returns(true)

      member = Visualization::Member.new(id: member.id).fetch
      CartoDB::Varnish.any_instance.expects(:purge).with(member.varnish_vizzjson_key)
      member.name = 'changed'
      member.store
    end

    it 'invalidates vizjson cache in varnish if privacy changed' do
      # Need to at least have this decorated in the user data or checks before becoming private will raise an error
      CartoDB::Visualization::Member.any_instance.stubs(:supports_private_maps?).returns(true)

      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      member = Visualization::Member.new(id: member.id).fetch
      CartoDB::Varnish.any_instance.expects(:purge).with(member.varnish_vizzjson_key)
      member.privacy = Visualization::Member::PRIVACY_PRIVATE
      member.store
    end

    it 'invalidates vizjson cache in varnish if description changed' do
      member      = Visualization::Member.new(random_attributes_for_vis_member(user_id: @user_mock.id))
      member.store

      member = Visualization::Member.new(id: member.id).fetch
      CartoDB::Varnish.any_instance.expects(:purge).with(member.varnish_vizzjson_key)
      member.description = 'changed description'
      member.store
    end
  end #store

  describe '#fetch' do
    it 'fetches attributes from the data repository' do
      attributes  = random_attributes_for_vis_member(user_id: @user_mock.id)
      member      = Visualization::Member.new(attributes).store
      member      = Visualization::Member.new(id: member.id)
      member.name = 'changed'
      member.fetch
      member.name.should == attributes.fetch(:name)
    end
  end #fetch

  describe '#delete' do
    it 'deletes this member data from the data repository' do
      CartoDB::Visualization::Relator.any_instance.stubs(:children).returns([])
{'fraction_non_alphanumeric': 0.1083969465648855, 'fraction_numerical': 0.002762631770265358, 'mean_word_length': 3.2853582554517136, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4427813', 'n_tokens_mistral': 4095, 'n_tokens_neox': 3979, 'n_words': 813}