From 946ea3bf56864adac41dfb970ad5a059c681ca09 Mon Sep 17 00:00:00 2001
From: Nicolas Dular <ndular@gitlab.com>
Date: Fri, 26 Jul 2024 11:47:32 +0000
Subject: [PATCH] Redirect to epics when work item is not available

---
 .../groups/work_items_controller.rb           |  2 +-
 app/controllers/groups_controller.rb          |  2 +-
 app/finders/work_items/work_items_finder.rb   |  2 +-
 .../namespaces/work_item_resolver.rb          |  2 +-
 .../namespaces/work_items_resolver.rb         |  2 +-
 app/models/group.rb                           |  2 +-
 app/services/groups/autocomplete_service.rb   |  2 +-
 .../ee/groups/work_items_controller.rb        | 16 ++++++---
 ee/app/controllers/groups/epics_controller.rb |  3 +-
 ee/app/helpers/ee/nav/new_dropdown_helper.rb  |  2 +-
 ee/app/models/ee/group.rb                     |  8 +++--
 .../groups/epics_controller_spec.rb           |  4 +--
 .../epic_quick_actions_spec.rb                |  2 +-
 .../features/discussion_comments/epic_spec.rb |  2 +-
 ee/spec/features/epics/abuse_report_spec.rb   |  2 +-
 .../features/epics/confidential_notes_spec.rb |  2 +-
 ee/spec/features/epics/epic_issues_spec.rb    |  2 +-
 ee/spec/features/epics/epic_labels_spec.rb    |  2 +-
 .../features/epics/epic_related_epics_spec.rb |  2 +-
 ee/spec/features/epics/epic_show_spec.rb      |  2 +-
 .../epics/epic_work_item_sync_spec.rb         |  2 +-
 .../features/epics/gfm_autocomplete_spec.rb   |  6 +++-
 .../features/epics/referencing_epics_spec.rb  |  2 +-
 ee/spec/features/epics/shortcuts_epic_spec.rb |  2 +-
 ee/spec/features/epics/todo_spec.rb           |  6 ++--
 ee/spec/features/epics/update_epic_spec.rb    |  2 +-
 .../epics/user_comments_on_epic_spec.rb       |  2 +-
 .../epics/user_uses_quick_actions_spec.rb     |  2 +-
 .../helpers/nav/new_dropdown_helper_spec.rb   | 28 ++++++++++++---
 ee/spec/models/ee/group_spec.rb               | 27 ++++++++++----
 .../ee/groups/work_items_controller_spec.rb   | 36 +++++++++++++++----
 .../requests/groups/epics_controller_spec.rb  |  2 +-
 32 files changed, 128 insertions(+), 52 deletions(-)

diff --git a/app/controllers/groups/work_items_controller.rb b/app/controllers/groups/work_items_controller.rb
index ab1e1d50d9cf7..badf4819580e7 100644
--- a/app/controllers/groups/work_items_controller.rb
+++ b/app/controllers/groups/work_items_controller.rb
@@ -31,7 +31,7 @@ def show
     private
 
     def namespace_work_items_enabled?
-      group&.namespace_work_items_enabled?
+      group&.namespace_work_items_enabled?(current_user)
     end
 
     def show_params
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb
index 7a6b683d1ea60..78bfca4c2c648 100644
--- a/app/controllers/groups_controller.rb
+++ b/app/controllers/groups_controller.rb
@@ -42,7 +42,7 @@ class GroupsController < Groups::ApplicationController
     push_force_frontend_feature_flag(:work_items_alpha, group.work_items_alpha_feature_flag_enabled?)
     push_frontend_feature_flag(:issues_grid_view)
     push_frontend_feature_flag(:group_multi_select_tokens, group)
-    push_force_frontend_feature_flag(:namespace_level_work_items, group.namespace_work_items_enabled?)
+    push_force_frontend_feature_flag(:namespace_level_work_items, group.namespace_work_items_enabled?(current_user))
   end
 
   before_action only: :merge_requests do
diff --git a/app/finders/work_items/work_items_finder.rb b/app/finders/work_items/work_items_finder.rb
index 672566f17d68a..339ad1aa7be2c 100644
--- a/app/finders/work_items/work_items_finder.rb
+++ b/app/finders/work_items/work_items_finder.rb
@@ -130,7 +130,7 @@ def project_namespaces
     end
 
     def include_namespace_level_work_items?
-      params.group? && params.group.namespace_work_items_enabled?
+      params.group? && params.group.namespace_work_items_enabled?(current_user)
     end
 
     def include_descendants?
diff --git a/app/graphql/resolvers/namespaces/work_item_resolver.rb b/app/graphql/resolvers/namespaces/work_item_resolver.rb
index 345fc9951f722..5c8bdac7b5cfa 100644
--- a/app/graphql/resolvers/namespaces/work_item_resolver.rb
+++ b/app/graphql/resolvers/namespaces/work_item_resolver.rb
@@ -8,7 +8,7 @@ class WorkItemResolver < Resolvers::BaseResolver
       argument :iid, GraphQL::Types::String, required: true, description: 'IID of the work item.'
 
       def ready?(**args)
-        return false if resource_parent.is_a?(Group) && !resource_parent.namespace_work_items_enabled?
+        return false if resource_parent.is_a?(Group) && !resource_parent.namespace_work_items_enabled?(current_user)
 
         super
       end
diff --git a/app/graphql/resolvers/namespaces/work_items_resolver.rb b/app/graphql/resolvers/namespaces/work_items_resolver.rb
index 2b0acb91b7600..a08969e3ad357 100644
--- a/app/graphql/resolvers/namespaces/work_items_resolver.rb
+++ b/app/graphql/resolvers/namespaces/work_items_resolver.rb
@@ -15,7 +15,7 @@ class WorkItemsResolver < ::Resolvers::WorkItemsResolver
         description: 'Include work items from descendant groups and projects.'
 
       def ready?(**args)
-        super && resource_parent.namespace_work_items_enabled?
+        super && resource_parent.namespace_work_items_enabled?(current_user)
       end
 
       private
diff --git a/app/models/group.rb b/app/models/group.rb
index a04771e27f010..1bb8a516869b4 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -952,7 +952,7 @@ def work_items_rolledup_dates_feature_flag_enabled?
   end
 
   # Note: this method is overridden in EE to check the work_item_epics feature flag  which also enables this feature
-  def namespace_work_items_enabled?
+  def namespace_work_items_enabled?(_user = nil)
     ::Feature.enabled?(:namespace_level_work_items, self, type: :development)
   end
 
diff --git a/app/services/groups/autocomplete_service.rb b/app/services/groups/autocomplete_service.rb
index 9dcd73d2a3549..79feec246c008 100644
--- a/app/services/groups/autocomplete_service.rb
+++ b/app/services/groups/autocomplete_service.rb
@@ -11,7 +11,7 @@ def issues(confidential_only: false, issue_types: nil)
       finder_params[:issue_types] = issue_types if issue_types.present?
 
       finder_class =
-        if group.namespace_work_items_enabled?
+        if group.namespace_work_items_enabled?(current_user)
           finder_params[:include_descendants] = true
           WorkItems::WorkItemsFinder
         else
diff --git a/ee/app/controllers/ee/groups/work_items_controller.rb b/ee/app/controllers/ee/groups/work_items_controller.rb
index 17423196a77b2..6ece12c1a464e 100644
--- a/ee/app/controllers/ee/groups/work_items_controller.rb
+++ b/ee/app/controllers/ee/groups/work_items_controller.rb
@@ -20,18 +20,26 @@ module WorkItemsController
         include DescriptionDiffActions
       end
 
-      private
+      def show
+        # Once we rollout epic work items, links to `/work_items/:iid` might be already used. However there could be the
+        # scenario where we rollback the feature flag to enable epic work items. In this case, we want users to still
+        # see their epics and therefore redirect them to `/epics/:iid`.
+        return redirect_to group_epic_path(group, issuable.iid) if epic_work_item? && !namespace_work_items_enabled?
 
