Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-08-31 15:09:59 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-08-31 15:09:59 +0300
commita8632f50992a5304304e122fc7dfff1fd87b3c09 (patch)
tree497a8c0bbb88abcebf7889c79f098ace8d0033bf /spec
parent3608a02eb461c2cadbac0e08c0c6edec471d6648 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/app_spec.js10
-rw-r--r--spec/frontend/projects/compare/components/revision_dropdown_legacy_spec.js136
-rw-r--r--spec/frontend/super_sidebar/components/nav_item_spec.js60
-rw-r--r--spec/frontend/tracing/components/tracing_details_span_chart_spec.js6
-rw-r--r--spec/frontend/tracing/components/tracing_table_list_spec.js2
-rw-r--r--spec/graphql/types/issue_type_spec.rb2
-rw-r--r--spec/helpers/sidebars_helper_spec.rb97
-rw-r--r--spec/lib/bulk_imports/network_error_spec.rb30
-rw-r--r--spec/lib/bulk_imports/pipeline/runner_spec.rb2
-rw-r--r--spec/lib/sidebars/admin/panel_spec.rb1
-rw-r--r--spec/lib/sidebars/groups/super_sidebar_panel_spec.rb1
-rw-r--r--spec/lib/sidebars/organizations/panel_spec.rb1
-rw-r--r--spec/lib/sidebars/organizations/super_sidebar_panel_spec.rb1
-rw-r--r--spec/lib/sidebars/panel_spec.rb18
-rw-r--r--spec/lib/sidebars/projects/super_sidebar_panel_spec.rb1
-rw-r--r--spec/lib/sidebars/search/panel_spec.rb1
-rw-r--r--spec/lib/sidebars/user_profile/panel_spec.rb1
-rw-r--r--spec/lib/sidebars/user_settings/panel_spec.rb1
-rw-r--r--spec/lib/sidebars/your_work/panel_spec.rb1
-rw-r--r--spec/requests/api/settings_spec.rb3
-rw-r--r--spec/services/merge_requests/create_ref_service_spec.rb8
-rw-r--r--spec/support/shared_examples/lib/menus_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/requests/api/graphql/issue_list_shared_examples.rb33
23 files changed, 230 insertions, 193 deletions
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) }