<commit_before>require 'spec_helper'

# TODO change some of these tests to use Rack::Test

describe Split::Helper do
  include Split::Helper

  let(:experiment) {
    Split::Experiment.find_or_create('link_color', 'blue', 'red')
  }

  describe "ab_test" do

    it "should not raise an error when passed strings for alternatives" do
      lambda { ab_test('xyz', '1', '2', '3') }.should_not raise_error
    end

    it "should raise the appropriate error when passed integers for alternatives" do
      lambda { ab_test('xyz', 1, 2, 3) }.should raise_error(ArgumentError)
    end

    it "should raise the appropriate error when passed symbols for alternatives" do
      lambda { ab_test('xyz', :a, :b, :c) }.should raise_error(ArgumentError)
    end

    it "should not raise error when passed an array for goals" do
      lambda { ab_test({'link_color' => ["purchase", "refund"]}, 'blue', 'red') }.should_not raise_error
    end

    it "should raise the appropriate error when passed string for goals" do
      lambda { ab_test({'link_color' => "purchase"}, 'blue', 'red') }.should raise_error(ArgumentError)
    end

    it "should assign a random alternative to a new user when there are an equal number of alternatives assigned" do
      ab_test('link_color', 'blue', 'red')
      ['red', 'blue'].should include(ab_user['link_color'])
    end

    it "should increment the participation counter after assignment to a new user" do

      previous_red_count = Split::Alternative.new('red', 'link_color').participant_count
      previous_blue_count = Split::Alternative.new('blue', 'link_color').participant_count

      ab_test('link_color', 'blue', 'red')

      new_red_count = Split::Alternative.new('red', 'link_color').participant_count
      new_blue_count = Split::Alternative.new('blue', 'link_color').participant_count

      (new_red_count + new_blue_count).should eql(previous_red_count + previous_blue_count + 1)
    end

    it "should return the given alternative for an existing user" do
      alternative = ab_test('link_color', 'blue', 'red')
      repeat_alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql repeat_alternative
    end

    it 'should always return the winner if one is present' do
      experiment.winner = "orange"

      ab_test('link_color', 'blue', 'red').should == 'orange'
    end

    it "should allow the alternative to be force by passing it in the params" do
      @params = {'link_color' => 'blue'}
      alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql('blue')
      alternative = ab_test('link_color', {'blue' => 1}, 'red' => 5)
      alternative.should eql('blue')
      @params = {'link_color' => 'red'}
      alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql('red')
      alternative = ab_test('link_color', {'blue' => 5}, 'red' => 1)
      alternative.should eql('red')
    end

    it "should allow passing a block" do
      alt = ab_test('link_color', 'blue', 'red')
      ret = ab_test('link_color', 'blue', 'red') { |alternative| "shared/#{alternative}" }
      ret.should eql("shared/#{alt}")
    end

    it "should allow the share of visitors see an alternative to be specificed" do
      ab_test('link_color', {'blue' => 0.8}, {'red' => 20})
      ['red', 'blue'].should include(ab_user['link_color'])
    end

    it "should allow alternative weighting interface as a single hash" do
      ab_test('link_color', {'blue' => 0.01}, 'red' => 0.2)
      experiment = Split::Experiment.find('link_color')
      experiment.alternatives.map(&:name).should eql(['blue', 'red'])
      # TODO: persist alternative weights
      # experiment.alternatives.collect{|a| a.weight}.should == [0.01, 0.2]
    end

    it "should only let a user participate in one experiment at a time" do
      link_color = ab_test('link_color', 'blue', 'red')
      ab_test('button_size', 'small', 'big')
      ab_user.should eql({'link_color' => link_color})
      big = Split::Alternative.new('big', 'button_size')
      big.participant_count.should eql(0)
      small = Split::Alternative.new('small', 'button_size')
      small.participant_count.should eql(0)
    end

    it 'should not raise the completion rate of an experiment that the user is not participating in' do
      ab_test('link_color', 'blue', 'red')
      ab_test('button_size', 'small', 'big')

      # So, user should be participating in the link_color experiment and
      # receive the control for button_size. As the user is not participating in
      # the button size experiment, finishing it should not increase the
      # completion count for that alternative.
      ab_user['button_size'].should eql('small')
      previous_completion_count = Split::Alternative.new('small', 'button_size').completed_count

      finished('button_size')

      new_completion_count = Split::Alternative.new('small', 'button_size').completed_count
      previous_completion_count.should eql(new_completion_count)
    end

    it "should let a user participate in many experiment with allow_multiple_experiments option" do
      Split.configure do |config|
        config.allow_multiple_experiments = true
      end
      link_color = ab_test('link_color', 'blue', 'red')
      button_size = ab_test('button_size', 'small', 'big')
      ab_user.should eql({'link_color' => link_color, 'button_size' => button_size})
      button_size_alt = Split::Alternative.new(button_size, 'button_size')
      button_size_alt.participant_count.should eql(1)
    end

    it "should not over-write a finished key when an experiment is on a later version" do
      experiment.increment_version
      ab_user = { experiment.key => 'blue', experiment.finished_key => true }
      finshed_session = ab_user.dup
      ab_test('link_color', 'blue', 'red')
      ab_user.should eql(finshed_session)
    end<commit_msg>Update and clean completions test<commit_after>require 'spec_helper'

# TODO change some of these tests to use Rack::Test

describe Split::Helper do
  include Split::Helper

  let(:experiment) {
    Split::Experiment.find_or_create('link_color', 'blue', 'red')
  }

  describe "ab_test" do

    it "should not raise an error when passed strings for alternatives" do
      lambda { ab_test('xyz', '1', '2', '3') }.should_not raise_error
    end

    it "should raise the appropriate error when passed integers for alternatives" do
      lambda { ab_test('xyz', 1, 2, 3) }.should raise_error(ArgumentError)
    end

    it "should raise the appropriate error when passed symbols for alternatives" do
      lambda { ab_test('xyz', :a, :b, :c) }.should raise_error(ArgumentError)
    end

    it "should not raise error when passed an array for goals" do
      lambda { ab_test({'link_color' => ["purchase", "refund"]}, 'blue', 'red') }.should_not raise_error
    end

    it "should raise the appropriate error when passed string for goals" do
      lambda { ab_test({'link_color' => "purchase"}, 'blue', 'red') }.should raise_error(ArgumentError)
    end

    it "should assign a random alternative to a new user when there are an equal number of alternatives assigned" do
      ab_test('link_color', 'blue', 'red')
      ['red', 'blue'].should include(ab_user['link_color'])
    end

    it "should increment the participation counter after assignment to a new user" do

      previous_red_count = Split::Alternative.new('red', 'link_color').participant_count
      previous_blue_count = Split::Alternative.new('blue', 'link_color').participant_count

      ab_test('link_color', 'blue', 'red')

      new_red_count = Split::Alternative.new('red', 'link_color').participant_count
      new_blue_count = Split::Alternative.new('blue', 'link_color').participant_count

      (new_red_count + new_blue_count).should eql(previous_red_count + previous_blue_count + 1)
    end

    it "should return the given alternative for an existing user" do
      alternative = ab_test('link_color', 'blue', 'red')
      repeat_alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql repeat_alternative
    end

    it 'should always return the winner if one is present' do
      experiment.winner = "orange"

      ab_test('link_color', 'blue', 'red').should == 'orange'
    end

    it "should allow the alternative to be force by passing it in the params" do
      @params = {'link_color' => 'blue'}
      alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql('blue')
      alternative = ab_test('link_color', {'blue' => 1}, 'red' => 5)
      alternative.should eql('blue')
      @params = {'link_color' => 'red'}
      alternative = ab_test('link_color', 'blue', 'red')
      alternative.should eql('red')
      alternative = ab_test('link_color', {'blue' => 5}, 'red' => 1)
      alternative.should eql('red')
    end

    it "should allow passing a block" do
      alt = ab_test('link_color', 'blue', 'red')
      ret = ab_test('link_color', 'blue', 'red') { |alternative| "shared/#{alternative}" }
      ret.should eql("shared/#{alt}")
    end

    it "should allow the share of visitors see an alternative to be specificed" do
      ab_test('link_color', {'blue' => 0.8}, {'red' => 20})
      ['red', 'blue'].should include(ab_user['link_color'])
    end

    it "should allow alternative weighting interface as a single hash" do
      ab_test('link_color', {'blue' => 0.01}, 'red' => 0.2)
      experiment = Split::Experiment.find('link_color')
      experiment.alternatives.map(&:name).should eql(['blue', 'red'])
      # TODO: persist alternative weights
      # experiment.alternatives.collect{|a| a.weight}.should == [0.01, 0.2]
    end

    it "should only let a user participate in one experiment at a time" do
      link_color = ab_test('link_color', 'blue', 'red')
      ab_test('button_size', 'small', 'big')
      ab_user.should eql({'link_color' => link_color})
      big = Split::Alternative.new('big', 'button_size')
      big.participant_count.should eql(0)
      small = Split::Alternative.new('small', 'button_size')
      small.participant_count.should eql(0)
    end

    it 'should not raise the completion rate of an experiment that the user is not participating in' do
      ab_test('link_color', 'blue', 'red')
      ab_test('button_size', 'small', 'big')

      # So, user should be participating in the link_color experiment and
      # receive the control for button_size. As the user is not participating in
      # the button size experiment, finishing it should not increase the
      # completion count for that alternative.
      lambda {
        finished('button_size')
      }.should_not change { Split::Alternative.new('small', 'button_size').completed_count }

    end

    it "should let a user participate in many experiment with allow_multiple_experiments option" do
      Split.configure do |config|
        config.allow_multiple_experiments = true
      end
      link_color = ab_test('link_color', 'blue', 'red')
      button_size = ab_test('button_size', 'small', 'big')
      ab_user.should eql({'link_color' => link_color, 'button_size' => button_size})
      button_size_alt = Split::Alternative.new(button_size, 'button_size')
      button_size_alt.participant_count.should eql(1)
    end

    it "should not over-write a finished key when an experiment is on a later version" do
      experiment.increment_version
      ab_user = { experiment.key => 'blue', experiment.finished_key => true }
      finshed_session = ab_user.dup
      ab_test('link_color', 'blue', 'red')
      ab_user.should eql(finshed_session)
    end
{'fraction_non_alphanumeric': 0.12374870555747325, 'fraction_numerical': 0.004832585433206766, 'mean_word_length': 3.6560867818400964, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 37, 'https://': 0, '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': '3784490', 'n_tokens_mistral': 3573, 'n_tokens_neox': 3433, 'n_words': 1048}