306 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			8.7 KiB
		
	
	
	
		
			Ruby
		
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
require 'spec_helper'
 | 
						|
 | 
						|
describe Gitlab::Experimentation do
 | 
						|
  before do
 | 
						|
    stub_const('Gitlab::Experimentation::EXPERIMENTS', {
 | 
						|
      test_experiment: {
 | 
						|
        feature_toggle: feature_toggle,
 | 
						|
        environment: environment,
 | 
						|
        enabled_ratio: enabled_ratio,
 | 
						|
        tracking_category: 'Team'
 | 
						|
      }
 | 
						|
    })
 | 
						|
 | 
						|
    stub_feature_flags(feature_toggle => true)
 | 
						|
  end
 | 
						|
 | 
						|
  let(:feature_toggle) { :test_experiment_toggle }
 | 
						|
  let(:environment) { Rails.env.test? }
 | 
						|
  let(:enabled_ratio) { 0.1 }
 | 
						|
 | 
						|
  describe Gitlab::Experimentation::ControllerConcern, type: :controller do
 | 
						|
    controller(ApplicationController) do
 | 
						|
      include Gitlab::Experimentation::ControllerConcern
 | 
						|
 | 
						|
      def index
 | 
						|
        head :ok
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe '#set_experimentation_subject_id_cookie' do
 | 
						|
      before do
 | 
						|
        get :index
 | 
						|
      end
 | 
						|
 | 
						|
      context 'cookie is present' do
 | 
						|
        before do
 | 
						|
          cookies[:experimentation_subject_id] = 'test'
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not change the cookie' do
 | 
						|
          expect(cookies[:experimentation_subject_id]).to eq 'test'
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'cookie is not present' do
 | 
						|
        it 'sets a permanent signed cookie' do
 | 
						|
          expect(cookies.permanent.signed[:experimentation_subject_id]).to be_present
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe '#experiment_enabled?' do
 | 
						|
      context 'cookie is not present' do
 | 
						|
        it 'calls Gitlab::Experimentation.enabled_for_user? with the name of the experiment and an experimentation_subject_index of nil' do
 | 
						|
          expect(Gitlab::Experimentation).to receive(:enabled_for_user?).with(:test_experiment, nil)
 | 
						|
          controller.experiment_enabled?(:test_experiment)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'cookie is present' do
 | 
						|
        before do
 | 
						|
          cookies.permanent.signed[:experimentation_subject_id] = 'abcd-1234'
 | 
						|
          get :index
 | 
						|
        end
 | 
						|
 | 
						|
        it 'calls Gitlab::Experimentation.enabled_for_user? with the name of the experiment and an experimentation_subject_index of the modulo 100 of the hex value of the uuid' do
 | 
						|
          # 'abcd1234'.hex % 100 = 76
 | 
						|
          expect(Gitlab::Experimentation).to receive(:enabled_for_user?).with(:test_experiment, 76)
 | 
						|
          controller.experiment_enabled?(:test_experiment)
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      describe 'URL parameter to force enable experiment' do
 | 
						|
        it 'returns true' do
 | 
						|
          get :index, params: { force_experiment: :test_experiment }
 | 
						|
 | 
						|
          expect(controller.experiment_enabled?(:test_experiment)).to be_truthy
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe '#track_experiment_event' do
 | 
						|
      context 'when the experiment is enabled' do
 | 
						|
        before do
 | 
						|
          stub_experiment(test_experiment: true)
 | 
						|
        end
 | 
						|
 | 
						|
        context 'the user is part of the experimental group' do
 | 
						|
          before do
 | 
						|
            stub_experiment_for_user(test_experiment: true)
 | 
						|
          end
 | 
						|
 | 
						|
          it 'tracks the event with the right parameters' do
 | 
						|
            expect(Gitlab::Tracking).to receive(:event).with(
 | 
						|
              'Team',
 | 
						|
              'start',
 | 
						|
              property: 'experimental_group',
 | 
						|
              value: 'team_id'
 | 
						|
            )
 | 
						|
            controller.track_experiment_event(:test_experiment, 'start', 'team_id')
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context 'the user is part of the control group' do
 | 
						|
          before do
 | 
						|
            stub_experiment_for_user(test_experiment: false)
 | 
						|
          end
 | 
						|
 | 
						|
          it 'tracks the event with the right parameters' do
 | 
						|
            expect(Gitlab::Tracking).to receive(:event).with(
 | 
						|
              'Team',
 | 
						|
              'start',
 | 
						|
              property: 'control_group',
 | 
						|
              value: 'team_id'
 | 
						|
            )
 | 
						|
            controller.track_experiment_event(:test_experiment, 'start', 'team_id')
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when the experiment is disabled' do
 | 
						|
        before do
 | 
						|
          stub_experiment(test_experiment: false)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not track the event' do
 | 
						|
          expect(Gitlab::Tracking).not_to receive(:event)
 | 
						|
          controller.track_experiment_event(:test_experiment, 'start')
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe '#frontend_experimentation_tracking_data' do
 | 
						|
      context 'when the experiment is enabled' do
 | 
						|
        before do
 | 
						|
          stub_experiment(test_experiment: true)
 | 
						|
        end
 | 
						|
 | 
						|
        context 'the user is part of the experimental group' do
 | 
						|
          before do
 | 
						|
            stub_experiment_for_user(test_experiment: true)
 | 
						|
          end
 | 
						|
 | 
						|
          it 'pushes the right parameters to gon' do
 | 
						|
            controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
 | 
						|
            expect(Gon.tracking_data).to eq(
 | 
						|
              {
 | 
						|
                category: 'Team',
 | 
						|
                action: 'start',
 | 
						|
                property: 'experimental_group',
 | 
						|
                value: 'team_id'
 | 
						|
              }
 | 
						|
            )
 | 
						|
          end
 | 
						|
        end
 | 
						|
 | 
						|
        context 'the user is part of the control group' do
 | 
						|
          before do
 | 
						|
            allow_next_instance_of(described_class) do |instance|
 | 
						|
              allow(instance).to receive(:experiment_enabled?).with(:test_experiment).and_return(false)
 | 
						|
            end
 | 
						|
          end
 | 
						|
 | 
						|
          it 'pushes the right parameters to gon' do
 | 
						|
            controller.frontend_experimentation_tracking_data(:test_experiment, 'start', 'team_id')
 | 
						|
            expect(Gon.tracking_data).to eq(
 | 
						|
              {
 | 
						|
                category: 'Team',
 | 
						|
                action: 'start',
 | 
						|
                property: 'control_group',
 | 
						|
                value: 'team_id'
 | 
						|
              }
 | 
						|
            )
 | 
						|
          end
 | 
						|
 | 
						|
          it 'does not send nil value to gon' do
 | 
						|
            controller.frontend_experimentation_tracking_data(:test_experiment, 'start')
 | 
						|
            expect(Gon.tracking_data).to eq(
 | 
						|
              {
 | 
						|
                category: 'Team',
 | 
						|
                action: 'start',
 | 
						|
                property: 'control_group'
 | 
						|
              }
 | 
						|
            )
 | 
						|
          end
 | 
						|
        end
 | 
						|
      end
 | 
						|
 | 
						|
      context 'when the experiment is disabled' do
 | 
						|
        before do
 | 
						|
          stub_experiment(test_experiment: false)
 | 
						|
        end
 | 
						|
 | 
						|
        it 'does not push data to gon' do
 | 
						|
          expect(Gon.method_defined?(:tracking_data)).to be_falsey
 | 
						|
          controller.track_experiment_event(:test_experiment, 'start')
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '.enabled?' do
 | 
						|
    subject { described_class.enabled?(:test_experiment) }
 | 
						|
 | 
						|
    context 'feature toggle is enabled, we are on the right environment and we are selected' do
 | 
						|
      it { is_expected.to be_truthy }
 | 
						|
    end
 | 
						|
 | 
						|
    describe 'experiment is not defined' do
 | 
						|
      it 'returns false' do
 | 
						|
        expect(described_class.enabled?(:missing_experiment)).to be_falsey
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe 'feature toggle' do
 | 
						|
      context 'feature toggle is not set' do
 | 
						|
        let(:feature_toggle) { nil }
 | 
						|
 | 
						|
        it { is_expected.to be_truthy }
 | 
						|
      end
 | 
						|
 | 
						|
      context 'feature toggle is not set, but a feature with the experiment key as name does exist' do
 | 
						|
        before do
 | 
						|
          stub_feature_flags(test_experiment: false)
 | 
						|
        end
 | 
						|
 | 
						|
        let(:feature_toggle) { nil }
 | 
						|
 | 
						|
        it { is_expected.to be_falsey }
 | 
						|
      end
 | 
						|
 | 
						|
      context 'feature toggle is disabled' do
 | 
						|
        before do
 | 
						|
          stub_feature_flags(feature_toggle => false)
 | 
						|
        end
 | 
						|
 | 
						|
        it { is_expected.to be_falsey }
 | 
						|
      end
 | 
						|
    end
 | 
						|
 | 
						|
    describe 'environment' do
 | 
						|
      context 'environment is not set' do
 | 
						|
        let(:environment) { nil }
 | 
						|
 | 
						|
        it { is_expected.to be_truthy }
 | 
						|
      end
 | 
						|
 | 
						|
      context 'we are on the wrong environment' do
 | 
						|
        let(:environment) { ::Gitlab.com? }
 | 
						|
 | 
						|
        it { is_expected.to be_falsey }
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  describe '.enabled_for_user?' do
 | 
						|
    subject { described_class.enabled_for_user?(:test_experiment, experimentation_subject_index) }
 | 
						|
 | 
						|
    let(:experimentation_subject_index) { 9 }
 | 
						|
 | 
						|
    context 'experiment is disabled' do
 | 
						|
      before do
 | 
						|
        allow(described_class).to receive(:enabled?).and_return(false)
 | 
						|
      end
 | 
						|
 | 
						|
      it { is_expected.to be_falsey }
 | 
						|
    end
 | 
						|
 | 
						|
    context 'experiment is enabled' do
 | 
						|
      before do
 | 
						|
        allow(described_class).to receive(:enabled?).and_return(true)
 | 
						|
      end
 | 
						|
 | 
						|
      it { is_expected.to be_truthy }
 | 
						|
 | 
						|
      context 'enabled ratio is not set' do
 | 
						|
        let(:enabled_ratio) { nil }
 | 
						|
 | 
						|
        it { is_expected.to be_falsey }
 | 
						|
      end
 | 
						|
 | 
						|
      describe 'experimentation_subject_index' do
 | 
						|
        context 'experimentation_subject_index is not set' do
 | 
						|
          let(:experimentation_subject_index) { nil }
 | 
						|
 | 
						|
          it { is_expected.to be_falsey }
 | 
						|
        end
 | 
						|
 | 
						|
        context 'experimentation_subject_index is an empty string' do
 | 
						|
          let(:experimentation_subject_index) { '' }
 | 
						|
 | 
						|
          it { is_expected.to be_falsey }
 | 
						|
        end
 | 
						|
 | 
						|
        context 'experimentation_subject_index outside enabled ratio' do
 | 
						|
          let(:experimentation_subject_index) { 11 }
 | 
						|
 | 
						|
          it { is_expected.to be_falsey }
 | 
						|
        end
 | 
						|
      end
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |