Commit 665d0793 authored by Doug Stull's avatar Doug Stull Committed by Vitali Tatarintev

Add trial status widget to projects within group trial

parent cc2f3a8c
...@@ -43,7 +43,13 @@ export default { ...@@ -43,7 +43,13 @@ export default {
</script> </script>
<template> <template>
<gl-link :id="containerId" :title="widgetTitle" :href="plansHref" @click="onWidgetClick"> <gl-link
:id="containerId"
:title="widgetTitle"
:href="plansHref"
class="gl-text-decoration-none! gl-text-body!"
@click="onWidgetClick"
>
<div class="gl-display-flex gl-flex-direction-column gl-align-items-stretch gl-w-full"> <div class="gl-display-flex gl-flex-direction-column gl-align-items-stretch gl-w-full">
<span class="gl-display-flex gl-align-items-center"> <span class="gl-display-flex gl-align-items-center">
<span class="nav-icon-container svg-container"> <span class="nav-icon-container svg-container">
......
import '~/pages/projects';
import { initTrialStatusWidgetAndPopover } from 'ee/contextual_sidebar/init_trial_status_widget_and_popover';
initTrialStatusWidgetAndPopover();
...@@ -33,10 +33,6 @@ module TrialStatusWidgetHelper ...@@ -33,10 +33,6 @@ module TrialStatusWidgetHelper
) )
end end
def show_trial_status_widget?(group)
billing_plans_and_trials_available? && eligible_for_trial_upgrade_callout?(group)
end
private private
def billing_plans_and_trials_available? def billing_plans_and_trials_available?
......
-# Only top-level groups can have trials & plans #js-trial-status-widget{ data: trial_status_widget_data_attrs(root_group) }
- root_group = group.root_ancestor #js-trial-status-popover{ data: trial_status_popover_data_attrs(root_group) }
- return unless show_trial_status_widget?(root_group)
= nav_link do
#js-trial-status-widget{ data: trial_status_widget_data_attrs(root_group) }
#js-trial-status-popover{ data: trial_status_popover_data_attrs(root_group) }
...@@ -10,6 +10,9 @@ module EE ...@@ -10,6 +10,9 @@ module EE
def configure_menus def configure_menus
super super
insert_menu_before(::Sidebars::Projects::Menus::ProjectInformationMenu,
::Sidebars::Projects::Menus::TrialExperimentMenu.new(context))
if ::Sidebars::Projects::Menus::IssuesMenu.new(context).show_jira_menu_items? if ::Sidebars::Projects::Menus::IssuesMenu.new(context).show_jira_menu_items?
remove_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu) remove_menu(::Sidebars::Projects::Menus::ExternalIssueTrackerMenu)
end end
......
...@@ -4,6 +4,14 @@ module Sidebars ...@@ -4,6 +4,14 @@ module Sidebars
module Groups module Groups
module Menus module Menus
class TrialExperimentMenu < ::Sidebars::Menu class TrialExperimentMenu < ::Sidebars::Menu
override :render?
def render?
# Only top-level groups can have trials & plans
::Gitlab::CurrentSettings.should_check_namespace_plan? &&
root_group.trial_active? &&
can?(current_user, :admin_namespace, root_group)
end
override :menu_partial override :menu_partial
def menu_partial def menu_partial
'layouts/nav/sidebar/group_trial_status_widget' 'layouts/nav/sidebar/group_trial_status_widget'
...@@ -12,9 +20,15 @@ module Sidebars ...@@ -12,9 +20,15 @@ module Sidebars
override :menu_partial_options override :menu_partial_options
def menu_partial_options def menu_partial_options
{ {
group: context.group root_group: root_group
} }
end end
private
def root_group
context.group.root_ancestor
end
end end
end end
end end
......
# frozen_string_literal: true
module Sidebars
module Projects
module Menus
class TrialExperimentMenu < ::Sidebars::Groups::Menus::TrialExperimentMenu
private
def root_group
context.project.namespace.root_ancestor
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Contextual sidebar', :saas, :js do
let_it_be(:user) { create(:user) }
let_it_be(:group) do
create(:group).tap do |record|
record.add_owner(user)
end
end
let_it_be(:subscription) do
create(:gitlab_subscription, :active_trial, namespace: group)
end
before do
stub_application_setting(check_namespace_plan: true)
allow_next_instance_of(GitlabSubscriptions::FetchSubscriptionPlansService, plan: :free) do |instance|
allow(instance).to receive(:execute).and_return([{ 'code' => 'ultimate', 'id' => 'ultimate-plan-id' }])
end
sign_in(user)
end
context 'when in group' do
before do
visit group_path(group)
end
it 'shows the popover for the trial status widget' do
expect(page).not_to have_selector('.js-sidebar-collapsed')
find('#trial-status-sidebar-widget').hover
expect(page).to have_content("We hope you’re enjoying the features of GitLab")
end
end
context 'when in project' do
let_it_be(:project) { create(:project, namespace: group) }
before do
visit project_path(project)
end
it 'shows the popover for the trial status widget' do
expect(page).not_to have_selector('.js-sidebar-collapsed')
find('#trial-status-sidebar-widget').hover
expect(page).to have_content("We hope you’re enjoying the features of GitLab")
end
end
end
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
exports[`TrialStatusWidget component without the optional containerId prop matches the snapshot 1`] = ` exports[`TrialStatusWidget component without the optional containerId prop matches the snapshot 1`] = `
<gl-link-stub <gl-link-stub
class="gl-text-decoration-none! gl-text-body!"
href="billing/path-for/group" href="billing/path-for/group"
title="Ultimate Trial – 20 days left" title="Ultimate Trial – 20 days left"
> >
......
...@@ -147,28 +147,4 @@ RSpec.describe TrialStatusWidgetHelper, :saas do ...@@ -147,28 +147,4 @@ RSpec.describe TrialStatusWidgetHelper, :saas do
end end
end end
end end
describe '#show_trial_status_widget?' do
let(:user) { instance_double(User) }
let(:group) { instance_double(Group, trial_active?: trial_active) }
before do
stub_application_setting(check_namespace_plan: trials_available)
allow(helper).to receive(:current_user).and_return(user)
allow(helper).to receive(:can?).and_call_original
allow(helper).to receive(:can?).with(user, :admin_namespace, group).and_return(user_can_admin_group)
end
subject { helper.show_trial_status_widget?(group) }
where(
trials_available: [true, false],
trial_active: [true, false],
user_can_admin_group: [true, false]
)
with_them do
it { is_expected.to eq(trials_available && trial_active && user_can_admin_group) }
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::TrialExperimentMenu, :saas do
it_behaves_like 'trial experiment menu items' do
let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) }
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::Menus::TrialExperimentMenu, :saas do
it_behaves_like 'trial experiment menu items' do
let(:context) do
container = instance_double(Project, namespace: group)
Sidebars::Projects::Context.new(current_user: user, container: container)
end
end
end
# frozen_string_literal: true
RSpec.shared_examples 'trial experiment menu items' do
describe '#render?' do
using RSpec::Parameterized::TableSyntax
let(:user) { instance_double(User) }
let(:group) { instance_double(Group, trial_active?: trial_active) }
let(:menu) { described_class.new(context) }
before do
stub_application_setting(check_namespace_plan: trials_available)
allow(menu).to receive(:can?).and_call_original
allow(menu).to receive(:can?).with(user, :admin_namespace, group).and_return(user_can_admin_group)
allow(group).to receive(:root_ancestor).and_return(group)
end
subject { menu.render? }
where(
trials_available: [true, false],
trial_active: [true, false],
user_can_admin_group: [true, false]
)
with_them do
it { is_expected.to eq(trials_available && trial_active && user_can_admin_group) }
end
end
end
...@@ -8,34 +8,6 @@ RSpec.describe 'layouts/nav/sidebar/_group' do ...@@ -8,34 +8,6 @@ RSpec.describe 'layouts/nav/sidebar/_group' do
before do before do
assign(:group, group) assign(:group, group)
allow(view).to receive(:show_trial_status_widget?).and_return(false)
end
describe 'trial status widget', :aggregate_failures do
subject do
render
rendered
end
context 'when the widget should not be shown' do
it 'does not render the widget & popover' do
is_expected.not_to have_selector '#js-trial-status-widget'
is_expected.not_to have_selector '#js-trial-status-popover'
end
end
context 'when the widget should be shown' do
before do
allow(view).to receive(:show_trial_status_widget?).and_return(true)
allow(view).to receive(:trial_status_widget_data_attrs).and_return({ foo: 'bar' })
allow(view).to receive(:trial_status_popover_data_attrs).and_return({ baz: 'quux' })
end
it 'renders both the widget & popover component initialization elements' do
is_expected.to have_selector '#js-trial-status-widget[data-foo="bar"]'
is_expected.to have_selector '#js-trial-status-popover[data-baz="quux"]'
end
end
end end
describe 'Epics menu' do describe 'Epics menu' 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