diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-16 12:09:50 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2024-01-16 12:09:50 +0300 |
commit | 65d9a877b3487bdcb75985dbcbe8bcf76280591f (patch) | |
tree | 4ae3347b3e82fbfe05df935d42291f15a6ed2127 | |
parent | 2bc11b8442e9f68800cfed57f9abad3f2dfc0b78 (diff) |
Add latest changes from gitlab-org/gitlab@master
19 files changed, 140 insertions, 294 deletions
diff --git a/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue b/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue index 9588d21a3c5..45c12cb2e08 100644 --- a/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue +++ b/app/assets/javascripts/work_items/components/work_item_milestone_with_edit.vue @@ -93,6 +93,12 @@ export default { })); }, }, + watch: { + workItemMilestone(newVal) { + this.localMilestone = newVal; + this.selectedMilestoneId = newVal?.id; + }, + }, apollo: { milestones: { query: projectMilestonesQuery, diff --git a/app/finders/issues_finder.rb b/app/finders/issues_finder.rb index 2297c0569d9..b47e8a47a7f 100644 --- a/app/finders/issues_finder.rb +++ b/app/finders/issues_finder.rb @@ -113,15 +113,25 @@ class IssuesFinder < IssuableFinder def by_parent(items) return super unless include_namespace_level_work_items? - items.in_namespaces( - Namespace.from_union( - [ - Group.id_in(params.group).select(:id), - params.projects.select(:project_namespace_id) - ], - remove_duplicates: false - ) - ) + relations = [group_namespaces, project_namespaces].compact + + namespaces = if relations.one? + relations.first + else + Namespace.from_union(relations, remove_duplicates: false) + end + + items.in_namespaces(namespaces) + end + + def group_namespaces + return if params[:project_id] || params[:projects] + + Group.id_in(params.group).select(:id) + end + + def project_namespaces + params.projects.select(:project_namespace_id) end def by_confidential(items) @@ -174,9 +184,7 @@ class IssuesFinder < IssuableFinder end def include_namespace_level_work_items? - params.group? && - Array(params[:issue_types]).map(&:to_s).include?('epic') && - Feature.enabled?(:namespace_level_work_items, params.group) + params.group? && Feature.enabled?(:namespace_level_work_items, params.group) end end diff --git a/app/finders/work_items/namespace_work_items_finder.rb b/app/finders/work_items/namespace_work_items_finder.rb deleted file mode 100644 index 95075e0ca0d..00000000000 --- a/app/finders/work_items/namespace_work_items_finder.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: true - -module WorkItems - class NamespaceWorkItemsFinder < WorkItemsFinder - FilterNotAvailableError = Class.new(ArgumentError) - - def initialize(...) - super - - self.parent_param = namespace - end - - override :with_confidentiality_access_check - def with_confidentiality_access_check - return model_class.all if params.user_can_see_all_issuables? - - # Only admins can see hidden issues, so for non-admins, we filter out any hidden issues - issues = model_class.without_hidden - - return issues.all if params.user_can_see_all_confidential_issues? - - return issues.public_only if params.user_cannot_see_confidential_issues? - - issues.with_confidentiality_check(current_user) - end - - private - - def filter_items(items) - items = super(items) - - by_namespace(items) - end - - def by_namespace(items) - if namespace.blank? || !Ability.allowed?(current_user, "read_#{namespace.to_ability_name}".to_sym, namespace) - return klass.none - end - - items.in_namespaces(namespace) - end - - override :by_search - def by_search(items) - return items unless search - - raise FilterNotAvailableError, 'Searching is not available for work items at the namespace level yet' - end - - def namespace - return if params[:namespace_id].blank? - - params[:namespace_id].is_a?(Namespace) ? params[:namespace_id] : Namespace.find_by_id(params[:namespace_id]) - end - strong_memoize_attr :namespace - - override :by_parent - def by_parent(items) - items - end - end -end diff --git a/app/graphql/resolvers/namespaces/work_items_resolver.rb b/app/graphql/resolvers/namespaces/work_items_resolver.rb index 671788668b1..5df2b87222e 100644 --- a/app/graphql/resolvers/namespaces/work_items_resolver.rb +++ b/app/graphql/resolvers/namespaces/work_items_resolver.rb @@ -10,20 +10,13 @@ module Resolvers super end - override :resolve_with_lookahead - def resolve_with_lookahead(...) - super - rescue ::WorkItems::NamespaceWorkItemsFinder::FilterNotAvailableError => e - raise Gitlab::Graphql::Errors::ArgumentError, e.message - end - private override :finder def finder(args) - ::WorkItems::NamespaceWorkItemsFinder.new( + ::WorkItems::WorkItemsFinder.new( current_user, - args.merge(namespace_id: resource_parent) + args.merge(group_id: resource_parent) ) end end diff --git a/app/mailers/emails/profile.rb b/app/mailers/emails/profile.rb index cf46257f7d4..0047882005e 100644 --- a/app/mailers/emails/profile.rb +++ b/app/mailers/emails/profile.rb @@ -44,7 +44,7 @@ module Emails @current_user = @user = @key.user @target_url = user_url(@user) - mail_with_locale(to: @user.notification_email_or_default, subject: subject("SSH key was added to your account")) + email_with_layout(to: @user.notification_email_or_default, subject: subject("SSH key was added to your account")) end # rubocop: enable CodeReuse/ActiveRecord diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb index 2ffad4498bf..c3987d85381 100644 --- a/app/mailers/previews/notify_preview.rb +++ b/app/mailers/previews/notify_preview.rb @@ -130,6 +130,12 @@ class NotifyPreview < ActionMailer::Preview Notify.new_merge_request_email(user.id, merge_request.id).message end + def new_ssh_key_email + cleanup do + Notify.new_ssh_key_email(key.id).message + end + end + def closed_merge_request_email Notify.closed_merge_request_email(user.id, merge_request.id, user.id).message end @@ -420,6 +426,14 @@ class NotifyPreview < ActionMailer::Preview @member ||= Member.last end + def key + @key ||= find_or_create_key + end + + def find_or_create_key + Key.last || Keys::CreateService.new(user).execute + end + def create_note(params) Notes::CreateService.new(project, user, params).execute end diff --git a/app/models/work_item.rb b/app/models/work_item.rb index f1d007e8167..58e8337a9db 100644 --- a/app/models/work_item.rb +++ b/app/models/work_item.rb @@ -26,17 +26,6 @@ class WorkItem < Issue scope :inc_relations_for_permission_check, -> { includes(:author, project: :project_feature) } - scope :with_confidentiality_check, ->(user) { - confidential_query = <<~SQL - issues.confidential = FALSE - OR (issues.confidential = TRUE - AND (issues.author_id = :user_id - OR EXISTS (SELECT TRUE FROM issue_assignees WHERE user_id = :user_id AND issue_id = issues.id))) - SQL - - where(confidential_query, user_id: user.id) - } - class << self def find_by_namespace_and_iid!(namespace, iid) find_by!(namespace: namespace, iid: iid) diff --git a/db/post_migrate/20240115004429_validate_merge_request_diffs_project_id_foreign_key.rb b/db/post_migrate/20240115004429_validate_merge_request_diffs_project_id_foreign_key.rb new file mode 100644 index 00000000000..15ca300ecb2 --- /dev/null +++ b/db/post_migrate/20240115004429_validate_merge_request_diffs_project_id_foreign_key.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class ValidateMergeRequestDiffsProjectIdForeignKey < Gitlab::Database::Migration[2.2] + milestone '16.8' + + def up + validate_foreign_key(:merge_request_diffs, :project_id) + end + + def down + # no-op + end +end diff --git a/db/schema_migrations/20240115004429 b/db/schema_migrations/20240115004429 new file mode 100644 index 00000000000..86cd1b2c11a --- /dev/null +++ b/db/schema_migrations/20240115004429 @@ -0,0 +1 @@ +c304bbf472c1f0e3e1cc362fabd6cd71348e7571643fc9a724c217326aceee8f
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 4102ce44c63..8055f7984c4 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -38418,7 +38418,7 @@ ALTER TABLE ONLY vulnerability_feedback ADD CONSTRAINT fk_563ff1912e FOREIGN KEY (merge_request_id) REFERENCES merge_requests(id) ON DELETE SET NULL; ALTER TABLE ONLY merge_request_diffs - ADD CONSTRAINT fk_56ac6fc9c0 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE NOT VALID; + ADD CONSTRAINT fk_56ac6fc9c0 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE; ALTER TABLE ONLY ml_candidates ADD CONSTRAINT fk_56d6ed4d3d FOREIGN KEY (experiment_id) REFERENCES ml_experiments(id) ON DELETE CASCADE; diff --git a/doc/development/pages/index.md b/doc/development/pages/index.md index 7bf89789ee0..e4e2af10808 100644 --- a/doc/development/pages/index.md +++ b/doc/development/pages/index.md @@ -265,3 +265,57 @@ Example of a merge request enabling a GitLab Pages feature flag: ## Related topics - [Feature flags in the development of GitLab](../feature_flags/index.md) + +## Becoming a GitLab Pages maintainer + +This document serves as a guideline for GitLab team members that want to become maintainers for the GitLab Pages project. +Maintainers should have an advanced understanding of the GitLab Pages codebase. +Prior to applying for maintainer of a project, a person should gain a good feel for the codebase, expertise in one or more functionalities, +and deep understanding of our coding standards. + +### Expectations + +The process to [become a maintainer at GitLab is defined in the handbook](https://about.gitlab.com/handbook/engineering/workflow/code-review/#how-to-become-a-project-maintainer), +and it is the baseline for this process. One thing that is expected is a high number of reviews, however; +the rate of change of the GitLab Pages compared to the GitLab Rails project is too little. + +To work around that problem, one must be comfortable in the following areas of the codebase: + +Main areas: + +- Namespace/project resolution +- ZIP serving and the virtual file system +- Authentication + +Smaller areas: + +- Redirects +- Artifacts proxying +- Handling of TLS certificates +- Rate-limiting +- Metrics and monitoring + +To achieve this, you should try to make relevant contributions in all main areas and 2-3 smaller areas +mentioned above so that you have a better understanding of the functionality. A relevant contribution may be a bug fix, +a performance improvement, a new feature, or a significant refactoring. + +### Reviewer + +Prior to becoming a maintainer, you should first become a reviewer of the project. This should include changes +to any part of the codebase including the documentation. + +To become a reviewer follow the steps [outlined in the handbook](https://about.gitlab.com/handbook/engineering/workflow/code-review/#reviewer). +There is no set timeline of how long you should be a reviewer before becoming a maintainer, but you should +gain enough experience in the areas mentioned in the [expectations section](#expectations) of this document. + +### Maintainer + +To become a maintainer follow the steps [outlined in the handbook](https://handbook.gitlab.com/handbook/engineering/workflow/code-review/#how-to-become-a-project-maintainer). +You are probably ready to become a maintainer when these statements feel true: + +- The MRs you have reviewed consistently make it through maintainer review without significant additionally required changes +- The MRs you have created consistently make it through reviewer and maintainer review without significant required changes +- You feel comfortable working through operational tasks + +If those subjective requirements are satisfied, [open an MR](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/merge_request_templates/Backend%20maintainer.md) +promoting you to maintainer and tag the existing maintainers. diff --git a/spec/finders/work_items/namespace_work_items_finder_spec.rb b/spec/finders/work_items/namespace_work_items_finder_spec.rb deleted file mode 100644 index 71fde0546ee..00000000000 --- a/spec/finders/work_items/namespace_work_items_finder_spec.rb +++ /dev/null @@ -1,128 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe WorkItems::NamespaceWorkItemsFinder, feature_category: :team_planning do - include AdminModeHelper - - describe '#execute' do - let_it_be(:group) { create(:group, :public) } - let_it_be(:sub_group) { create(:group, :private, parent: group) } - let_it_be(:project) { create(:project, :repository, :public, group: group) } - let_it_be(:user) { create(:user) } - let_it_be(:reporter) { create(:user).tap { |user| group.add_reporter(user) } } - let_it_be(:guest) { create(:user).tap { |user| group.add_guest(user) } } - let_it_be(:guest_author) { create(:user).tap { |user| group.add_guest(user) } } - let_it_be(:banned_user) { create(:banned_user) } - - let_it_be(:project_work_item) { create(:work_item, project: project) } - let_it_be(:sub_group_work_item) do - create(:work_item, namespace: sub_group, author: reporter) - end - - let_it_be(:group_work_item) do - create(:work_item, namespace: group, author: reporter) - end - - let_it_be(:group_confidential_work_item, reload: true) do - create(:work_item, :confidential, namespace: group, author: guest_author) - end - - let_it_be(:sub_group_confidential_work_item, reload: true) do - create(:work_item, :confidential, namespace: sub_group, author: guest_author) - end - - let_it_be(:hidden_work_item) do - create(:work_item, :confidential, namespace: group, author: banned_user.user) - end - - let_it_be(:other_work_item) { create(:work_item) } - let(:finder_params) { {} } - let(:current_user) { user } - let(:namespace) { nil } - - subject do - described_class.new(current_user, finder_params.merge( - namespace_id: namespace - )).execute - end - - context 'when no parent is provided' do - it { is_expected.to be_empty } - end - - context 'when the namespace is private' do - let(:namespace) { sub_group } - - context 'when the user cannot read the namespace' do - it { is_expected.to be_empty } - end - - context 'when the user can not see confidential work_items' do - let(:current_user) { guest } - - it { is_expected.to contain_exactly(sub_group_work_item) } - - context 'when the user is the author of the work item' do - let(:current_user) { guest_author } - - it { is_expected.to contain_exactly(sub_group_work_item, sub_group_confidential_work_item) } - end - - context 'when the user is assigned to a confidential work item' do - before do - sub_group_confidential_work_item.update!(assignees: [current_user]) - end - - it { is_expected.to contain_exactly(sub_group_work_item, sub_group_confidential_work_item) } - end - end - - context 'when the user can see confidential work_items' do - let(:current_user) { reporter } - - it { is_expected.to contain_exactly(sub_group_work_item, sub_group_confidential_work_item) } - end - end - - context 'when the namespace is public' do - let(:namespace) { group } - - context 'when user is admin' do - let(:current_user) { create(:user, :admin).tap { |u| enable_admin_mode!(u) } } - - it { is_expected.to contain_exactly(group_work_item, group_confidential_work_item, hidden_work_item) } - end - - context 'with an anonymous user' do - let(:current_user) { nil } - - it { is_expected.to contain_exactly(group_work_item) } - end - - context 'when the user can not see confidential work_items' do - it { is_expected.to contain_exactly(group_work_item) } - - context 'when the user is the author of the work item' do - let(:current_user) { guest_author } - - it { is_expected.to contain_exactly(group_work_item, group_confidential_work_item) } - end - - context 'when the user is assigned to a confidential work item' do - before do - group_confidential_work_item.update!(assignees: [current_user]) - end - - it { is_expected.to contain_exactly(group_work_item, group_confidential_work_item) } - end - end - - context 'when the user can see confidential work_items' do - let(:current_user) { reporter } - - it { is_expected.to contain_exactly(group_work_item, group_confidential_work_item) } - end - end - end -end diff --git a/spec/mailers/previews_spec.rb b/spec/mailers/previews_spec.rb index e1af0d7ef77..cbf51943d5a 100644 --- a/spec/mailers/previews_spec.rb +++ b/spec/mailers/previews_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe 'Mailer previews' do +RSpec.describe 'Mailer previews', feature_category: :shared do # Setup needed for email previews let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, :repository, :import_failed, group: group, import_last_error: 'some error') } @@ -14,6 +14,7 @@ RSpec.describe 'Mailer previews' do let_it_be(:remote_mirror) { create(:remote_mirror, project: project) } let_it_be(:member) { create(:project_member, :maintainer, project: project, created_by: user) } let_it_be(:review) { create(:review, project: project, merge_request: merge_request, author: user) } + let_it_be(:key) { create(:key, user: user) } Gitlab.ee do let_it_be(:epic) { create(:epic, group: group) } diff --git a/spec/models/work_item_spec.rb b/spec/models/work_item_spec.rb index 68e9e8ee50d..843e3d40dc2 100644 --- a/spec/models/work_item_spec.rb +++ b/spec/models/work_item_spec.rb @@ -86,21 +86,6 @@ RSpec.describe WorkItem, feature_category: :portfolio_management do end end - describe '.with_confidentiality_check' do - let(:user) { create(:user) } - let!(:authored_work_item) { create(:work_item, :confidential, project: reusable_project, author: user) } - let!(:assigned_work_item) { create(:work_item, :confidential, project: reusable_project, assignees: [user]) } - let!(:public_work_item) { create(:work_item, project: reusable_project) } - - before do - create(:work_item, :confidential, project: reusable_project) - end - - subject { described_class.with_confidentiality_check(user) } - - it { is_expected.to contain_exactly(public_work_item, authored_work_item, assigned_work_item) } - end - describe '#noteable_target_type_name' do it 'returns `issue` as the target name' do work_item = build(:work_item) diff --git a/spec/requests/api/graphql/group/issues_spec.rb b/spec/requests/api/graphql/group/issues_spec.rb index 1da6abf3cac..93ecaee03ac 100644 --- a/spec/requests/api/graphql/group/issues_spec.rb +++ b/spec/requests/api/graphql/group/issues_spec.rb @@ -15,8 +15,6 @@ RSpec.describe 'getting an issue list for a group', feature_category: :team_plan let_it_be(:issue2) { create(:issue, project: project2) } let_it_be(:issue3) { create(:issue, project: project3) } - let_it_be(:group_level_issue) { create(:issue, :epic, :group_level, namespace: group1) } - let(:issue1_gid) { issue1.to_global_id.to_s } let(:issue2_gid) { issue2.to_global_id.to_s } let(:issues_data) { graphql_data['group']['issues']['edges'] } @@ -145,6 +143,8 @@ RSpec.describe 'getting an issue list for a group', feature_category: :team_plan end context 'when querying epic types' do + let_it_be(:group_level_issue) { create(:issue, :epic, :group_level, namespace: group1) } + let(:query) do graphql_query_for( 'group', diff --git a/spec/requests/api/graphql/group/work_items_spec.rb b/spec/requests/api/graphql/group/work_items_spec.rb index ef96ef4754a..cadd95a1537 100644 --- a/spec/requests/api/graphql/group/work_items_spec.rb +++ b/spec/requests/api/graphql/group/work_items_spec.rb @@ -56,19 +56,6 @@ RSpec.describe 'getting a work_item list for a group', feature_category: :team_p end end - context 'when filtering by search' do - let(:item_filter_params) { { search: 'search_term', in: [:DESCRIPTION] } } - - # TODO: https://gitlab.com/gitlab-org/gitlab/-/work_items/393126 - it 'returns an error since search is not implemented at the group level yet' do - post_graphql(query, current_user: current_user) - - expect(graphql_errors).to contain_exactly( - hash_including('message' => 'Searching is not available for work items at the namespace level yet') - ) - end - end - context 'when the user can not see confidential work_items' do it_behaves_like 'a working graphql query' do before do @@ -80,6 +67,7 @@ RSpec.describe 'getting a work_item list for a group', feature_category: :team_p post_graphql(query, current_user: current_user) expect(work_item_ids).to contain_exactly( + project_work_item.to_global_id.to_s, group_work_item.to_global_id.to_s ) end @@ -91,9 +79,11 @@ RSpec.describe 'getting a work_item list for a group', feature_category: :team_p it 'returns also confidential work_items' do post_graphql(query, current_user: current_user) - expect(work_item_ids).to eq([ - confidential_work_item.to_global_id.to_s, group_work_item.to_global_id.to_s - ]) + expect(work_item_ids).to contain_exactly( + project_work_item.to_global_id.to_s, + confidential_work_item.to_global_id.to_s, + group_work_item.to_global_id.to_s + ) end context 'when the namespace_level_work_items feature flag is disabled' do diff --git a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb index 2ad2fcec39e..4e3fada649f 100644 --- a/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb +++ b/spec/support/shared_contexts/finders/issues_finder_shared_contexts.rb @@ -63,9 +63,9 @@ RSpec.shared_context 'IssuesFinder context' do ) end - let_it_be(:group_level_item) { create(:issue, :epic, :group_level, namespace: group, author: user) } + let_it_be(:group_level_item) { create(:issue, :group_level, namespace: group, author: user) } let_it_be(:group_level_confidential_item) do - create(:issue, :confidential, :epic, :group_level, namespace: group, author: user2) + create(:issue, :confidential, :group_level, namespace: group, author: user2) end let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: item1) } diff --git a/spec/support/shared_contexts/finders/work_items_finder_shared_contexts.rb b/spec/support/shared_contexts/finders/work_items_finder_shared_contexts.rb index 39e2819235b..f72b0382c7c 100644 --- a/spec/support/shared_contexts/finders/work_items_finder_shared_contexts.rb +++ b/spec/support/shared_contexts/finders/work_items_finder_shared_contexts.rb @@ -66,7 +66,6 @@ RSpec.shared_context 'WorkItemsFinder context' do let_it_be(:group_level_item) do create( :work_item, - :epic, namespace: group, author: user ) @@ -76,7 +75,6 @@ RSpec.shared_context 'WorkItemsFinder context' do create( :work_item, :confidential, - :epic, namespace: group, author: user2 ) diff --git a/spec/support/shared_examples/finders/issues_finder_shared_examples.rb b/spec/support/shared_examples/finders/issues_finder_shared_examples.rb index a5fee9c5fed..472387fa610 100644 --- a/spec/support/shared_examples/finders/issues_finder_shared_examples.rb +++ b/spec/support/shared_examples/finders/issues_finder_shared_examples.rb @@ -22,18 +22,10 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context it 'returns no items' do expect(items).to be_empty end - - context 'when there are group-level work items' do - let!(:group_work_item) { create(:work_item, namespace: create(:group)) } - - it 'returns no items' do - expect(items).to be_empty - end - end end context 'when filtering by group id' do - let(:params) { { group_id: group.id } } + let(:params) { { group_id: subgroup.id } } it 'returns no items' do expect(items).to be_empty @@ -216,7 +208,7 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context context 'when include_subgroup param not set' do it 'returns all group items' do - expect(items).to contain_exactly(item1, item5) + expect(items).to contain_exactly(item1, item5, group_level_item) end context 'when projects outside the group are passed' do @@ -247,7 +239,7 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context let(:params) { { group_id: group.id, release_tag: 'dne-release-tag' } } it 'ignores the release_tag parameter' do - expect(items).to contain_exactly(item1, item5) + expect(items).to contain_exactly(item1, item5, group_level_item) end end end @@ -258,7 +250,7 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context end it 'returns all group and subgroup items' do - expect(items).to contain_exactly(item1, item4, item5) + expect(items).to contain_exactly(item1, item4, item5, group_level_item) end context 'when mixed projects are passed' do @@ -270,31 +262,23 @@ RSpec.shared_examples 'issues or work items finder' do |factory, execute_context end end - context 'when querying group-level items' do - let(:params) { { group_id: group.id, issue_types: %w[issue epic] } } - - it 'includes group-level items' do - expect(items).to contain_exactly(item1, item5, group_level_item) + context 'when user has access to confidential items' do + before do + group.add_reporter(user) end - context 'when user has access to confidential items' do - before do - group.add_reporter(user) - end - - it 'includes confidential group-level items' do - expect(items).to contain_exactly(item1, item5, group_level_item, group_level_confidential_item) - end + it 'includes confidential group-level items' do + expect(items).to contain_exactly(item1, item5, group_level_item, group_level_confidential_item) end + end - context 'when namespace_level_work_items is disabled' do - before do - stub_feature_flags(namespace_level_work_items: false) - end + context 'when namespace_level_work_items is disabled' do + before do + stub_feature_flags(namespace_level_work_items: false) + end - it 'only returns project-level items' do - expect(items).to contain_exactly(item1, item5) - end + it 'only returns project-level items' do + expect(items).to contain_exactly(item1, item5) end end end |