Commit eddabbbe authored by Angelo Gulina's avatar Angelo Gulina Committed by Markus Koller

Add CI Minutes flow success banner

Provide redirect after success
Add banner for successfull purchase
Use URL to describe product purchased
parent d6cdc4e6
# frozen_string_literal: true
class SubscriptionsController < ApplicationController
include InternalRedirect
layout 'checkout'
skip_before_action :authenticate_user!, only: [:new]
......@@ -62,16 +64,8 @@ class SubscriptionsController < ApplicationController
).execute
if response[:success]
plan_id, quantity = subscription_params.values_at(:plan_id, :quantity)
redirect_location = if params[:selected_group]
group_path(group, plan_id: plan_id, purchased_quantity: quantity)
else
edit_subscriptions_group_path(group.path, plan_id: plan_id, quantity: quantity, new_user: params[:new_user])
end
experiment(:force_company_trial, user: current_user).track(:create_subscription, namespace: group, user: current_user)
response[:data] = { location: redirect_location }
response[:data] = { location: redirect_location(group) }
end
render json: response[:data]
......@@ -79,6 +73,15 @@ class SubscriptionsController < ApplicationController
private
def redirect_location(group)
return safe_redirect_path(params[:redirect_after_success]) if params[:redirect_after_success]
plan_id, quantity = subscription_params.values_at(:plan_id, :quantity)
return group_path(group, plan_id: plan_id, purchased_quantity: quantity) if params[:selected_group]
edit_subscriptions_group_path(group.path, plan_id: plan_id, quantity: quantity, new_user: params[:new_user])
end
def customer_params
params.require(:customer).permit(:country, :address_1, :address_2, :city, :state, :zip_code, :company)
end
......
......@@ -105,6 +105,10 @@ module EE
group.licensed_feature_available?(:adjourned_deletion_for_projects_and_groups)
end
def show_product_purchase_success_alert?
!params[:purchased_product].blank?
end
private
def get_group_sidebar_links
......
......@@ -16,6 +16,12 @@ module SubscriptionsHelper
}
end
def buy_minutes_addon_data(group)
{
redirect_after_success: group_usage_quotas_path(group, purchased_product: _('CI minutes'))
}.merge(addon_data(group))
end
def addon_data(group)
{
group_data: [present_group(group)].to_json,
......
= render 'shared/global_alert',
title: _('Thanks for your purchase!'),
variant: :success,
close_button_data: { testid: 'close-product-purchase-success' } do
.gl-alert-body
= _('You have successfully purchased %{product}. You\'ll receive a receipt by mail.') % { product: product_name }
......@@ -2,6 +2,9 @@
- url_to_purchase_storage = purchase_storage_url if purchase_storage_link_enabled?(@group)
- other_storage_enabled = Feature.enabled?(:other_storage_tab, @group)
- if show_product_purchase_success_alert?
= render 'product_purchase_success_alert', product_name: params[:purchased_product]
%h3.page-title
= s_('UsageQuota|Usage Quotas')
......
- page_title _('Buy CI Minutes')
#js-buy-minutes{ data: addon_data(@group) }
#js-buy-minutes{ data: buy_minutes_addon_data(@group) }
......@@ -272,10 +272,13 @@ RSpec.describe SubscriptionsController do
{
selected_group: selected_group.id,
customer: { country: 'NL' },
subscription: { plan_id: 'x', quantity: 1, source: 'another_source' }
subscription: { plan_id: 'x', quantity: 1, source: 'another_source' },
redirect_after_success: redirect_after_success
}
end
let_it_be(:redirect_after_success) { nil }
context 'when the selected group is eligible for a new subscription' do
let_it_be(:selected_group) { create(:group) }
......@@ -311,6 +314,18 @@ RSpec.describe SubscriptionsController do
subject
end
context 'when having an explicit redirect' do
let_it_be(:redirect_after_success) { '/-/path/to/redirect' }
it { is_expected.to have_gitlab_http_status(:ok) }
it 'returns the provided redirect path as location' do
subject
expect(response.body).to eq({ location: redirect_after_success }.to_json)
end
end
end
context 'when the selected group is ineligible for a new subscription' do
......
......@@ -95,6 +95,20 @@ RSpec.describe 'Groups > Usage Quotas' do
end
end
context 'when successfully purchasing CI Minutes' do
let(:group) { create(:group, :with_build_minutes) }
let!(:project) { create(:project, namespace: group, shared_runners_enabled: true) }
it 'does show a banner' do
visit group_usage_quotas_path(group, purchased_product: 'CI minutes')
page.within('#content-body') do
expect(page).to have_content('Thanks for your purchase!')
expect(page).to have_content('You have successfully purchased CI minutes.')
end
end
end
context 'minutes under quota' do
let(:group) { create(:group, :with_not_used_build_minutes_limit) }
......@@ -162,7 +176,7 @@ RSpec.describe 'Groups > Usage Quotas' do
end
end
context 'when accesing root group' do
context 'when accessing root group' do
let!(:subgroup) { create(:group, parent: group) }
let!(:subproject) { create(:project, namespace: subgroup, shared_runners_enabled: true) }
......
......@@ -380,4 +380,26 @@ RSpec.describe GroupsHelper do
it { expect(helper.show_delayed_project_removal_setting?(group)).to be result }
end
end
describe '#show_product_purchase_success_alert?' do
describe 'when purchased_product is present' do
before do
allow(controller).to receive(:params) { { purchased_product: product } }
end
where(:product, :result) do
'product' | true
'' | false
nil | false
end
with_them do
it { expect(helper.show_product_purchase_success_alert?).to be result }
end
end
describe 'when purchased_product is not present' do
it { expect(helper.show_product_purchase_success_alert?).to be false }
end
end
end
......@@ -149,4 +149,22 @@ RSpec.describe SubscriptionsHelper do
it { is_expected.to include(source: 'some_source') }
it { is_expected.to include(group_data: %Q{[{"id":#{group.id},"name":"My Namespace","users":1,"guests":0}]}) }
end
describe '#buy_minutes_addon_data' do
subject(:buy_minutes_addon_data) { helper.buy_minutes_addon_data(group) }
let_it_be(:user) { create(:user, name: 'First Last') }
let_it_be(:group) { create(:group, name: 'My Namespace') }
before do
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:params).and_return({ selected_group: group.id.to_s, source: 'some_source' })
group.add_owner(user)
end
it { is_expected.to include(namespace_id: group.id.to_s) }
it { is_expected.to include(source: 'some_source') }
it { is_expected.to include(group_data: %Q{[{"id":#{group.id},"name":"My Namespace","users":1,"guests":0}]}) }
it { is_expected.to include(redirect_after_success: group_usage_quotas_path(group, purchased_product: 'CI minutes')) }
end
end
......@@ -20,20 +20,22 @@ RSpec.shared_examples_for 'subscription form data' do |js_selector|
it { is_expected.to have_selector("#{js_selector}[data-source='some_source']") }
end
RSpec.shared_examples_for 'addon form data' do |js_selector|
RSpec.shared_examples_for 'buy minutes addon form data' do |js_selector|
before do
allow(view).to receive(:addon_data).and_return(
plan_data: '[{"id":"ci_minutes_plan_id","code":"ci_minutes","price_per_year":10.0}]',
allow(view).to receive(:buy_minutes_addon_data).and_return(
group_data: '[{"id":"ci_minutes_plan_id","code":"ci_minutes","price_per_year":10.0}]',
namespace_id: '1',
plan_id: 'ci_minutes_plan_id',
source: 'some_source'
source: 'some_source',
redirect_after_success: '/groups/my-ci-minutes-group/-/usage_quotas'
)
end
subject { render }
it { is_expected.to have_selector("#{js_selector}[data-plan-data='[{\"id\":\"ci_minutes_plan_id\",\"code\":\"ci_minutes\",\"price_per_year\":10.0}]']") }
it { is_expected.to have_selector("#{js_selector}[data-group-data='[{\"id\":\"ci_minutes_plan_id\",\"code\":\"ci_minutes\",\"price_per_year\":10.0}]']") }
it { is_expected.to have_selector("#{js_selector}[data-plan-id='ci_minutes_plan_id']") }
it { is_expected.to have_selector("#{js_selector}[data-namespace-id='1']") }
it { is_expected.to have_selector("#{js_selector}[data-source='some_source']") }
it { is_expected.to have_selector("#{js_selector}[data-redirect-after-success='/groups/my-ci-minutes-group/-/usage_quotas']") }
end
......@@ -3,5 +3,5 @@
require 'spec_helper'
RSpec.describe 'subscriptions/buy_minutes' do
it_behaves_like 'addon form data', '#js-buy-minutes'
it_behaves_like 'buy minutes addon form data', '#js-buy-minutes'
end
......@@ -5787,6 +5787,9 @@ msgstr ""
msgid "CI configuration validated, including all configuration added with the %{codeStart}includes%{codeEnd} keyword. %{link}"
msgstr ""
msgid "CI minutes"
msgstr ""
msgid "CI settings"
msgstr ""
......@@ -37732,6 +37735,9 @@ msgstr ""
msgid "You have set up 2FA for your account! If you lose access to your 2FA device, you can use your recovery codes to access your account. Alternatively, if you upload an SSH key, you can %{anchorOpen}use that key to generate additional recovery codes%{anchorClose}."
msgstr ""
msgid "You have successfully purchased %{product}. You'll receive a receipt by mail."
msgstr ""
msgid "You have successfully purchased a %{plan} plan subscription for %{seats}. You’ll receive a receipt via email."
msgstr ""
......
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