From a8632f50992a5304304e122fc7dfff1fd87b3c09 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Thu, 31 Aug 2023 12:09:59 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- .../dependency_proxy/app_spec.js | 10 +- .../components/revision_dropdown_legacy_spec.js | 136 --------------------- .../super_sidebar/components/nav_item_spec.js | 60 ++++++++- .../components/tracing_details_span_chart_spec.js | 6 +- .../tracing/components/tracing_table_list_spec.js | 2 +- spec/graphql/types/issue_type_spec.rb | 2 +- spec/helpers/sidebars_helper_spec.rb | 97 ++++++++++----- spec/lib/bulk_imports/network_error_spec.rb | 30 ++++- spec/lib/bulk_imports/pipeline/runner_spec.rb | 2 +- spec/lib/sidebars/admin/panel_spec.rb | 1 + .../sidebars/groups/super_sidebar_panel_spec.rb | 1 + spec/lib/sidebars/organizations/panel_spec.rb | 1 + .../organizations/super_sidebar_panel_spec.rb | 1 + spec/lib/sidebars/panel_spec.rb | 18 ++- .../sidebars/projects/super_sidebar_panel_spec.rb | 1 + spec/lib/sidebars/search/panel_spec.rb | 1 + spec/lib/sidebars/user_profile/panel_spec.rb | 1 + spec/lib/sidebars/user_settings/panel_spec.rb | 1 + spec/lib/sidebars/your_work/panel_spec.rb | 1 + spec/requests/api/settings_spec.rb | 3 +- .../merge_requests/create_ref_service_spec.rb | 8 +- .../shared_examples/lib/menus_shared_examples.rb | 7 ++ .../api/graphql/issue_list_shared_examples.rb | 33 +++++ 23 files changed, 230 insertions(+), 193 deletions(-) delete mode 100644 spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js (limited to 'spec') diff --git a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js index 4fd7957674d..dd70fca9dd2 100644 --- a/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js +++ b/spec/frontend/packages_and_registries/dependency_proxy/app_spec.js @@ -1,12 +1,12 @@ import { GlAlert, - GlDropdown, - GlDropdownItem, GlFormInputGroup, GlFormGroup, GlModal, GlSprintf, GlSkeletonLoader, + GlDisclosureDropdown, + GlDisclosureDropdownItem, } from '@gitlab/ui'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; @@ -63,8 +63,6 @@ describe('DependencyProxyApp', () => { router, stubs: { GlAlert, - GlDropdown, - GlDropdownItem, GlFormGroup, GlModal, GlSprintf, @@ -82,7 +80,7 @@ describe('DependencyProxyApp', () => { const findProxyCountText = () => wrapper.findByTestId('proxy-count'); const findManifestList = () => wrapper.findComponent(ManifestsList); const findLoader = () => wrapper.findComponent(GlSkeletonLoader); - const findClearCacheDropdownList = () => wrapper.findComponent(GlDropdown); + const findClearCacheDropdownList = () => wrapper.findComponent(GlDisclosureDropdown); const findClearCacheModal = () => wrapper.findComponent(GlModal); const findClearCacheAlert = () => wrapper.findComponent(GlAlert); const findSettingsLink = () => wrapper.findByTestId('settings-link'); @@ -283,7 +281,7 @@ describe('DependencyProxyApp', () => { expect(findClearCacheDropdownList().exists()).toBe(true); const clearCacheDropdownItem = findClearCacheDropdownList().findComponent( - GlDropdownItem, + GlDisclosureDropdownItem, ); expect(clearCacheDropdownItem.text()).toBe('Clear cache'); diff --git a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js b/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js deleted file mode 100644 index e289569f8ce..00000000000 --- a/spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js +++ /dev/null @@ -1,136 +0,0 @@ -import { GlDropdown, GlDropdownItem } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; -import AxiosMockAdapter from 'axios-mock-adapter'; -import waitForPromises from 'helpers/wait_for_promises'; -import { createAlert } from '~/alert'; -import axios from '~/lib/utils/axios_utils'; -import { HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK } from '~/lib/utils/http_status'; -import RevisionDropdown from '~/projects/compare/components/revision_dropdown_legacy.vue'; - -const defaultProps = { - refsProjectPath: 'some/refs/path', - revisionText: 'Target', - paramsName: 'from', - paramsBranch: 'main', -}; - -jest.mock('~/alert'); - -describe('RevisionDropdown component', () => { - let wrapper; - let axiosMock; - - const createComponent = (props = {}) => { - wrapper = shallowMount(RevisionDropdown, { - propsData: { - ...defaultProps, - ...props, - }, - }); - }; - - beforeEach(() => { - axiosMock = new AxiosMockAdapter(axios); - createComponent(); - }); - - afterEach(() => { - axiosMock.restore(); - }); - - const findGlDropdown = () => wrapper.findComponent(GlDropdown); - const findBranchesDropdownItem = () => - wrapper.findAllComponents('[data-testid="branches-dropdown-item"]'); - const findTagsDropdownItem = () => - wrapper.findAllComponents('[data-testid="tags-dropdown-item"]'); - - it('sets hidden input', () => { - expect(wrapper.find('input[type="hidden"]').attributes('value')).toBe( - defaultProps.paramsBranch, - ); - }); - - it('update the branches on success', async () => { - const Branches = ['branch-1', 'branch-2']; - const Tags = ['tag-1', 'tag-2', 'tag-3']; - - axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(HTTP_STATUS_OK, { - Branches, - Tags, - }); - - createComponent(); - - expect(findBranchesDropdownItem()).toHaveLength(0); - expect(findTagsDropdownItem()).toHaveLength(0); - - await waitForPromises(); - - Branches.forEach((branch, index) => { - expect(findBranchesDropdownItem().at(index).text()).toBe(branch); - }); - - Tags.forEach((tag, index) => { - expect(findTagsDropdownItem().at(index).text()).toBe(tag); - }); - - expect(findBranchesDropdownItem()).toHaveLength(Branches.length); - expect(findTagsDropdownItem()).toHaveLength(Tags.length); - }); - - it('sets branches and tags to be an empty array when no tags or branches are given', async () => { - axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(HTTP_STATUS_OK, { - Branches: undefined, - Tags: undefined, - }); - - await waitForPromises(); - - expect(findBranchesDropdownItem()).toHaveLength(0); - expect(findTagsDropdownItem()).toHaveLength(0); - }); - - it('shows an alert on error', async () => { - axiosMock.onGet('some/invalid/path').replyOnce(HTTP_STATUS_NOT_FOUND); - - await waitForPromises(); - - expect(createAlert).toHaveBeenCalled(); - }); - - describe('GlDropdown component', () => { - it('renders props', () => { - expect(wrapper.props()).toEqual(expect.objectContaining(defaultProps)); - }); - - it('display default text', () => { - createComponent({ - paramsBranch: null, - }); - expect(findGlDropdown().props('text')).toBe('Select branch/tag'); - }); - - it('display params branch text', () => { - expect(findGlDropdown().props('text')).toBe(defaultProps.paramsBranch); - }); - - it('emits a "selectRevision" event when a revision is selected', async () => { - const findGlDropdownItems = () => wrapper.findAllComponents(GlDropdownItem); - const findFirstGlDropdownItem = () => findGlDropdownItems().at(0); - const branchName = 'some-branch'; - - axiosMock.onGet(defaultProps.refsProjectPath).replyOnce(HTTP_STATUS_OK, { - Branches: [branchName], - }); - - createComponent(); - await waitForPromises(); - - findFirstGlDropdownItem().vm.$emit('click'); - - expect(wrapper.emitted()).toEqual({ - selectRevision: [[{ direction: 'from', revision: branchName }]], - }); - }); - }); -}); diff --git a/spec/frontend/super_sidebar/components/nav_item_spec.js b/spec/frontend/super_sidebar/components/nav_item_spec.js index f41f6954ed1..589db349dc6 100644 --- a/spec/frontend/super_sidebar/components/nav_item_spec.js +++ b/spec/frontend/super_sidebar/components/nav_item_spec.js @@ -1,5 +1,6 @@ -import { GlBadge } from '@gitlab/ui'; +import { GlBadge, GlButton } from '@gitlab/ui'; import { RouterLinkStub } from '@vue/test-utils'; +import { nextTick } from 'vue'; import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper'; import NavItem from '~/super_sidebar/components/nav_item.vue'; import NavItemRouterLink from '~/super_sidebar/components/nav_item_router_link.vue'; @@ -15,6 +16,7 @@ describe('NavItem component', () => { const findLink = () => wrapper.findByTestId('nav-item-link'); const findPill = () => wrapper.findComponent(GlBadge); + const findPinButton = () => wrapper.findComponent(GlButton); const findNavItemRouterLink = () => extendedWrapper(wrapper.findComponent(NavItemRouterLink)); const findNavItemLink = () => extendedWrapper(wrapper.findComponent(NavItemLink)); @@ -59,6 +61,62 @@ describe('NavItem component', () => { ); }); + describe('pins', () => { + describe('when pins are not supported', () => { + it('does not render pin button', () => { + createWrapper({ + item: { title: 'Foo' }, + provide: { + panelSupportsPins: false, + }, + }); + + expect(findPinButton().exists()).toBe(false); + }); + }); + + describe('when pins are supported', () => { + beforeEach(() => { + createWrapper({ + item: { title: 'Foo' }, + provide: { + panelSupportsPins: true, + }, + }); + }); + + it('renders pin button', () => { + expect(findPinButton().exists()).toBe(true); + }); + + it('toggles pointer events on after CSS fade-in', async () => { + const pinButton = findPinButton(); + + expect(pinButton.classes()).toContain('gl-pointer-events-none'); + + wrapper.trigger('mouseenter'); + pinButton.vm.$emit('transitionend'); + await nextTick(); + + expect(pinButton.classes()).not.toContain('gl-pointer-events-none'); + }); + + it('does not toggle pointer events if mouse leaves before CSS fade-in ends', async () => { + const pinButton = findPinButton(); + + expect(pinButton.classes()).toContain('gl-pointer-events-none'); + + wrapper.trigger('mouseenter'); + wrapper.trigger('mousemove'); + wrapper.trigger('mouseleave'); + pinButton.vm.$emit('transitionend'); + await nextTick(); + + expect(pinButton.classes()).toContain('gl-pointer-events-none'); + }); + }); + }); + it('applies custom link classes', () => { const customClass = 'customClass'; createWrapper({ diff --git a/spec/frontend/tracing/components/tracing_details_span_chart_spec.js b/spec/frontend/tracing/components/tracing_details_span_chart_spec.js index 0ca4288333b..aaa02aef406 100644 --- a/spec/frontend/tracing/components/tracing_details_span_chart_spec.js +++ b/spec/frontend/tracing/components/tracing_details_span_chart_spec.js @@ -1,4 +1,4 @@ -import { GlButton } from '@gitlab/ui'; +import { GlButton, GlTruncate } from '@gitlab/ui'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import TracingDetailsSpansChart from '~/tracing/components/tracing_details_spans_chart.vue'; @@ -111,7 +111,9 @@ describe('TracingDetailsSpansChart', () => { }); it('renders span operation and service name', () => { - expect(getSpanDetails(0).text()).toBe('operation-1 service-1'); + const textContents = getSpanDetails(0).findAllComponents(GlTruncate); + expect(textContents.at(0).props('text')).toBe('operation-1'); + expect(textContents.at(1).props('text')).toBe('service-1'); }); it('renders the expanded button', () => { diff --git a/spec/frontend/tracing/components/tracing_table_list_spec.js b/spec/frontend/tracing/components/tracing_table_list_spec.js index b05d152599b..1930ebe6b4e 100644 --- a/spec/frontend/tracing/components/tracing_table_list_spec.js +++ b/spec/frontend/tracing/components/tracing_table_list_spec.js @@ -49,7 +49,7 @@ describe('TracingTableList', () => { mockTraces.forEach((trace, i) => { expect(getCells(i).length).toBe(4); - expect(getCell(i, 0).text()).toBe(trace.timestamp); + expect(getCell(i, 0).text()).toBe('Jul 10, 2023 3:02pm UTC'); expect(getCell(i, 1).text()).toBe(trace.service_name); expect(getCell(i, 2).text()).toBe(trace.operation); expect(getCell(i, 3).text()).toBe(`${trace.duration_nano / 1000} ms`); diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb index 6c4e68fba6b..d4d0eff9adb 100644 --- a/spec/graphql/types/issue_type_spec.rb +++ b/spec/graphql/types/issue_type_spec.rb @@ -21,7 +21,7 @@ RSpec.describe GitlabSchema.types['Issue'] do confidential hidden discussion_locked upvotes downvotes merge_requests_count user_notes_count user_discussions_count web_path web_url relative_position emails_disabled emails_enabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status design_collection alert_management_alert alert_management_alerts severity current_user_todos moved moved_to - closed_as_duplicate_of create_note_email timelogs project_id customer_relations_contacts escalation_status] + closed_as_duplicate_of create_note_email timelogs project_id customer_relations_contacts escalation_status external_author] fields.each do |field_name| expect(described_class).to have_graphql_field(field_name) diff --git a/spec/helpers/sidebars_helper_spec.rb b/spec/helpers/sidebars_helper_spec.rb index 4109eb01caa..d87e01eaeb0 100644 --- a/spec/helpers/sidebars_helper_spec.rb +++ b/spec/helpers/sidebars_helper_spec.rb @@ -488,7 +488,6 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do end describe '#super_sidebar_nav_panel' do - let(:user) { build(:user) } let(:group) { build(:group) } let(:project) { build(:project) } let(:organization) { build(:organization) } @@ -500,48 +499,84 @@ RSpec.describe SidebarsHelper, feature_category: :navigation do { current_user: nil, container: group, show_discover_group_security: false }) allow(group).to receive(:to_global_id).and_return(5) - Rails.cache.write(['users', user.id, 'assigned_open_issues_count'], 1) - Rails.cache.write(['users', user.id, 'assigned_open_merge_requests_count'], 4) - Rails.cache.write(['users', user.id, 'review_requested_open_merge_requests_count'], 0) - Rails.cache.write(['users', user.id, 'todos_pending_count'], 3) end - it 'returns Project Panel for project nav' do - expect(helper.super_sidebar_nav_panel(nav: 'project')).to be_a(Sidebars::Projects::SuperSidebarPanel) - end + shared_examples 'nav panels available to logged-out users' do + it 'returns Project Panel for project nav' do + expect(helper.super_sidebar_nav_panel(nav: 'project', + user: user)).to be_a(Sidebars::Projects::SuperSidebarPanel) + end - it 'returns Group Panel for group nav' do - expect(helper.super_sidebar_nav_panel(nav: 'group')).to be_a(Sidebars::Groups::SuperSidebarPanel) - end + it 'returns Group Panel for group nav' do + expect(helper.super_sidebar_nav_panel(nav: 'group', user: user)).to be_a(Sidebars::Groups::SuperSidebarPanel) + end - it 'returns User Settings Panel for profile nav' do - expect(helper.super_sidebar_nav_panel(nav: 'profile')).to be_a(Sidebars::UserSettings::Panel) - end + it 'returns User profile Panel for user profile nav' do + viewed_user = build(:user) + expect(helper.super_sidebar_nav_panel(nav: 'user_profile', user: user, + viewed_user: viewed_user)).to be_a(Sidebars::UserProfile::Panel) + end - it 'returns User profile Panel for user profile nav' do - expect(helper.super_sidebar_nav_panel(nav: 'user_profile')).to be_a(Sidebars::UserProfile::Panel) - end + it 'returns Explore Panel for explore nav' do + expect(helper.super_sidebar_nav_panel(nav: 'explore', user: user)).to be_a(Sidebars::Explore::Panel) + end - it 'returns Admin Panel for admin nav' do - expect(helper.super_sidebar_nav_panel(nav: 'admin')).to be_a(Sidebars::Admin::Panel) - end + it 'returns Organization Panel for organization nav' do + expect( + helper.super_sidebar_nav_panel(nav: 'organization', organization: organization, user: user) + ).to be_a(Sidebars::Organizations::SuperSidebarPanel) + end - it 'returns Organization Panel for organization nav' do - expect( - helper.super_sidebar_nav_panel(nav: 'organization', organization: organization) - ).to be_a(Sidebars::Organizations::SuperSidebarPanel) + it 'returns Search Panel for search nav' do + expect(helper.super_sidebar_nav_panel(nav: 'search', user: user)).to be_a(Sidebars::Search::Panel) + end end - it 'returns "Your Work" Panel for your_work nav', :use_clean_rails_memory_store_caching do - expect(helper.super_sidebar_nav_panel(nav: 'your_work', user: user)).to be_a(Sidebars::YourWork::Panel) - end + describe 'when logged-in' do + let(:user) { build(:user) } - it 'returns Search Panel for search nav' do - expect(helper.super_sidebar_nav_panel(nav: 'search', user: user)).to be_a(Sidebars::Search::Panel) + before do + Rails.cache.write(['users', user.id, 'assigned_open_issues_count'], 1) + Rails.cache.write(['users', user.id, 'assigned_open_merge_requests_count'], 4) + Rails.cache.write(['users', user.id, 'review_requested_open_merge_requests_count'], 0) + Rails.cache.write(['users', user.id, 'todos_pending_count'], 3) + end + + it 'returns User Settings Panel for profile nav' do + expect(helper.super_sidebar_nav_panel(nav: 'profile', user: user)).to be_a(Sidebars::UserSettings::Panel) + end + + describe 'admin user' do + it 'returns Admin Panel for admin nav', :aggregate_failures do + allow(user).to receive(:can_admin_all_resources?).and_return(true) + + expect(helper.super_sidebar_nav_panel(nav: 'admin', user: user)).to be_a(Sidebars::Admin::Panel) + end + end + + it 'returns Your Work Panel for admin nav' do + expect(helper.super_sidebar_nav_panel(nav: 'admin', user: user)).to be_a(Sidebars::YourWork::Panel) + end + + it 'returns "Your Work" Panel for your_work nav', :use_clean_rails_memory_store_caching do + expect(helper.super_sidebar_nav_panel(nav: 'your_work', user: user)).to be_a(Sidebars::YourWork::Panel) + end + + it 'returns "Your Work" Panel as a fallback', :use_clean_rails_memory_store_caching do + expect(helper.super_sidebar_nav_panel(user: user)).to be_a(Sidebars::YourWork::Panel) + end + + it_behaves_like 'nav panels available to logged-out users' end - it 'returns "Your Work" Panel as a fallback', :use_clean_rails_memory_store_caching do - expect(helper.super_sidebar_nav_panel(user: user)).to be_a(Sidebars::YourWork::Panel) + describe 'when logged-out' do + let(:user) { nil } + + it_behaves_like 'nav panels available to logged-out users' + + it 'returns "Explore" Panel as a fallback' do + expect(helper.super_sidebar_nav_panel(user: user)).to be_a(Sidebars::Explore::Panel) + end end end diff --git a/spec/lib/bulk_imports/network_error_spec.rb b/spec/lib/bulk_imports/network_error_spec.rb index 54d6554df96..d5e2b739c8f 100644 --- a/spec/lib/bulk_imports/network_error_spec.rb +++ b/spec/lib/bulk_imports/network_error_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe BulkImports::NetworkError, :clean_gitlab_redis_cache do +RSpec.describe BulkImports::NetworkError, :clean_gitlab_redis_cache, feature_category: :importers do let(:tracker) { double(id: 1, stage: 2, entity: double(id: 3)) } describe '.new' do @@ -65,10 +65,32 @@ RSpec.describe BulkImports::NetworkError, :clean_gitlab_redis_cache do end describe '#retry_delay' do - it 'returns the default value when there is not a rate limit error' do - exception = described_class.new('foo') + context 'when the exception is not a rate limit error' do + let(:exception) { described_class.new('Error!') } - expect(exception.retry_delay).to eq(described_class::DEFAULT_RETRY_DELAY_SECONDS.seconds) + it 'returns the default value' do + expect(exception.retry_delay).to eq(described_class::DEFAULT_RETRY_DELAY_SECONDS.seconds) + end + + context 'when the exception is a decompression error' do + before do + allow(exception).to receive(:cause).and_return(Zlib::Error.new('Error!')) + end + + it 'returns the exception delay value' do + expect(exception.retry_delay).to eq(60.seconds) + end + end + + context 'when the exception is a no space left error' do + before do + allow(exception).to receive(:cause).and_return(Errno::ENOSPC.new('Error!')) + end + + it 'returns the exception delay value' do + expect(exception.retry_delay).to eq(120.seconds) + end + end end context 'when the exception is a rate limit error' do diff --git a/spec/lib/bulk_imports/pipeline/runner_spec.rb b/spec/lib/bulk_imports/pipeline/runner_spec.rb index e66f2d26911..2f54ab111c8 100644 --- a/spec/lib/bulk_imports/pipeline/runner_spec.rb +++ b/spec/lib/bulk_imports/pipeline/runner_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe BulkImports::Pipeline::Runner do +RSpec.describe BulkImports::Pipeline::Runner, feature_category: :importers do let(:extractor) do Class.new do def initialize(options = {}); end diff --git a/spec/lib/sidebars/admin/panel_spec.rb b/spec/lib/sidebars/admin/panel_spec.rb index 9c362f527f5..7e5b3fa54ad 100644 --- a/spec/lib/sidebars/admin/panel_spec.rb +++ b/spec/lib/sidebars/admin/panel_spec.rb @@ -28,4 +28,5 @@ RSpec.describe Sidebars::Admin::Panel, feature_category: :navigation do end it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' end diff --git a/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb b/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb index 52c3a35a9d7..6da04178441 100644 --- a/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb +++ b/spec/lib/sidebars/groups/super_sidebar_panel_spec.rb @@ -53,4 +53,5 @@ RSpec.describe Sidebars::Groups::SuperSidebarPanel, feature_category: :navigatio it_behaves_like 'a panel with uniquely identifiable menu items' it_behaves_like 'a panel with all menu_items categorized' + it_behaves_like 'a panel instantiable by the anonymous user' end diff --git a/spec/lib/sidebars/organizations/panel_spec.rb b/spec/lib/sidebars/organizations/panel_spec.rb index 1f0b8d72aef..edaa676aa41 100644 --- a/spec/lib/sidebars/organizations/panel_spec.rb +++ b/spec/lib/sidebars/organizations/panel_spec.rb @@ -14,4 +14,5 @@ RSpec.describe Sidebars::Organizations::Panel, feature_category: :navigation do end it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' end diff --git a/spec/lib/sidebars/organizations/super_sidebar_panel_spec.rb b/spec/lib/sidebars/organizations/super_sidebar_panel_spec.rb index 99b33a5edf8..0e8a650652b 100644 --- a/spec/lib/sidebars/organizations/super_sidebar_panel_spec.rb +++ b/spec/lib/sidebars/organizations/super_sidebar_panel_spec.rb @@ -36,4 +36,5 @@ RSpec.describe Sidebars::Organizations::SuperSidebarPanel, feature_category: :na end it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' end diff --git a/spec/lib/sidebars/panel_spec.rb b/spec/lib/sidebars/panel_spec.rb index 857cb1139b5..e4b3b973484 100644 --- a/spec/lib/sidebars/panel_spec.rb +++ b/spec/lib/sidebars/panel_spec.rb @@ -46,17 +46,25 @@ RSpec.describe Sidebars::Panel, feature_category: :navigation do end end - describe '#has_renderable_menus?' do - it 'returns false when no renderable menus' do - expect(panel.has_renderable_menus?).to be false + describe '#render?' do + it 'returns false with no menus' do + expect(panel.render?).to be false end - it 'returns true when no renderable menus' do + it 'returns false with no renderable menus' do + allow(menu1).to receive(:render?).and_return(false) + + panel.add_menu(menu1) + + expect(panel.render?).to be false + end + + it 'returns true with renderable menus' do allow(menu1).to receive(:render?).and_return(true) panel.add_menu(menu1) - expect(panel.has_renderable_menus?).to be true + expect(panel.render?).to be true end end diff --git a/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb index 3fc6cd5083f..e9cf6591037 100644 --- a/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb +++ b/spec/lib/sidebars/projects/super_sidebar_panel_spec.rb @@ -64,4 +64,5 @@ RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigat it_behaves_like 'a panel with uniquely identifiable menu items' it_behaves_like 'a panel with all menu_items categorized' + it_behaves_like 'a panel instantiable by the anonymous user' end diff --git a/spec/lib/sidebars/search/panel_spec.rb b/spec/lib/sidebars/search/panel_spec.rb index 39c0f112793..73f9fd2f103 100644 --- a/spec/lib/sidebars/search/panel_spec.rb +++ b/spec/lib/sidebars/search/panel_spec.rb @@ -12,6 +12,7 @@ RSpec.describe Sidebars::Search::Panel, feature_category: :navigation do subject { described_class.new(context) } it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' describe '#aria_label' do it 'returns the correct aria label' do diff --git a/spec/lib/sidebars/user_profile/panel_spec.rb b/spec/lib/sidebars/user_profile/panel_spec.rb index a2bf490bc58..628b70c9100 100644 --- a/spec/lib/sidebars/user_profile/panel_spec.rb +++ b/spec/lib/sidebars/user_profile/panel_spec.rb @@ -11,6 +11,7 @@ RSpec.describe Sidebars::UserProfile::Panel, feature_category: :navigation do subject { described_class.new(context) } it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' it 'implements #aria_label' do expect(subject.aria_label).to eq(s_('UserProfile|User profile navigation')) diff --git a/spec/lib/sidebars/user_settings/panel_spec.rb b/spec/lib/sidebars/user_settings/panel_spec.rb index d574652188d..c586ff9306d 100644 --- a/spec/lib/sidebars/user_settings/panel_spec.rb +++ b/spec/lib/sidebars/user_settings/panel_spec.rb @@ -10,6 +10,7 @@ RSpec.describe Sidebars::UserSettings::Panel, feature_category: :navigation do subject { described_class.new(context) } it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' it 'implements #super_sidebar_context_header' do expect(subject.super_sidebar_context_header).to eq({ title: _('User settings'), avatar: user.avatar_url }) diff --git a/spec/lib/sidebars/your_work/panel_spec.rb b/spec/lib/sidebars/your_work/panel_spec.rb index 65c2786a16d..e2ca422359a 100644 --- a/spec/lib/sidebars/your_work/panel_spec.rb +++ b/spec/lib/sidebars/your_work/panel_spec.rb @@ -10,6 +10,7 @@ RSpec.describe Sidebars::YourWork::Panel, feature_category: :navigation do subject { described_class.new(context) } it_behaves_like 'a panel with uniquely identifiable menu items' + it_behaves_like 'a panel instantiable by the anonymous user' it 'implements #super_sidebar_context_header' do expect(subject.super_sidebar_context_header).to eq({ title: 'Your work', icon: 'work' }) diff --git a/spec/requests/api/settings_spec.rb b/spec/requests/api/settings_spec.rb index 7d630f18681..ad52076523c 100644 --- a/spec/requests/api/settings_spec.rb +++ b/spec/requests/api/settings_spec.rb @@ -854,7 +854,8 @@ RSpec.describe API::Settings, 'Settings', :do_not_mock_admin_mode_setting, featu sentry_enabled: true, sentry_dsn: 'http://sentry.example.com', sentry_clientside_dsn: 'http://sentry.example.com', - sentry_environment: 'production' + sentry_environment: 'production', + sentry_clientside_traces_sample_rate: 0.25 } end diff --git a/spec/services/merge_requests/create_ref_service_spec.rb b/spec/services/merge_requests/create_ref_service_spec.rb index ea3ad61a30d..0538b07aa79 100644 --- a/spec/services/merge_requests/create_ref_service_spec.rb +++ b/spec/services/merge_requests/create_ref_service_spec.rb @@ -89,7 +89,7 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains it 'merges with a merge commit', :aggregate_failures do expect(result[:status]).to eq :success expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha) - expect(result[:source_sha]).to eq(project.repository.commit(target_ref).parents[1].sha) + expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha) expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( @@ -109,7 +109,7 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains it 'writes the squashed result', :aggregate_failures do expect(result[:status]).to eq :success expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha) - expect(result[:source_sha]).to eq(project.repository.commit(target_ref).parents[1].sha) + expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha) expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( @@ -128,7 +128,7 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains it 'writes the squashed result without a merge commit', :aggregate_failures do expect(result[:status]).to eq :success expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha) - expect(result[:source_sha]).to eq(project.repository.commit(target_ref).sha) + expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha) expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( match( @@ -146,7 +146,7 @@ RSpec.describe MergeRequests::CreateRefService, feature_category: :merge_trains it 'writes the rebased merged result', :aggregate_failures do expect(result[:status]).to eq :success expect(result[:commit_sha]).to eq(project.repository.commit(target_ref).sha) - expect(result[:source_sha]).to eq(project.repository.commit(target_ref).sha) + expect(result[:source_sha]).to eq(project.repository.commit(source_branch).sha) expect(result[:target_sha]).to eq(project.repository.commit(first_parent_ref).sha) expect(project.repository.commits(target_ref, limit: 10, order: 'topo').map(&:message)).to( eq( diff --git a/spec/support/shared_examples/lib/menus_shared_examples.rb b/spec/support/shared_examples/lib/menus_shared_examples.rb index 0aa98517444..575f48c43e0 100644 --- a/spec/support/shared_examples/lib/menus_shared_examples.rb +++ b/spec/support/shared_examples/lib/menus_shared_examples.rb @@ -62,6 +62,13 @@ RSpec.shared_examples_for 'not serializable as super_sidebar_menu_args' do end end +RSpec.shared_examples_for 'a panel instantiable by the anonymous user' do + it do + context.instance_variable_set(:@current_user, nil) + expect(described_class.new(context)).to be_a(described_class) + end +end + RSpec.shared_examples_for 'a panel with uniquely identifiable menu items' do let(:menu_items) do subject.instance_variable_get(:@menus) diff --git a/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb index 6eceb7c350d..04f340fef37 100644 --- a/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb @@ -518,6 +518,39 @@ RSpec.shared_examples 'graphql issue list request spec' do end end + context 'when fetching external participants' do + before_all do + issue_a.update!(external_author: 'user@example.com') + end + + let(:fields) do + <<~QUERY + nodes { + id + externalAuthor + } + QUERY + end + + it 'returns the email address' do + post_query + + emails = issues_data.pluck('externalAuthor').compact + expect(emails).to contain_exactly('user@example.com') + end + + context 'when user does not have access to view emails' do + let(:current_user) { external_user } + + it 'obfuscates the email address' do + post_query + + emails = issues_data.pluck('externalAuthor').compact + expect(emails).to contain_exactly("us*****@e*****.c**") + end + end + end + context 'when fetching escalation status' do let_it_be(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: issue_a) } let_it_be(:incident_type) { WorkItems::Type.default_by_type(:incident) } -- cgit v1.2.3