From 1fc7995a5e4dd091180135330eedbb752340dc1f Mon Sep 17 00:00:00 2001
From: Mark Chao <mchao@gitlab.com>
Date: Thu, 8 Feb 2024 11:55:48 +0000
Subject: [PATCH] Hide AI powered toggle at service start date

specified by CloudConnector duo_chat query.
---
 .../admin/application_settings_helper.rb      | 10 +++
 .../_ai_powered.html.haml                     | 23 +++---
 .../admin/application_settings_helper_spec.rb | 58 ++++++++++++++
 .../general.html.haml_spec.rb                 | 78 ++++++++++++++-----
 4 files changed, 138 insertions(+), 31 deletions(-)

diff --git a/ee/app/helpers/admin/application_settings_helper.rb b/ee/app/helpers/admin/application_settings_helper.rb
index 08f22bfe1b267..e15d00fb1b147 100644
--- a/ee/app/helpers/admin/application_settings_helper.rb
+++ b/ee/app/helpers/admin/application_settings_helper.rb
@@ -14,6 +14,16 @@ def ai_powered_description
         tag_pair_for_link(ai_powered_docs_url))
     end
 
+    def admin_display_code_suggestions_toggle?
+      start_date = CodeSuggestions::SelfManaged::SERVICE_START_DATE
+      License.feature_available?(:code_suggestions) && start_date.future?
+    end
+
+    def admin_display_ai_powered_toggle?
+      start_date = CloudConnector::Access.service_start_date_for('duo_chat')
+      License.feature_available?(:ai_chat) && (start_date.nil? || start_date&.future?)
+    end
+
     private
 
     # rubocop:disable Gitlab/DocUrl
diff --git a/ee/app/views/admin/application_settings/_ai_powered.html.haml b/ee/app/views/admin/application_settings/_ai_powered.html.haml
index a6939a43073ea..9df16426807ca 100644
--- a/ee/app/views/admin/application_settings/_ai_powered.html.haml
+++ b/ee/app/views/admin/application_settings/_ai_powered.html.haml
@@ -2,10 +2,10 @@
 
 -# TODO: clean-up after the Code Suggestions service start date (16.9+)
 -# Details (internal): https://gitlab.com/gitlab-org/gitlab/-/issues/425047#note_1673643291
-- if CodeSuggestions::SelfManaged::SERVICE_START_DATE.past?
-  - return unless License.feature_available?(:ai_chat)
-- else
-  - return unless License.feature_available?(:code_suggestions) || License.feature_available?(:ai_chat)
+- visible_code_suggestions = admin_display_code_suggestions_toggle?
+- visible_duo_chat = admin_display_ai_powered_toggle?
+
+- return if !visible_code_suggestions && !visible_duo_chat
 
 - expanded = false
 
@@ -24,20 +24,17 @@
 
       %fieldset
         .form-group
-          - if CodeSuggestions::SelfManaged::SERVICE_START_DATE.past?
-            = f.gitlab_ui_checkbox_component :instance_level_ai_beta_features_enabled,
-              s_('AIPoweredSM|Enable Experiment and Beta AI-powered features'),
-              help_text: ai_powered_testing_agreement
-          - else
-            -# TODO: remove this block after the Code Suggestions service start date (16.9+)
+          - if visible_code_suggestions
             %h5.settings-header-controls
-              =  s_('CodeSuggestionsSM|Code Suggestions').html_safe
+              = s_('CodeSuggestionsSM|Code Suggestions').html_safe
             = f.gitlab_ui_checkbox_component :instance_level_code_suggestions_enabled,
               s_('CodeSuggestionsSM|Enable Code Suggestions for this instance'),
               help_text: ai_powered_testing_agreement
 
-            %h5.settings-header-controls
-              = s_('AIPoweredSM|AI-powered features')
+          - if visible_duo_chat
+            - if visible_code_suggestions
+              %h5.settings-header-controls
+                = s_('AIPoweredSM|AI-powered features')
             = f.gitlab_ui_checkbox_component :instance_level_ai_beta_features_enabled,
               s_('AIPoweredSM|Enable Experiment and Beta AI-powered features'),
               help_text: ai_powered_testing_agreement
diff --git a/ee/spec/helpers/admin/application_settings_helper_spec.rb b/ee/spec/helpers/admin/application_settings_helper_spec.rb
index b902bac33eb65..77ab67094d6a8 100644
--- a/ee/spec/helpers/admin/application_settings_helper_spec.rb
+++ b/ee/spec/helpers/admin/application_settings_helper_spec.rb
@@ -3,6 +3,8 @@
 require "spec_helper"
 
 RSpec.describe Admin::ApplicationSettingsHelper, feature_category: :code_suggestions do
+  using RSpec::Parameterized::TableSyntax
+
   describe 'AI-Powered features settings for Self-Managed instances' do
     describe '#ai_powered_description' do
       subject { helper.ai_powered_description }
@@ -16,4 +18,60 @@
       it { is_expected.to include 'https://about.gitlab.com/handbook/legal/testing-agreement/' }
     end
   end
+
+  describe '#admin_display_code_suggestions_toggle?', :freeze_time, feature_category: :code_suggestions do
+    let(:feature_enabled) { true }
+
+    let(:today) { Date.current }
+    let(:tomorrow) { today + 1.day }
+
+    before do
+      stub_licensed_features(ai_chat: feature_enabled)
+      stub_const('CodeSuggestions::SelfManaged::SERVICE_START_DATE', service_start_date)
+    end
+
+    where(:service_start_date, :feature_available, :expectation) do
+      ref(:today) | true | false
+      ref(:today) | false | false
+      ref(:tomorrow) | true | true
+      ref(:tomorrow) | false | false
+    end
+
+    with_them do
+      it 'returns expectation' do
+        stub_licensed_features(code_suggestions: feature_available)
+
+        expect(helper.admin_display_code_suggestions_toggle?).to eq(expectation)
+      end
+    end
+  end
+
+  describe '#admin_display_ai_powered_toggle?', :freeze_time, feature_category: :duo_chat do
+    let(:feature_enabled) { true }
+
+    let(:today) { Date.current }
+    let(:tomorrow) { today + 1.day }
+
+    before do
+      stub_licensed_features(ai_chat: feature_enabled)
+      allow(CloudConnector::Access).to receive(:service_start_date_for).with('duo_chat').and_return(service_start_date)
+    end
+
+    where(:service_start_date, :feature_available, :expectation) do
+      ref(:today) | true | false
+      ref(:today) | false | false
+      ref(:tomorrow) | true | true
+      ref(:tomorrow) | false | false
+      nil | true | true
+      nil | false | false
+    end
+
+    with_them do
+      it 'returns expectation' do
+        stub_licensed_features(ai_chat: feature_available)
+
+        expect(helper.admin_display_ai_powered_toggle?).to eq(expectation)
+      end
+    end
+  end
 end
diff --git a/ee/spec/views/admin/application_settings/general.html.haml_spec.rb b/ee/spec/views/admin/application_settings/general.html.haml_spec.rb
index bc5dbbc232c3a..d5897c83c6908 100644
--- a/ee/spec/views/admin/application_settings/general.html.haml_spec.rb
+++ b/ee/spec/views/admin/application_settings/general.html.haml_spec.rb
@@ -8,11 +8,16 @@
   let_it_be(:user) { create(:admin) }
   let_it_be(:app_settings) { build(:application_setting) }
 
+  let(:code_suggestions_start_date) { CodeSuggestions::SelfManaged::SERVICE_START_DATE }
+  let(:duo_chat_start_date) { code_suggestions_start_date + 1.month }
+  let(:before_code_suggestions_start_date) { code_suggestions_start_date - 1.day }
+
   subject { rendered }
 
   before do
     assign(:application_setting, app_settings)
     allow(view).to receive(:current_user).and_return(user)