-      override :namespace_work_items_enabled?
-      def namespace_work_items_enabled?
-        super && ::Feature.enabled?(:work_item_epics_rollout, current_user)
+        super
       end
 
+      private
+
       def issuable
         ::WorkItem.find_by_namespace_and_iid!(group, params[:iid])
       end
       strong_memoize_attr :issuable
 
+      def epic_work_item?
+        issuable.work_item_type == ::WorkItems::Type.default_by_type(:epic)
+      end
+
       def authorize_read_work_item!
         access_denied! unless can?(current_user, :read_work_item, issuable)
       end
diff --git a/ee/app/controllers/groups/epics_controller.rb b/ee/app/controllers/groups/epics_controller.rb
index 53bef6b1d4427..6ad7f69327d4b 100644
--- a/ee/app/controllers/groups/epics_controller.rb
+++ b/ee/app/controllers/groups/epics_controller.rb
@@ -19,7 +19,6 @@ class Groups::EpicsController < Groups::ApplicationController
 
   before_action do
     push_frontend_feature_flag(:notifications_todos_buttons, current_user)
-    push_frontend_feature_flag(:namespace_level_work_items, @group)
     push_force_frontend_feature_flag(:namespace_level_work_items, epic_work_items_enabled?)
   end
 
@@ -69,7 +68,7 @@ def create
   private
 
   def epic_work_items_enabled?
-    @group&.namespace_work_items_enabled? && ::Feature.enabled?(:work_item_epics_rollout, current_user)
+    !!@group&.namespace_work_items_enabled?(current_user)
   end
 
   # rubocop: disable CodeReuse/ActiveRecord
diff --git a/ee/app/helpers/ee/nav/new_dropdown_helper.rb b/ee/app/helpers/ee/nav/new_dropdown_helper.rb
index 826380ec5c805..72b5cda1780be 100644
--- a/ee/app/helpers/ee/nav/new_dropdown_helper.rb
+++ b/ee/app/helpers/ee/nav/new_dropdown_helper.rb
@@ -10,7 +10,7 @@ module NewDropdownHelper
       override :create_epic_menu_item
       def create_epic_menu_item(group)
         if can?(current_user, :create_epic, group)
