Commit 4ee0f178 authored by Alper Akgun's avatar Alper Akgun Committed by Illya Klymov

Expose a portion of users to new purchase flow

Only for free gitlab.com users for group billing we direct the owners
to the new paid signup flow
parent 49b8c8ad
......@@ -175,6 +175,10 @@ class Namespace < ApplicationRecord
kind == 'user'
end
def group?
type == 'Group'
end
def find_fork_of(project)
return unless project.fork_network
......
......@@ -23,9 +23,24 @@ const determineSelectedPlan = (planId, plans) => {
return plans[0] && plans[0].value;
};
const determineNumberOfUsers = (groupId, groups) => {
if (!groupId || !groups) {
return 1;
}
const chosenGroup = groups.find(group => group.value === groupId);
if (chosenGroup?.numberOfUsers > 1) {
return chosenGroup.numberOfUsers;
}
return 1;
};
export default ({
planData = '[]',
planId,
namespaceId,
setupForCompany,
fullName,
newUser,
......@@ -33,6 +48,8 @@ export default ({
}) => {
const availablePlans = parsePlanData(planData);
const isNewUser = parseBoolean(newUser);
const groupId = parseInt(namespaceId, 10) || null;
const groups = parseGroupData(groupData);
return {
currentStep: STEPS[0],
......@@ -41,10 +58,10 @@ export default ({
selectedPlan: determineSelectedPlan(planId, availablePlans),
isNewUser,
fullName,
groupData: parseGroupData(groupData),
selectedGroup: null,
groupData: groups,
selectedGroup: groupId,
organizationName: null,
numberOfUsers: 1,
numberOfUsers: determineNumberOfUsers(groupId, groups),
country: null,
streetAddressLine1: null,
streetAddressLine2: null,
......
......@@ -42,8 +42,18 @@ module BillingPlansHelper
"#{EE::SUBSCRIPTIONS_URL}/gitlab/namespaces/#{group.id}/upgrade/#{plan.id}"
end
def use_new_purchase_flow?(namespace)
namespace.group? &&
namespace.actual_plan_name == Plan::FREE &&
Feature.enabled?(:free_group_new_purchase_flow, current_user)
end
def plan_purchase_url(group, plan)
"#{plan.purchase_link.href}&gl_namespace_id=#{group.id}"
if use_new_purchase_flow?(group)
new_subscriptions_path(plan_id: plan.id, namespace_id: group.id)
else
"#{plan.purchase_link.href}&gl_namespace_id=#{group.id}"
end
end
def plan_feature_short_list(plan)
......
......@@ -9,6 +9,7 @@ module SubscriptionsHelper
full_name: current_user.name,
plan_data: plan_data.to_json,
plan_id: params[:plan_id],
namespace_id: params[:namespace_id],
new_user: new_user?.to_s,
group_data: group_data.to_json
}
......
......@@ -35,4 +35,5 @@
.card-footer.p-3
.pull-right{ class: ("invisible" unless purchase_link.action == 'upgrade' || is_current_plan) }
- upgrade_button_class = "disabled" if is_current_plan && !namespace.trial_active?
= link_to s_('BillingPlan|Upgrade'), plan_purchase_or_upgrade_url(namespace, plan, current_plan), class: "btn btn-success #{upgrade_button_class}"
- cta_class = '-new' if use_new_purchase_flow?(namespace)
= link_to s_('BillingPlan|Upgrade'), plan_purchase_or_upgrade_url(namespace, plan, current_plan), class: "btn btn-success #{upgrade_button_class} billing-cta-purchase#{cta_class}"
......@@ -19,6 +19,7 @@ describe('Order Summary', () => {
const initialData = {
planData: JSON.stringify(planData),
planId: 'thirdPlanId',
namespaceId: null,
fullName: 'Full Name',
};
......
......@@ -23,12 +23,16 @@ describe('Subscription Details', () => {
{ id: 483, name: 'My second group', users: 12 },
];
const initialData = {
planData: JSON.stringify(planData),
groupData: JSON.stringify(groupData),
planId: 'secondPlanId',
setupForCompany: 'true',
fullName: 'Full Name',
let initialNamespaceId = null;
const initialData = namespaceId => {
return {
planData: JSON.stringify(planData),
groupData: JSON.stringify(groupData),
planId: 'secondPlanId',
namespaceId,
setupForCompany: 'true',
fullName: 'Full Name',
};
};
const createComponent = () => {
......@@ -44,7 +48,7 @@ describe('Subscription Details', () => {
const companyLink = () => wrapper.find({ ref: 'company-link' });
beforeEach(() => {
store = createStore(initialData);
store = createStore(initialData(initialNamespaceId));
createComponent();
});
......@@ -191,6 +195,55 @@ describe('Subscription Details', () => {
});
});
describe('An existing user coming from group billing page', () => {
beforeEach(() => {
initialNamespaceId = '132';
store.state.isNewUser = false;
});
it('should not display an input field for the company or group name', () => {
expect(organizationNameInput().exists()).toBe(false);
});
it('should display the group select', () => {
expect(groupSelect().exists()).toBe(true);
});
it('should enable the number of users input field', () => {
expect(numberOfUsersInput().attributes('disabled')).toBeUndefined();
});
it('should set the min number of users to 3', () => {
expect(numberOfUsersInput().attributes('min')).toBe('3');
});
it('should set the selected group to initial namespace id', () => {
expect(groupSelect().element.value).toBe('132');
});
it('should not show a link to change to setting up for a company', () => {
expect(companyLink().exists()).toBe(false);
});
describe('selecting an existing group', () => {
beforeEach(() => {
store.commit(types.UPDATE_SELECTED_GROUP, 483);
});
it('should display the correct description', () => {
expect(wrapper.text()).toContain('Your subscription will be applied to this group');
});
it('should set the min number of users to 12', () => {
expect(numberOfUsersInput().attributes('min')).toBe('12');
});
it('should set the selected group to the user selected namespace id', () => {
expect(groupSelect().element.value).toBe('483');
});
});
});
describe('validations', () => {
const isStepValid = () => wrapper.find(Step).props('isValid');
......
......@@ -19,6 +19,7 @@ describe('projectsSelector default state', () => {
planData: JSON.stringify(planData),
groupData: JSON.stringify(groupData),
planId: 'secondPlanId',
namespaceId: null,
setupForCompany: 'true',
fullName: 'Full Name',
newUser: 'true',
......
......@@ -58,4 +58,33 @@ describe BillingPlansHelper do
end
end
end
describe '#use_new_purchase_flow?' do
using RSpec::Parameterized::TableSyntax
where free_group_new_purchase: [true, false],
type: ['Group', nil],
plan: Plan.all_plans
with_them do
let_it_be(:user) { create(:user) }
let(:namespace) do
create :namespace, type: type,
gitlab_subscription: create(:gitlab_subscription, hosted_plan: create("#{plan}_plan".to_sym))
end
before do
allow(helper).to receive(:current_user).and_return(user)
stub_feature_flags free_group_new_purchase_flow: free_group_new_purchase
end
subject { helper.use_new_purchase_flow?(namespace) }
it do
result = free_group_new_purchase && type == 'Group' && plan == Plan::FREE
is_expected.to be(result)
end
end
end
end
......@@ -22,7 +22,7 @@ describe SubscriptionsHelper do
end
before do
allow(helper).to receive(:params).and_return(plan_id: 'bronze_id')
allow(helper).to receive(:params).and_return(plan_id: 'bronze_id', namespace_id: nil)
allow_next_instance_of(FetchSubscriptionPlansService) do |instance|
allow(instance).to receive(:execute).and_return(raw_plan_data)
end
......@@ -33,6 +33,7 @@ describe SubscriptionsHelper do
let_it_be(:group) { create(:group, name: 'My Namespace') }
before do
allow(helper).to receive(:params).and_return(plan_id: 'bronze_id', namespace_id: group.id.to_s)
allow(helper).to receive(:current_user).and_return(user)
group.add_owner(user)
end
......@@ -43,6 +44,7 @@ describe SubscriptionsHelper do
it { is_expected.to include(full_name: 'First Last') }
it { is_expected.to include(plan_data: '[{"id":"bronze_id","code":"bronze","price_per_year":48.0}]') }
it { is_expected.to include(plan_id: 'bronze_id') }
it { is_expected.to include(namespace_id: group.id.to_s) }
it { is_expected.to include(group_data: %Q{[{"id":#{group.id},"name":"My Namespace","users":1}]}) }
describe 'new_user' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment