diff --git a/ee/app/models/concerns/ee/issuable.rb b/ee/app/models/concerns/ee/issuable.rb index a4d3ba15ae3fd372525496d2ec067954f8e05592..8ab533da7d01f45b728b1a414d6b316f7e9e557c 100644 --- a/ee/app/models/concerns/ee/issuable.rb +++ b/ee/app/models/concerns/ee/issuable.rb @@ -66,7 +66,7 @@ def supports_iterations? end def send_to_ai? - !try(:confidential) && resource_parent.public? + !try(:confidential) && resource_parent.public? && resource_parent.root_ancestor.third_party_ai_features_enabled end override :hook_association_changes diff --git a/ee/app/models/ee/group.rb b/ee/app/models/ee/group.rb index 7cf1ef4afe893409c24b75d8b8836eb451848658..25a19e62d20e748e676fa2f017910dee59fd085e 100644 --- a/ee/app/models/ee/group.rb +++ b/ee/app/models/ee/group.rb @@ -76,8 +76,6 @@ module Group delegate :repository_read_only, :code_suggestions, :code_suggestions=, - :experiment_features_enabled, :experiment_features_enabled=, - :third_party_ai_features_enabled, :third_party_ai_features_enabled=, :default_compliance_framework_id, to: :namespace_settings, allow_nil: true diff --git a/ee/app/models/ee/namespace.rb b/ee/app/models/ee/namespace.rb index 71c5d01f232395a13f3bb9ca6529037ce20078af..089778e5af7707e41e0706fb02a2f58d84f6fd0f 100644 --- a/ee/app/models/ee/namespace.rb +++ b/ee/app/models/ee/namespace.rb @@ -106,6 +106,10 @@ module Namespace delegate :trial_ends_on, :trial_starts_on, to: :gitlab_subscription, allow_nil: true + delegate :third_party_ai_features_enabled, :third_party_ai_features_enabled=, + :experiment_features_enabled, :experiment_features_enabled=, + to: :namespace_settings, allow_nil: true + before_create :sync_membership_lock_with_parent # Changing the plan or other details may invalidate this cache diff --git a/ee/app/policies/ee/issue_policy.rb b/ee/app/policies/ee/issue_policy.rb index c0f86e442d053eb8074c62040a0d8cbf7af8a19c..fcd4b068cae837074541dbd02a3b0d9d60cebbbf 100644 --- a/ee/app/policies/ee/issue_policy.rb +++ b/ee/app/policies/ee/issue_policy.rb @@ -7,7 +7,9 @@ module IssuePolicy prepended do with_scope :subject condition(:ai_available) do - ::Feature.enabled?(:openai_experimentation) && @subject.send_to_ai? + ::Feature.enabled?(:openai_experimentation) && + subject_container.root_ancestor.experiment_features_enabled && + @subject.send_to_ai? end with_scope :subject diff --git a/ee/app/policies/epic_policy.rb b/ee/app/policies/epic_policy.rb index 822d7f5dc25ceed616f61a7f0dd37bd02d0b3508..fe66a9c1cbea2cf74c68240e766796a371be4f0b 100644 --- a/ee/app/policies/epic_policy.rb +++ b/ee/app/policies/epic_policy.rb @@ -27,7 +27,9 @@ class EpicPolicy < BasePolicy end condition(:ai_available, scope: :subject) do - ::Feature.enabled?(:openai_experimentation) && @subject.send_to_ai? + ::Feature.enabled?(:openai_experimentation) && + @subject.group.root_ancestor.experiment_features_enabled && + @subject.send_to_ai? end condition(:summarize_notes_enabled, scope: :subject) do diff --git a/ee/spec/lib/gitlab/llm/open_ai/completions/generate_test_file_spec.rb b/ee/spec/lib/gitlab/llm/open_ai/completions/generate_test_file_spec.rb index b11dd26105c778875fd26192448e15fc71ecd353..a3f2989dbeb97e76f7512a7f10460be2713c149f 100644 --- a/ee/spec/lib/gitlab/llm/open_ai/completions/generate_test_file_spec.rb +++ b/ee/spec/lib/gitlab/llm/open_ai/completions/generate_test_file_spec.rb @@ -4,7 +4,8 @@ RSpec.describe Gitlab::Llm::OpenAi::Completions::GenerateTestFile, feature_category: :code_review_workflow do let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } + let_it_be(:group) { create(:group, :public) } + let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:merge_request) { create(:merge_request, source_project: project) } let(:template_class) { ::Gitlab::Llm::OpenAi::Templates::GenerateTestFile } @@ -26,6 +27,10 @@ described_class.new(template_class).execute(user, merge_request, { file_path: 'index.js' }) end + before do + group.namespace_settings.update!(third_party_ai_features_enabled: true) + end + describe "#execute" do context 'with invalid params' do context 'without user' do diff --git a/ee/spec/models/concerns/ee/issuable_spec.rb b/ee/spec/models/concerns/ee/issuable_spec.rb index 6f4f7597d66c27c90f4ed981360cabf2b5a701e1..d454e278512cc2520dccb27ec5cc9ccebdae19be 100644 --- a/ee/spec/models/concerns/ee/issuable_spec.rb +++ b/ee/spec/models/concerns/ee/issuable_spec.rb @@ -110,12 +110,14 @@ describe '#send_to_ai?' do context 'for issues' do - where(:confidentiality, :visibility, :send_to_ai) do + where(:confidentiality, :visibility, :third_party_ai_features_enabled, :result) do [ - [true, :public, false], - [true, :private, false], - [false, :public, true], - [false, :private, false] + [true, :public, false, false], + [true, :public, true, false], + [true, :private, false, false], + [false, :private, false, false], + [false, :private, true, false], + [false, :public, true, true] ] end @@ -123,47 +125,64 @@ let(:project) { build_stubbed(:project, visibility) } let(:issuable) { build_stubbed(:issue, confidential: confidentiality, project: project) } + before do + allow(project.namespace).to receive(:third_party_ai_features_enabled).and_return(third_party_ai_features_enabled) + end + subject { issuable.send_to_ai? } - it { is_expected.to eq(send_to_ai) } + it { is_expected.to eq(result) } end end context 'for epics' do - where(:confidentiality, :visibility, :send_to_ai) do + where(:confidentiality, :visibility, :third_party_ai_features_enabled, :result) do [ - [true, :public, false], - [true, :private, false], - [false, :public, true], - [false, :private, false] + [true, :public, false, false], + [true, :public, true, false], + [true, :private, false, false], + [false, :private, false, false], + [false, :private, true, false], + [false, :public, true, true] ] end - with_them do let(:group) { build_stubbed(:group, visibility) } let(:issuable) { build_stubbed(:epic, confidential: confidentiality, group: group) } + before do + allow(group).to receive(:third_party_ai_features_enabled).and_return(third_party_ai_features_enabled) + end + subject { issuable.send_to_ai? } - it { is_expected.to eq(send_to_ai) } + it { is_expected.to eq(result) } end end context 'for merge requests' do - where(:visibility, :send_to_ai) do + where(:visibility, :third_party_ai_features_enabled, :result) do [ - [Gitlab::VisibilityLevel::PUBLIC, true], - [Gitlab::VisibilityLevel::INTERNAL, false], - [Gitlab::VisibilityLevel::PRIVATE, false] + [Gitlab::VisibilityLevel::PUBLIC, true, true], + [Gitlab::VisibilityLevel::PUBLIC, false, false], + [Gitlab::VisibilityLevel::INTERNAL, false, false], + [Gitlab::VisibilityLevel::INTERNAL, true, false], + [Gitlab::VisibilityLevel::PRIVATE, false, false], + [Gitlab::VisibilityLevel::PRIVATE, true, false] ] end + before do + allow(project.namespace).to receive(:third_party_ai_features_enabled).and_return(third_party_ai_features_enabled) + end + with_them do - let(:issuable) { build_stubbed(:merge_request, project: build_stubbed(:project, visibility_level: visibility)) } + let(:project) { build_stubbed(:project, visibility_level: visibility) } + let(:issuable) { build_stubbed(:merge_request, project: project) } subject { issuable.send_to_ai? } - it { is_expected.to eq(send_to_ai) } + it { is_expected.to eq(result) } end end end diff --git a/ee/spec/models/ee/namespace_spec.rb b/ee/spec/models/ee/namespace_spec.rb index 81cc2f47a8af64a025feabc71dc6f32383a55fd5..94e81ce03af365349dd76bb55da21ce4bc97ef1e 100644 --- a/ee/spec/models/ee/namespace_spec.rb +++ b/ee/spec/models/ee/namespace_spec.rb @@ -33,6 +33,10 @@ it { is_expected.to delegate_method(:temporary_storage_increase_ends_on=).to(:namespace_limit).with_arguments(:args) } it { is_expected.to delegate_method(:temporary_storage_increase_enabled?).to(:namespace_limit) } it { is_expected.to delegate_method(:eligible_for_temporary_storage_increase?).to(:namespace_limit) } + it { is_expected.to delegate_method(:third_party_ai_features_enabled).to(:namespace_settings).allow_nil } + it { is_expected.to delegate_method(:third_party_ai_features_enabled=).to(:namespace_settings).with_arguments(:args).allow_nil } + it { is_expected.to delegate_method(:experiment_features_enabled).to(:namespace_settings).allow_nil } + it { is_expected.to delegate_method(:experiment_features_enabled=).to(:namespace_settings).with_arguments(:args).allow_nil } shared_examples 'plan helper' do |namespace_plan| let(:namespace) { create(:namespace_with_plan, plan: "#{plan_name}_plan") } diff --git a/ee/spec/policies/epic_policy_spec.rb b/ee/spec/policies/epic_policy_spec.rb index 1602148903c5a80d8e5919de6b0d6ea031712cf3..6cbc3d71e6cf11f767d96746499ebff0636b7fb0 100644 --- a/ee/spec/policies/epic_policy_spec.rb +++ b/ee/spec/policies/epic_policy_spec.rb @@ -370,12 +370,15 @@ end end - describe 'summarize_notes' do - let_it_be(:group) { create(:group, :private) } + describe 'summarize_notes', :saas do + let_it_be(:group) { create(:group_with_plan, :private, plan: :ultimate_plan) } before do - stub_licensed_features(summarize_notes: true) + stub_ee_application_setting(should_check_namespace_plan: true) + stub_licensed_features(summarize_notes: true, ai_features: true) stub_feature_flags(summarize_comments: group) + group.namespace_settings.update!(experiment_features_enabled: true) + group.namespace_settings.update!(third_party_ai_features_enabled: true) end context 'when a member' do @@ -390,6 +393,22 @@ it { is_expected.to be_allowed(:summarize_notes) } + context 'when experiment features are disabled' do + before do + group.namespace_settings.update!(experiment_features_enabled: false) + end + + it { is_expected.to be_disallowed(:summarize_notes) } + end + + context 'when third party ai features are disabled' do + before do + group.namespace_settings.update!(third_party_ai_features_enabled: false) + end + + it { is_expected.to be_disallowed(:summarize_notes) } + end + context 'when license is not set' do before do stub_licensed_features(summarize_notes: false) diff --git a/ee/spec/policies/issue_policy_spec.rb b/ee/spec/policies/issue_policy_spec.rb index 3f8ff592987814286ebd40c8b0974796aa10b41f..3d36e62134b167df9afeb0dea017e1a2116b71e7 100644 --- a/ee/spec/policies/issue_policy_spec.rb +++ b/ee/spec/policies/issue_policy_spec.rb @@ -2,152 +2,130 @@ require 'spec_helper' -RSpec.describe IssuePolicy do +RSpec.describe IssuePolicy, :saas, feature_category: :team_planning do let_it_be(:owner) { create(:user) } - let_it_be(:namespace) { create(:group) } - let_it_be(:project) { create(:project, group: namespace) } - let_it_be(:issue) { create(:issue, project: project) } let(:user) { owner } subject { described_class.new(user, issue) } - before do - namespace.add_owner(owner) + context 'on group namespace' do + let_it_be(:namespace) { create(:group_with_plan, plan: :ultimate_plan) } + let_it_be(:project) { create(:project, group: namespace) } + let_it_be(:issue) { create(:issue, project: project) } - allow(issue).to receive(:project).and_return(project) - allow(project).to receive(:namespace).and_return(namespace) - allow(project).to receive(:design_management_enabled?).and_return true - end - - it { is_expected.to be_allowed(:create_issue, :update_issue, :read_issue_iid, :reopen_issue, :create_design, :create_note) } - - describe 'summarize_notes' do before do - stub_licensed_features(summarize_notes: true) - stub_feature_flags(summarize_comments: project) - end + namespace.add_owner(owner) - context 'when a member' do - context 'on a public project' do - before do - project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - end + allow(issue).to receive(:project).and_return(project) + allow(project).to receive(:namespace).and_return(namespace) + allow(project).to receive(:design_management_enabled?).and_return true + end - it { is_expected.to be_allowed(:summarize_notes) } + it { is_expected.to be_allowed(:create_issue, :update_issue, :read_issue_iid, :reopen_issue, :create_design, :create_note) } - context 'when license is not set' do - before do - stub_licensed_features(summarize_notes: false) - end + describe '#rules' do + context 'on a group namespace' do + before do + stub_ee_application_setting(should_check_namespace_plan: true) + stub_licensed_features(summarize_notes: true, ai_features: true, generate_description: true) + stub_feature_flags(summarize_comments: project, generate_description_ai: project) - it { is_expected.to be_disallowed(:summarize_notes) } + namespace.namespace_settings.update!(experiment_features_enabled: true) + namespace.namespace_settings.update!(third_party_ai_features_enabled: true) end - context 'when feature flag is not set' do - before do - stub_feature_flags(summarize_comments: false) - end - - it { is_expected.to be_disallowed(:summarize_notes) } - end + context 'when a member' do + context 'on a public project' do + before do + project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) + end - context 'on confidential issue' do - let_it_be(:issue) { create(:issue, :confidential, project: project) } + it { is_expected.to be_allowed(:summarize_notes) } + it { is_expected.to be_allowed(:generate_description) } - it { is_expected.to be_disallowed(:summarize_notes) } - end - end + context 'when experiment features are disabled' do + before do + namespace.namespace_settings.update!(experiment_features_enabled: false) + end - context 'on a private project' do - let_it_be(:project) { create(:project, :private) } + it { is_expected.to be_disallowed(:summarize_notes) } + end - it { is_expected.to be_disallowed(:summarize_notes) } - end + context 'when third party ai features are disabled' do + before do + namespace.namespace_settings.update!(third_party_ai_features_enabled: false) + end - context 'on confidential issue' do - let_it_be(:issue) { create(:issue, :confidential, project: project) } + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end - it { is_expected.to be_disallowed(:summarize_notes) } - end - end + context 'when license is not set' do + before do + stub_licensed_features(summarize_notes: false, generate_description: false) + end - context 'when not a member' do - let_it_be(:user) { create(:user) } + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end - context 'on a public project' do - let_it_be(:project) { create(:project, :public) } + context 'when feature flag is not set' do + before do + stub_feature_flags(summarize_comments: false, generate_description_ai: false) + end - it { is_expected.to be_disallowed(:summarize_notes) } - end + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end - context 'on a private project' do - it { is_expected.to be_disallowed(:summarize_notes) } - end - end - end + context 'on confidential issue' do + let_it_be(:issue) { create(:issue, :confidential, project: project) } - describe 'generate_description' do - before do - stub_licensed_features(generate_description: true) - stub_feature_flags(generate_description_ai: project) - end - - context 'when a member' do - context 'on a public project' do - before do - project.update!(visibility_level: Gitlab::VisibilityLevel::PUBLIC) - end + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end + end - it { is_expected.to be_allowed(:generate_description) } + context 'on a private project' do + let_it_be(:project) { create(:project, :private) } - context 'when license is not set' do - before do - stub_licensed_features(generate_description: false) + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } end - it { is_expected.to be_disallowed(:generate_description) } - end + context 'on confidential issue' do + let_it_be(:issue) { create(:issue, :confidential, project: project) } - context 'when feature flag is not set' do - before do - stub_feature_flags(generate_description_ai: false) + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } end - - it { is_expected.to be_disallowed(:generate_description) } end - context 'on confidential issue' do - let_it_be(:issue) { create(:issue, :confidential, project: project) } + context 'when not a member' do + let_it_be(:user) { create(:user) } - it { is_expected.to be_disallowed(:generate_description) } - end - end + context 'on a public project' do + let_it_be(:project) { create(:project, :public) } - context 'on a private project' do - let_it_be(:project) { create(:project, :private) } - - it { is_expected.to be_disallowed(:generate_description) } - end - - context 'on confidential issue' do - let_it_be(:issue) { create(:issue, :confidential, project: project) } + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end - it { is_expected.to be_disallowed(:generate_description) } + context 'on a private project' do + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } + end + end end end + end - context 'when not a member' do - let_it_be(:user) { create(:user) } - - context 'on a public project' do - let_it_be(:project) { create(:project, :public) } - - it { is_expected.to be_disallowed(:generate_description) } - end + context 'on a user namespace' do + let_it_be(:namespace) { owner.namespace } + let_it_be(:project) { create(:project, namespace: namespace) } + let_it_be(:issue) { create(:issue, project: project) } - context 'on a private project' do - it { is_expected.to be_disallowed(:generate_description) } - end - end + it { is_expected.to be_disallowed(:summarize_notes) } + it { is_expected.to be_disallowed(:generate_description) } end end diff --git a/ee/spec/requests/api/graphql/mutations/projects/generate_test_file_spec.rb b/ee/spec/requests/api/graphql/mutations/projects/generate_test_file_spec.rb index 3ed698de156659c57a7ae9c60d12a0f36281d16b..6dbb1988c208dbdf9af3a3a1c332afacc340d360 100644 --- a/ee/spec/requests/api/graphql/mutations/projects/generate_test_file_spec.rb +++ b/ee/spec/requests/api/graphql/mutations/projects/generate_test_file_spec.rb @@ -6,7 +6,8 @@ include GraphqlHelpers include Graphql::Subscriptions::Notes::Helper - let_it_be(:project) { create(:project, :public) } + let_it_be(:group) { create(:group, :public) } + let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:current_user) { create(:user, developer_projects: [project]) } let_it_be(:merge_request) { create(:merge_request, source_project: project) } let_it_be(:file_path) { "files/js/commit.coffee" } @@ -23,6 +24,7 @@ before do stub_licensed_features(generate_test_file: true) + group.namespace_settings.update!(third_party_ai_features_enabled: true) end it 'successfully performs an explain code request' do diff --git a/ee/spec/requests/groups/epics_controller_spec.rb b/ee/spec/requests/groups/epics_controller_spec.rb index 3f5931691d7d12bf201ad48fc4d510514af5e936..a9cbeef35acb889fb7c74dbca98fa38da5159fcf 100644 --- a/ee/spec/requests/groups/epics_controller_spec.rb +++ b/ee/spec/requests/groups/epics_controller_spec.rb @@ -38,38 +38,28 @@ end context 'for summarize notes feature' do - let(:summarize_notes_enabled) { true } let(:group) { create(:group, :public) } before do - stub_licensed_features(epics: true, summarize_notes: summarize_notes_enabled) - end - - context 'when user is a member' do - before do - group.add_developer(user) - end + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :summarize_notes, epic).and_return(summarize_notes_enabled) - context 'when license is set' do - it 'exposes the required feature flags' do - get group_epic_path(group, epic) - - expect(response.body).to have_pushed_frontend_feature_flags(summarizeComments: true) - end - end + stub_licensed_features(epics: true) + end - context 'when license is not set' do - let(:summarize_notes_enabled) { false } + context 'when feature is available set' do + let(:summarize_notes_enabled) { true } - it 'does not expose the feature flags' do - get group_epic_path(group, epic) + it 'exposes the required feature flags' do + get group_epic_path(group, epic) - expect(response.body).not_to have_pushed_frontend_feature_flags(summarizeComments: true) - end + expect(response.body).to have_pushed_frontend_feature_flags(summarizeComments: true) end end - context 'when user is not a member' do + context 'when feature is not available' do + let(:summarize_notes_enabled) { false } + it 'does not expose the feature flags' do get group_epic_path(group, epic) diff --git a/ee/spec/requests/projects/issues_controller_spec.rb b/ee/spec/requests/projects/issues_controller_spec.rb index 5278af3faf59ea274f44f404c68453eb9f74f3e2..82919fa9b75483918e9f504db1f02cb915ebe07c 100644 --- a/ee/spec/requests/projects/issues_controller_spec.rb +++ b/ee/spec/requests/projects/issues_controller_spec.rb @@ -74,11 +74,13 @@ def get_show context 'when user is a member' do before do project.add_guest(user) + + allow(Ability).to receive(:allowed?).and_call_original end - context 'when license is set' do + context 'when feature is available' do before do - stub_licensed_features(summarize_notes: true) + allow(Ability).to receive(:allowed?).with(user, :summarize_notes, issue).and_return(true) end it 'exposes the required feature flags' do @@ -88,7 +90,11 @@ def get_show end end - context 'when license is not set' do + context 'when feature is not available' do + before do + allow(Ability).to receive(:allowed?).with(user, :summarize_notes, issue).and_return(false) + end + it 'does not expose the feature flags' do get_show diff --git a/ee/spec/services/llm/base_service_spec.rb b/ee/spec/services/llm/base_service_spec.rb index aa0d4ef6e8ea50a7b9bc070b34c9884927f42787..5631620725bba2b7945588c693e52c0946267a25 100644 --- a/ee/spec/services/llm/base_service_spec.rb +++ b/ee/spec/services/llm/base_service_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' RSpec.describe Llm::BaseService, feature_category: :no_category do # rubocop: disable RSpec/InvalidFeatureCategory + let_it_be(:group) { create(:group, :public) } let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } + let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:resource) { create(:issue, project: project) } let(:options) { {} } diff --git a/ee/spec/services/llm/generate_description_service_spec.rb b/ee/spec/services/llm/generate_description_service_spec.rb index a53c9787dafed506bbd2bea53440ea23359e46ad..06e191400e12aae2666480ad34b0cb45ab35509e 100644 --- a/ee/spec/services/llm/generate_description_service_spec.rb +++ b/ee/spec/services/llm/generate_description_service_spec.rb @@ -9,11 +9,16 @@ let(:current_user) { user } let(:service) { described_class.new(current_user, resource, {}) } + let(:generate_description_license_enabled) { true } describe '#perform' do before do stub_licensed_features(generate_description: true) + group.namespace_settings.update!(third_party_ai_features_enabled: true) group.add_guest(user) + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?) + .with(user, :generate_description, resource).and_return(generate_description_license_enabled) end subject { service.execute } @@ -39,7 +44,7 @@ shared_examples 'ensures license and feature flag checks' do using RSpec::Parameterized::TableSyntax - where(:generate_description_license_flag, :openai_experimentation_ff, :result) do + where(:generate_description_license_enabled, :openai_experimentation_ff, :result) do true | true | true true | false | false false | true | false @@ -48,7 +53,6 @@ with_them do it 'checks validity' do - stub_licensed_features(generate_description: generate_description_license_flag) stub_feature_flags(openai_experimentation: openai_experimentation_ff) expect(service.valid?).to be(result) diff --git a/ee/spec/services/llm/generate_summary_service_spec.rb b/ee/spec/services/llm/generate_summary_service_spec.rb index 8308a6f444ae55028afc58f8c24bff0dd0892707..4fca95d085d090fecddde4dc98b8b04aa247ef73 100644 --- a/ee/spec/services/llm/generate_summary_service_spec.rb +++ b/ee/spec/services/llm/generate_summary_service_spec.rb @@ -7,12 +7,15 @@ let_it_be(:group) { create(:group, :public) } let_it_be(:project) { create(:project, :public, group: group) } + let(:summarize_notes_enabled) { true } let(:current_user) { user } describe '#perform' do before do - stub_licensed_features(summarize_notes: true) group.add_guest(user) + + allow(Ability).to receive(:allowed?).and_call_original + allow(Ability).to receive(:allowed?).with(user, :summarize_notes, resource).and_return(summarize_notes_enabled) end subject { described_class.new(current_user, resource, {}).execute } @@ -40,18 +43,8 @@ end shared_examples 'ensures feature flags and license' do - context 'without the correct license' do - before do - stub_licensed_features(summarize_notes: false) - end - - it { is_expected.to be_error.and have_attributes(message: eq(described_class::INVALID_MESSAGE)) } - end - - context 'without the feature specific flag enabled' do - before do - stub_feature_flags(summarize_comments: false) - end + context 'without the license available' do + let(:summarize_notes_enabled) { false } it { is_expected.to be_error.and have_attributes(message: eq(described_class::INVALID_MESSAGE)) } end diff --git a/ee/spec/services/llm/generate_test_file_service_spec.rb b/ee/spec/services/llm/generate_test_file_service_spec.rb index 67633a3ea08d2abc31723b5876b424872765fbeb..906a95a27071615388530dc5fbe60a6aaa573e7e 100644 --- a/ee/spec/services/llm/generate_test_file_service_spec.rb +++ b/ee/spec/services/llm/generate_test_file_service_spec.rb @@ -3,8 +3,9 @@ require 'spec_helper' RSpec.describe Llm::GenerateTestFileService, feature_category: :code_review_workflow do + let_it_be(:group) { create(:group, :public) } let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } + let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:merge_request) { create(:merge_request, source_project: project) } let(:options) { {} } @@ -13,6 +14,7 @@ describe '#execute' do before do stub_licensed_features(generate_test_file: true) + group.namespace_settings.update!(third_party_ai_features_enabled: true) allow(Llm::CompletionWorker).to receive(:perform_async) end diff --git a/ee/spec/workers/llm/completion_worker_spec.rb b/ee/spec/workers/llm/completion_worker_spec.rb index 7bcace047f81f2446d7a3b15d4200f1603d4df9b..eebd4cda6647e998360f2055ddc23c7e83d11502 100644 --- a/ee/spec/workers/llm/completion_worker_spec.rb +++ b/ee/spec/workers/llm/completion_worker_spec.rb @@ -9,7 +9,8 @@ describe '#perform' do let_it_be(:user) { create(:user) } - let_it_be(:project) { create(:project, :public) } + let_it_be(:group) { create(:group, :public) } + let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:resource) { create(:issue, project: project) } let(:user_id) { user.id }