-          if group.namespace_work_items_enabled? && ::Feature.enabled?(:work_item_epics_rollout, current_user)
+          if group.namespace_work_items_enabled?(current_user)
             ::Gitlab::Nav::TopNavMenuItem.build(
               id: 'create_epic',
               title: _('New epic'),
diff --git a/ee/app/models/ee/group.rb b/ee/app/models/ee/group.rb
index 6675779ce6afe..2b4d9bc4d5200 100644
--- a/ee/app/models/ee/group.rb
+++ b/ee/app/models/ee/group.rb
@@ -271,8 +271,12 @@ def licensed_ai_features_available?
     end
 
     override :namespace_work_items_enabled?
-    def namespace_work_items_enabled?
-      super || (::Feature.enabled?(:work_item_epics, self, type: :beta) && licensed_feature_available?(:epics))
+    def namespace_work_items_enabled?(user = nil)
+      super || (
+          ::Feature.enabled?(:work_item_epics, self, type: :beta) &&
+          ::Feature.enabled?(:work_item_epics_rollout, user) &&
+          licensed_feature_available?(:epics)
+        )
     end
 
     class_methods do
diff --git a/ee/spec/controllers/groups/epics_controller_spec.rb b/ee/spec/controllers/groups/epics_controller_spec.rb
index 406e13f9ea331..a95472858cebd 100644
--- a/ee/spec/controllers/groups/epics_controller_spec.rb
+++ b/ee/spec/controllers/groups/epics_controller_spec.rb
@@ -158,7 +158,7 @@ def show_epic(format = :html)
 
           context 'when work_item_epics_rollout is true' do
             before do
-              stub_feature_flags(work_item_epics_rollout: user)
+              stub_feature_flags(work_item_epics_rollout: user, namespace_level_work_items: false)
             end
 
             it 'renders work item template' do
@@ -177,7 +177,7 @@ def show_epic(format = :html)
 
           context 'when work_item_epics_rollout is false' do
             before do
-              stub_feature_flags(work_item_epics_rollout: false)
+              stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
             end
 
             it 'renders work item template' do
diff --git a/ee/spec/features/discussion_comments/epic_quick_actions_spec.rb b/ee/spec/features/discussion_comments/epic_quick_actions_spec.rb
index eb4bdb4992739..3812808bffc08 100644
--- a/ee/spec/features/discussion_comments/epic_quick_actions_spec.rb
+++ b/ee/spec/features/discussion_comments/epic_quick_actions_spec.rb
@@ -11,7 +11,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     group.add_developer(user)
 
     sign_in(user)
diff --git a/ee/spec/features/discussion_comments/epic_spec.rb b/ee/spec/features/discussion_comments/epic_spec.rb
index 64ae01e188619..977d4a4e37381 100644
--- a/ee/spec/features/discussion_comments/epic_spec.rb
+++ b/ee/spec/features/discussion_comments/epic_spec.rb
@@ -8,7 +8,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     epic.group.add_maintainer(user)
     sign_in(user)
 
diff --git a/ee/spec/features/epics/abuse_report_spec.rb b/ee/spec/features/epics/abuse_report_spec.rb
index a38bc4886f71f..103c72360d9e8 100644
--- a/ee/spec/features/epics/abuse_report_spec.rb
+++ b/ee/spec/features/epics/abuse_report_spec.rb
@@ -10,7 +10,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     sign_in(reporter1)
   end
 
diff --git a/ee/spec/features/epics/confidential_notes_spec.rb b/ee/spec/features/epics/confidential_notes_spec.rb
index eb9311efad24f..417eb889408c4 100644
--- a/ee/spec/features/epics/confidential_notes_spec.rb
+++ b/ee/spec/features/epics/confidential_notes_spec.rb
@@ -5,7 +5,7 @@
 RSpec.describe "Confidential notes on epics", :js, feature_category: :portfolio_management do
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
   end
 
   it_behaves_like 'confidential notes on issuables' do
diff --git a/ee/spec/features/epics/epic_issues_spec.rb b/ee/spec/features/epics/epic_issues_spec.rb
index 04746d04e87b2..dca06bc9e3a62 100644
--- a/ee/spec/features/epics/epic_issues_spec.rb
+++ b/ee/spec/features/epics/epic_issues_spec.rb
@@ -30,7 +30,7 @@
   end
 
   before do
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     stub_licensed_features(epics: true, subepics: true)
   end
 
diff --git a/ee/spec/features/epics/epic_labels_spec.rb b/ee/spec/features/epics/epic_labels_spec.rb
index b393808763355..230869def02b8 100644
--- a/ee/spec/features/epics/epic_labels_spec.rb
+++ b/ee/spec/features/epics/epic_labels_spec.rb
@@ -10,7 +10,7 @@
 
   before do
     group.add_developer(user)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     stub_licensed_features(epics: true)
     sign_in(user)
 
diff --git a/ee/spec/features/epics/epic_related_epics_spec.rb b/ee/spec/features/epics/epic_related_epics_spec.rb
index 959d8d86baa46..a52490362a5ee 100644
--- a/ee/spec/features/epics/epic_related_epics_spec.rb
+++ b/ee/spec/features/epics/epic_related_epics_spec.rb
@@ -13,7 +13,7 @@
 
   def visit_epic(related_epics: true)
     group.add_developer(user)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     stub_licensed_features(epics: true, related_epics: related_epics)
     sign_in(user)
     visit group_epic_path(group, epic1)
diff --git a/ee/spec/features/epics/epic_show_spec.rb b/ee/spec/features/epics/epic_show_spec.rb
index 7838c9ca9a7da..c4cd895aa0946 100644
--- a/ee/spec/features/epics/epic_show_spec.rb
+++ b/ee/spec/features/epics/epic_show_spec.rb
@@ -32,7 +32,7 @@
   before do
     group.add_developer(user)
     stub_licensed_features(epics: true, subepics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     sign_in(user)
   end
 
diff --git a/ee/spec/features/epics/epic_work_item_sync_spec.rb b/ee/spec/features/epics/epic_work_item_sync_spec.rb
index 4769e962d2834..3f9bd480d4621 100644
--- a/ee/spec/features/epics/epic_work_item_sync_spec.rb
+++ b/ee/spec/features/epics/epic_work_item_sync_spec.rb
@@ -24,7 +24,7 @@
   end
 
   before do
-    stub_feature_flags(work_item_epics: true, work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics: true, work_item_epics_rollout: false, namespace_level_work_items: false)
     stub_licensed_features(epics: true, subepics: true, epic_colors: true)
 
     sign_in(user)
diff --git a/ee/spec/features/epics/gfm_autocomplete_spec.rb b/ee/spec/features/epics/gfm_autocomplete_spec.rb
index 1bcbf7d920e7b..8b3c06db62d31 100644
--- a/ee/spec/features/epics/gfm_autocomplete_spec.rb
+++ b/ee/spec/features/epics/gfm_autocomplete_spec.rb
@@ -11,7 +11,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     sign_in(user)
   end
 
@@ -47,6 +47,10 @@
     context 'issuables' do
       let(:project) { create(:project, :repository, namespace: group) }
 
+      before do
+        stub_feature_flags(work_item_epics_rollout: true)
+      end
+
       context 'issues' do
         it 'shows issues of group' do
           issue_1 = create(:issue, project: project)
diff --git a/ee/spec/features/epics/referencing_epics_spec.rb b/ee/spec/features/epics/referencing_epics_spec.rb
index bc64a7337511d..56519d607e40d 100644
--- a/ee/spec/features/epics/referencing_epics_spec.rb
+++ b/ee/spec/features/epics/referencing_epics_spec.rb
@@ -97,7 +97,7 @@
       let(:note_text) { "Check #{epic.to_reference(full: true)}" }
 
       before do
-        stub_feature_flags(work_item_epics_rollout: false)
+        stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
         visit project_issue_path(project, issue)
 
         fill_in 'note[note]', with: note_text
diff --git a/ee/spec/features/epics/shortcuts_epic_spec.rb b/ee/spec/features/epics/shortcuts_epic_spec.rb
index c067984263402..e3b887f004aae 100644
--- a/ee/spec/features/epics/shortcuts_epic_spec.rb
+++ b/ee/spec/features/epics/shortcuts_epic_spec.rb
@@ -20,7 +20,7 @@
 
   before do
     group.add_developer(user)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     stub_licensed_features(epics: true)
     sign_in(user)
 
diff --git a/ee/spec/features/epics/todo_spec.rb b/ee/spec/features/epics/todo_spec.rb
index 4119e336e120c..1e0f37730f302 100644
--- a/ee/spec/features/epics/todo_spec.rb
+++ b/ee/spec/features/epics/todo_spec.rb
@@ -12,7 +12,8 @@
   context 'with notifications_todos_buttons feature flag disabled' do
     before do
       stub_licensed_features(epics: true)
-      stub_feature_flags(notifications_todos_buttons: false, work_item_epics_rollout: false)
+      stub_feature_flags(notifications_todos_buttons: false, work_item_epics_rollout: false,
+        namespace_level_work_items: false)
 
       sign_in(user)
       visit group_epic_path(group, epic)
@@ -55,7 +56,8 @@
   context 'with notifications_todos_buttons feature flag enabled' do
     before do
       stub_licensed_features(epics: true)
-      stub_feature_flags(notifications_todos_buttons: true, work_item_epics_rollout: false)
+      stub_feature_flags(notifications_todos_buttons: true, work_item_epics_rollout: false,
+        namespace_level_work_items: false)
 
       sign_in(user)
       visit group_epic_path(group, epic)
diff --git a/ee/spec/features/epics/update_epic_spec.rb b/ee/spec/features/epics/update_epic_spec.rb
index 9901be270a87f..4e6c6cefb0a5e 100644
--- a/ee/spec/features/epics/update_epic_spec.rb
+++ b/ee/spec/features/epics/update_epic_spec.rb
@@ -20,7 +20,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
   end
 
   context 'when user who is not a group member displays the epic' do
diff --git a/ee/spec/features/epics/user_comments_on_epic_spec.rb b/ee/spec/features/epics/user_comments_on_epic_spec.rb
index 6b894a7bf101c..1d9346720d872 100644
--- a/ee/spec/features/epics/user_comments_on_epic_spec.rb
+++ b/ee/spec/features/epics/user_comments_on_epic_spec.rb
@@ -12,7 +12,7 @@
 
   before do
     stub_licensed_features(epics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     sign_in(user)
 
     visit group_epic_path(group, epic)
diff --git a/ee/spec/features/epics/user_uses_quick_actions_spec.rb b/ee/spec/features/epics/user_uses_quick_actions_spec.rb
index 7f68bfede6345..e861403207d84 100644
--- a/ee/spec/features/epics/user_uses_quick_actions_spec.rb
+++ b/ee/spec/features/epics/user_uses_quick_actions_spec.rb
@@ -15,7 +15,7 @@
 
   before do
     stub_licensed_features(epics: true, subepics: true)
-    stub_feature_flags(work_item_epics_rollout: false)
+    stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
     sign_in(reporter)
   end
 
diff --git a/ee/spec/helpers/nav/new_dropdown_helper_spec.rb b/ee/spec/helpers/nav/new_dropdown_helper_spec.rb
index aab88b91ac20b..344e00dc7f8a4 100644
--- a/ee/spec/helpers/nav/new_dropdown_helper_spec.rb
+++ b/ee/spec/helpers/nav/new_dropdown_helper_spec.rb
@@ -64,12 +64,26 @@
         stub_licensed_features(epics: true)
       end
 
+      context 'when namespace_level_work_items flags is enabled' do
+        before do
+          stub_feature_flags(work_item_epics: false, work_item_epics_rollout: false, namespace_level_work_items: true)
+        end
+
+        it_behaves_like 'work item menu'
+      end
+
       context 'when work_item_epics and namespace_level_work_items flags are disabled' do
         before do
           stub_feature_flags(work_item_epics: false, namespace_level_work_items: false)
         end
 
-        it_behaves_like 'legacy epic menu'
+        context 'and work_item_epics_rollout flag is enabled' do
+          before do
+            stub_feature_flags(work_item_epics_rollout: user)
+          end
+
+          it_behaves_like 'legacy epic menu'
+        end
 
         context 'and work_item_epics_rollout flag is disabled' do
           before do
@@ -80,12 +94,18 @@
         end
       end
 
-      context 'when work_item_epics and namespace_level_work_items flags are enabled' do
+      context 'when work_item_epics is enabled and namespace_level_work_items is disabled' do
         before do
-          stub_feature_flags(work_item_epics: true, namespace_level_work_items: true)
+          stub_feature_flags(work_item_epics: true, namespace_level_work_items: false)
         end
 
-        it_behaves_like 'work item menu'
+        context 'and work_item_epics_rollout flag is enabled' do
+          before do
+            stub_feature_flags(work_item_epics_rollout: user)
+          end
+
+          it_behaves_like 'work item menu'
+        end
 
         context 'and work_item_epics_rollout flag is disabled' do
           before do
diff --git a/ee/spec/models/ee/group_spec.rb b/ee/spec/models/ee/group_spec.rb
index a7a3c13ce8f17..d4dddf92bec01 100644
--- a/ee/spec/models/ee/group_spec.rb
+++ b/ee/spec/models/ee/group_spec.rb
@@ -3839,12 +3839,13 @@ def webhook_headers
 
   describe '#namespace_work_items_enabled?' do
     let_it_be(:group) { create(:group) }
+    let_it_be(:current_user) { create(:user) }
 
-    subject { group.namespace_work_items_enabled? }
+    subject { group.namespace_work_items_enabled?(current_user) }
 
-    context 'when namespace_level_work_items and work_item_epics feature flags are enabled' do
+    context 'when all feature flags are enabled' do
       before do
-        stub_feature_flags(work_item_epics: true, namespace_level_work_items: true)
+        stub_feature_flags(work_item_epics: true, namespace_level_work_items: true, work_item_epics_rollout: true)
       end
 
       it { is_expected.to eq(true) }
@@ -3860,7 +3861,21 @@ def webhook_headers
           stub_licensed_features(epics: true)
         end
 
-        it { is_expected.to eq(true) }
+        context 'when work_item_epics_rollout is enabled' do
+          before do
+            stub_feature_flags(work_item_epics_rollout: current_user)
+          end
+
+          it { is_expected.to eq(true) }
+        end
+
+        context 'when work_item_epics_rollout is disabled' do
+          before do
+            stub_feature_flags(work_item_epics_rollout: false)
+          end
+
+          it { is_expected.to eq(false) }
+        end
       end
 
       context 'when epics are not available' do
@@ -3874,7 +3889,7 @@ def webhook_headers
 
     context 'when namespace_level_work_items is enabled and work_item_epics is disabled' do
       before do
-        stub_feature_flags(work_item_epics: false, namespace_level_work_items: true)
+        stub_feature_flags(work_item_epics: false, namespace_level_work_items: true, work_item_epics_rollout: false)
       end
 
       it { is_expected.to eq(true) }
@@ -3882,7 +3897,7 @@ def webhook_headers
 
     context 'when namespace_level_work_items and work_item_epics feature flags are disabled' do
       before do
-        stub_feature_flags(work_item_epics: false, namespace_level_work_items: false)
+        stub_feature_flags(work_item_epics: false, namespace_level_work_items: false, work_item_epics_rollout: false)
       end
 
       it { is_expected.to eq(false) }
diff --git a/ee/spec/requests/ee/groups/work_items_controller_spec.rb b/ee/spec/requests/ee/groups/work_items_controller_spec.rb
index 121b0f0110f0e..0a4b71060cc93 100644
--- a/ee/spec/requests/ee/groups/work_items_controller_spec.rb
+++ b/ee/spec/requests/ee/groups/work_items_controller_spec.rb
@@ -35,10 +35,22 @@
         stub_feature_flags(work_item_epics_rollout: false, namespace_level_work_items: false)
       end
 
-      it 'returns not found' do
-        show
+      context 'when work item type is epic' do
+        it 'redirects to /epic/:iid' do
+          show
+
+          expect(response).to redirect_to(group_epic_path(group, work_item.iid))
+        end
+      end
+
+      context 'when work item type is not epic' do
+        let_it_be(:work_item) { create(:work_item, :issue, namespace: group) }
+
+        it 'returns not found' do
+          show
 
-        expect(response).to have_gitlab_http_status(:not_found)
+          expect(response).to have_gitlab_http_status(:not_found)
+        end
       end
     end
 
@@ -47,10 +59,22 @@
         stub_feature_flags(work_item_epics: false, namespace_level_work_items: false)
       end
 
-      it 'returns not found' do
-        show
+      context 'when work item type is epic' do
+        it 'redirects to /epic/:iid' do
+          show
+
+          expect(response).to redirect_to(group_epic_path(group, work_item.iid))
+        end
+      end
+
+      context 'when work item type is not epic' do
+        let_it_be(:work_item) { create(:work_item, :issue, namespace: group) }
+
+        it 'returns not found' do
+          show
 
-        expect(response).to have_gitlab_http_status(:not_found)
+          expect(response).to have_gitlab_http_status(:not_found)
+        end
       end
     end
   end
diff --git a/ee/spec/requests/groups/epics_controller_spec.rb b/ee/spec/requests/groups/epics_controller_spec.rb
index 5d5a00fab4c7c..a2c07b5094aa1 100644
--- a/ee/spec/requests/groups/epics_controller_spec.rb
+++ b/ee/spec/requests/groups/epics_controller_spec.rb
@@ -84,7 +84,7 @@
 
       context 'when feature flag is false' do
         before do
-          stub_feature_flags(work_item_epics: false, work_item_epics_rollout: false)
+          stub_feature_flags(work_item_epics: false, work_item_epics_rollout: false, namespace_level_work_items: false)
         end
 
         it 'exposes the workItemEpics flag' do
-- 
GitLab