+    allow(CloudConnector::Access).to receive(:service_start_date_for).with('duo_chat').and_return(duo_chat_start_date)
   end
 
   describe 'maintenance mode' do
@@ -196,9 +201,9 @@
             end
           end
 
-          context 'when after the service start date' do
+          context 'when at the service start date' do
             around do |example|
-              travel_to(CodeSuggestions::SelfManaged::SERVICE_START_DATE + 1.day) do
+              travel_to(CodeSuggestions::SelfManaged::SERVICE_START_DATE) do
                 example.run
               end
             end
@@ -250,9 +255,45 @@
             stub_licensed_features(ai_chat: true)
           end
 
-          it 'renders AI Beta features toggle' do
-            render
-            expect(rendered).to have_field('application_setting_instance_level_ai_beta_features_enabled')
+          context 'when before the service start date' do
+            around do |example|
+              travel_to(duo_chat_start_date - 1.day) do
+                example.run
+              end
+            end
+
+            it 'renders AI Beta features toggle' do
+              render
+              expect(rendered).to have_field('application_setting_instance_level_ai_beta_features_enabled')
+            end
+          end
+
+          context 'when at the service start date' do
+            around do |example|
+              travel_to(duo_chat_start_date) do
+                example.run
+              end
+            end
+
+            it 'does not render AI Beta features toggle' do
+              render
+              expect(rendered).not_to have_field('application_setting_instance_level_ai_beta_features_enabled')
+            end
+          end
+
+          context 'when service start date is nil' do
+            let(:duo_chat_start_date) { nil }
+
+            around do |example|
+              travel_to(before_code_suggestions_start_date) do
+                example.run
+              end
+            end
+
+            it 'renders AI Beta features toggle' do
+              render
+              expect(rendered).to have_field('application_setting_instance_level_ai_beta_features_enabled')
+            end
           end
         end
 
@@ -275,15 +316,19 @@
   # (internal) https://gitlab.com/gitlab-org/gitlab/-/issues/425047#note_1673643291
   # TODO: clean-up after the Code Suggestions service start date (16.9+)
   describe 'entire instance-level ai-powered menu section visibility', feature_category: :duo_chat do
-    where(:before_start_date, :ai_chat_available, :code_suggestions_available, :expect_section_is_visible) do
-      true  | false | false | false
-      true  | false | true  | true
-      true  | true  | false | true
-      true  | true  | true  | true
-      false | false | false | false
-      false | false | true  | false
-      false | true  | false | true
-      false | true  | true  | true
+    where(:current_date, :ai_chat_available, :code_suggestions_available, :expect_section_is_visible) do
+      ref(:before_code_suggestions_start_date) | false | false | false
+      ref(:before_code_suggestions_start_date) | false | true  | true
+      ref(:before_code_suggestions_start_date) | true  | false | true
+      ref(:before_code_suggestions_start_date) | true  | true  | true
+      ref(:code_suggestions_start_date)        | false | false | false
+      ref(:code_suggestions_start_date)        | false | true  | false
+      ref(:code_suggestions_start_date)        | true  | false | true
+      ref(:code_suggestions_start_date)        | true  | true  | true
+      ref(:duo_chat_start_date)               | false | false | false
+      ref(:duo_chat_start_date)               | false | true  | false
+      ref(:duo_chat_start_date)               | true  | false | false
+      ref(:duo_chat_start_date)               | true  | true  | false
     end
 
     with_them do
@@ -291,10 +336,7 @@
         allow(::Gitlab).to receive(:org_or_com?).and_return(false)
         stub_licensed_features(ai_chat: ai_chat_available, code_suggestions: code_suggestions_available)
 
-        service_start_date = CodeSuggestions::SelfManaged::SERVICE_START_DATE
-        test_time = before_start_date ? service_start_date - 1.day : service_start_date + 1.day
-
-        travel_to(test_time) do
+        travel_to(current_date) do
           render
 
           if expect_section_is_visible
-- 
GitLab