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>2021-04-01 15:08:56 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-01 15:08:56 +0300
commit50d66f5ece57dcfbe074d97703691a8d3c38f4ac (patch)
treec96aa5ffd1cb73c18e53356680cb9792d24c257b /spec
parentcfec4ed6fe77e4150b1ea83b87f407aa0cca944c (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/boards/new_issue_spec.rb6
-rw-r--r--spec/features/boards/sidebar_spec.rb40
-rw-r--r--spec/features/boards/sidebar_subscription_spec.rb54
-rw-r--r--spec/features/boards/sidebar_time_tracking_spec.rb52
-rw-r--r--spec/features/groups/board_spec.rb2
-rw-r--r--spec/features/groups/navbar_spec.rb4
-rw-r--r--spec/features/projects/navbar_spec.rb4
-rw-r--r--spec/features/users/terms_spec.rb2
-rw-r--r--spec/frontend/boards/board_new_issue_deprecated_spec.js16
-rw-r--r--spec/frontend/boards/components/board_new_issue_spec.js6
-rw-r--r--spec/frontend/members/components/avatars/user_avatar_spec.js16
-rw-r--r--spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js27
-rw-r--r--spec/frontend/members/components/filter_sort/sort_dropdown_spec.js4
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js12
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js11
-rw-r--r--spec/frontend/members/index_spec.js27
-rw-r--r--spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb4
-rw-r--r--spec/lib/gitlab/legacy_github_import/importer_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb2
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb12
-rw-r--r--spec/lib/gitlab/tracking_spec.rb5
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb30
-rw-r--r--spec/serializers/merge_request_poll_cached_widget_entity_spec.rb45
-rw-r--r--spec/serializers/merge_request_poll_widget_entity_spec.rb29
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb12
-rw-r--r--spec/support/matchers/exceed_query_limit.rb5
-rw-r--r--spec/support/shared_examples/features/sidebar_shared_examples.rb165
-rw-r--r--spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb10
30 files changed, 371 insertions, 237 deletions
diff --git a/spec/features/boards/new_issue_spec.rb b/spec/features/boards/new_issue_spec.rb
index 4d419f89aa3..feb0b0b992f 100644
--- a/spec/features/boards/new_issue_spec.rb
+++ b/spec/features/boards/new_issue_spec.rb
@@ -60,7 +60,7 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
@@ -85,7 +85,7 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('bug')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
@@ -100,7 +100,7 @@ RSpec.describe 'Issue Boards new issue', :js do
page.within(first('.board-new-issue-form')) do
find('.form-control').set('new issue')
- click_button 'Submit issue'
+ click_button 'Create issue'
end
wait_for_requests
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 57e88fac013..977147c3c6b 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -7,10 +7,10 @@ RSpec.describe 'Project issue boards sidebar', :js do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :public) }
- let_it_be(:issue) { create(:issue, project: project, relative_position: 1) }
let_it_be(:board) { create(:board, project: project) }
let_it_be(:list) { create(:list, board: board, position: 0) }
- let(:card) { find('.board:nth-child(1)').first('.board-card') }
+
+ let_it_be(:issue, reload: true) { create(:issue, project: project, relative_position: 1) }
before do
project.add_maintainer(user)
@@ -18,41 +18,17 @@ RSpec.describe 'Project issue boards sidebar', :js do
sign_in(user)
visit project_board_path(project, board)
- wait_for_requests
- end
-
- it 'shows sidebar when clicking issue' do
- click_card(card)
-
- expect(page).to have_selector('.issue-boards-sidebar')
- end
-
- it 'closes sidebar when clicking issue' do
- click_card(card)
- expect(page).to have_selector('.issue-boards-sidebar')
-
- click_card(card)
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
+ wait_for_requests
end
- it 'closes sidebar when clicking close button' do
- click_card(card)
+ it_behaves_like 'issue boards sidebar'
- expect(page).to have_selector('.issue-boards-sidebar')
-
- find("[data-testid='sidebar-drawer'] .gl-drawer-close-button").click
-
- expect(page).not_to have_selector('.issue-boards-sidebar')
+ def first_card
+ find('.board:nth-child(1)').first("[data-testid='board_card']")
end
- it 'shows issue details when sidebar is open' do
- click_card(card)
-
- page.within('.issue-boards-sidebar') do
- expect(page).to have_content(issue.title)
- expect(page).to have_content(issue.to_reference)
- end
+ def click_first_issue_card
+ click_card(first_card)
end
end
diff --git a/spec/features/boards/sidebar_subscription_spec.rb b/spec/features/boards/sidebar_subscription_spec.rb
deleted file mode 100644
index 598fec7514e..00000000000
--- a/spec/features/boards/sidebar_subscription_spec.rb
+++ /dev/null
@@ -1,54 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Project issue boards sidebar subscription', :js do
- include BoardHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:issue1) { create(:issue, project: project, relative_position: 1) }
- let_it_be(:issue2) { create(:issue, project: project, relative_position: 2) }
- let_it_be(:subscription) { create(:subscription, user: user, project: project, subscribable: issue2, subscribed: true) }
- let_it_be(:board) { create(:board, project: project) }
- let_it_be(:list) { create(:list, board: board, position: 0) }
- let(:card1) { find('.board:nth-child(1) .board-card:nth-of-type(1)') }
- let(:card2) { find('.board:nth-child(1) .board-card:nth-of-type(2)') }
-
- before do
- stub_feature_flags(graphql_board_lists: false)
-
- project.add_maintainer(user)
-
- sign_in(user)
-
- visit project_board_path(project, board)
- wait_for_requests
- end
-
- context 'subscription' do
- it 'changes issue subscription' do
- click_card(card1)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button:not(.is-checked)').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button.is-checked')
- end
- end
-
- it 'has checked subscription toggle when already subscribed' do
- click_card(card2)
- wait_for_requests
-
- page.within('.subscriptions') do
- find('[data-testid="subscription-toggle"] button.is-checked').click
- wait_for_requests
-
- expect(page).to have_css('[data-testid="subscription-toggle"] button:not(.is-checked)')
- end
- end
- end
-end
diff --git a/spec/features/boards/sidebar_time_tracking_spec.rb b/spec/features/boards/sidebar_time_tracking_spec.rb
deleted file mode 100644
index 3ac8b93692a..00000000000
--- a/spec/features/boards/sidebar_time_tracking_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Project issue boards sidebar time tracking', :js do
- include BoardHelpers
-
- let_it_be(:user) { create(:user) }
- let_it_be(:project) { create(:project, :public) }
- let_it_be(:board) { create(:board, project: project) }
- let_it_be(:list) { create(:list, board: board, position: 0) }
- let!(:issue) { create(:issue, project: project, relative_position: 1) }
- let(:card) { find('.board:nth-child(1)').first('.board-card') }
-
- let(:application_settings) { {} }
-
- before do
- stub_feature_flags(graphql_board_lists: false)
-
- project.add_maintainer(user)
-
- sign_in(user)
-
- stub_application_setting(application_settings)
-
- visit project_board_path(project, board)
- wait_for_requests
- end
-
- context 'time tracking' do
- let(:compare_meter_tooltip) { find('.time-tracking .time-tracking-content .compare-meter')['title'] }
-
- before do
- issue.timelogs.create!(time_spent: 14400, user: user)
- issue.update!(time_estimate: 128800)
-
- click_card(card)
- end
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 3d 7h 46m')
- end
-
- context 'when time_tracking_limit_to_hours is true' do
- let(:application_settings) { { time_tracking_limit_to_hours: true } }
-
- it 'shows time tracking progress bar' do
- expect(compare_meter_tooltip).to eq('Time remaining: 31h 46m')
- end
- end
- end
-end
diff --git a/spec/features/groups/board_spec.rb b/spec/features/groups/board_spec.rb
index aab3f5e68d5..b4c60ff4fa3 100644
--- a/spec/features/groups/board_spec.rb
+++ b/spec/features/groups/board_spec.rb
@@ -33,7 +33,7 @@ RSpec.describe 'Group Boards' do
find('.gl-new-dropdown-item button').click
end
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(page).to have_content(issue_title)
end
diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb
index 710755ce306..021b1af54d4 100644
--- a/spec/features/groups/navbar_spec.rb
+++ b/spec/features/groups/navbar_spec.rb
@@ -68,7 +68,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Kubernetes'))
+ insert_container_nav
visit group_path(group)
end
@@ -80,7 +80,7 @@ RSpec.describe 'Group navbar' do
before do
stub_config(dependency_proxy: { enabled: true })
- insert_dependency_proxy_nav(_('Dependency Proxy'))
+ insert_dependency_proxy_nav
visit group_path(group)
end
diff --git a/spec/features/projects/navbar_spec.rb b/spec/features/projects/navbar_spec.rb
index 4ff3827b240..7dc3ee63669 100644
--- a/spec/features/projects/navbar_spec.rb
+++ b/spec/features/projects/navbar_spec.rb
@@ -13,6 +13,8 @@ RSpec.describe 'Project navbar' do
before do
insert_package_nav(_('Operations'))
+ insert_infrastructure_registry_nav
+ stub_config(registry: { enabled: false })
project.add_maintainer(user)
sign_in(user)
@@ -60,7 +62,7 @@ RSpec.describe 'Project navbar' do
before do
stub_config(registry: { enabled: true })
- insert_container_nav(_('Operations'))
+ insert_container_nav
visit project_path(project)
end
diff --git a/spec/features/users/terms_spec.rb b/spec/features/users/terms_spec.rb
index 7500f2fe59a..8ba79d77c22 100644
--- a/spec/features/users/terms_spec.rb
+++ b/spec/features/users/terms_spec.rb
@@ -121,7 +121,7 @@ RSpec.describe 'Users > Terms' do
enforce_terms
- click_button 'Submit issue'
+ click_button 'Create issue'
expect(current_path).to eq(terms_path)
diff --git a/spec/frontend/boards/board_new_issue_deprecated_spec.js b/spec/frontend/boards/board_new_issue_deprecated_spec.js
index 3903ad201b2..3beaf870bf5 100644
--- a/spec/frontend/boards/board_new_issue_deprecated_spec.js
+++ b/spec/frontend/boards/board_new_issue_deprecated_spec.js
@@ -111,7 +111,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -122,7 +122,7 @@ describe('Issue boards new issue form', () => {
it('enables button after submit', () => {
jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -132,7 +132,7 @@ describe('Issue boards new issue form', () => {
});
it('clears title after submit', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -143,17 +143,17 @@ describe('Issue boards new issue form', () => {
it('sets detail issue after submit', () => {
expect(boardsStore.detail.issue.title).toBe(undefined);
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
.then(() => {
- expect(boardsStore.detail.issue.title).toBe('submit issue');
+ expect(boardsStore.detail.issue.title).toBe('create issue');
});
});
it('sets detail list after submit', () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -164,7 +164,7 @@ describe('Issue boards new issue form', () => {
it('sets detail weight after submit', () => {
boardsStore.weightFeatureAvailable = true;
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
@@ -175,7 +175,7 @@ describe('Issue boards new issue form', () => {
it('does not set detail weight after submit', () => {
boardsStore.weightFeatureAvailable = false;
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
return Vue.nextTick()
.then(submitIssue)
diff --git a/spec/frontend/boards/components/board_new_issue_spec.js b/spec/frontend/boards/components/board_new_issue_spec.js
index 737a18294bc..e6405bbcff3 100644
--- a/spec/frontend/boards/components/board_new_issue_spec.js
+++ b/spec/frontend/boards/components/board_new_issue_spec.js
@@ -86,7 +86,7 @@ describe('Issue boards new issue form', () => {
describe('submit success', () => {
it('creates new issue', async () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
@@ -95,7 +95,7 @@ describe('Issue boards new issue form', () => {
it('enables button after submit', async () => {
jest.spyOn(wrapper.vm, 'submit').mockImplementation();
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
@@ -103,7 +103,7 @@ describe('Issue boards new issue form', () => {
});
it('clears title after submit', async () => {
- wrapper.setData({ title: 'submit issue' });
+ wrapper.setData({ title: 'create issue' });
await vm.$nextTick();
await submitIssue();
diff --git a/spec/frontend/members/components/avatars/user_avatar_spec.js b/spec/frontend/members/components/avatars/user_avatar_spec.js
index 3f4d9155c5d..5cf3a4cdc13 100644
--- a/spec/frontend/members/components/avatars/user_avatar_spec.js
+++ b/spec/frontend/members/components/avatars/user_avatar_spec.js
@@ -1,31 +1,25 @@
import { GlAvatarLink, GlBadge } from '@gitlab/ui';
import { within } from '@testing-library/dom';
import { mount, createWrapper } from '@vue/test-utils';
-import Vue from 'vue';
-import Vuex from 'vuex';
import UserAvatar from '~/members/components/avatars/user_avatar.vue';
import { member as memberMock, member2faEnabled, orphanedMember } from '../../mock_data';
-Vue.use(Vuex);
-
describe('UserAvatar', () => {
let wrapper;
const { user } = memberMock;
- const createComponent = (propsData = {}, state = {}) => {
+ const createComponent = (propsData = {}, provide = {}) => {
wrapper = mount(UserAvatar, {
propsData: {
member: memberMock,
isCurrentUser: false,
...propsData,
},
- store: new Vuex.Store({
- state: {
- canManageMembers: true,
- ...state,
- },
- }),
+ provide: {
+ canManageMembers: true,
+ ...provide,
+ },
});
};
diff --git a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
index 14b437a8c4e..326a29747ef 100644
--- a/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
+++ b/spec/frontend/members/components/filter_sort/members_filtered_search_bar_spec.js
@@ -10,10 +10,9 @@ localVue.use(Vuex);
describe('MembersFilteredSearchBar', () => {
let wrapper;
- const createComponent = (state) => {
+ const createComponent = ({ state = {}, provide = {} } = {}) => {
const store = new Vuex.Store({
state: {
- sourceId: 1,
filteredSearchBar: {
show: true,
tokens: ['two_factor'],
@@ -21,13 +20,17 @@ describe('MembersFilteredSearchBar', () => {
placeholder: 'Filter members',
recentSearchesStorageKey: 'group_members',
},
- canManageMembers: true,
...state,
},
});
wrapper = shallowMount(MembersFilteredSearchBar, {
localVue,
+ provide: {
+ sourceId: 1,
+ canManageMembers: true,
+ ...provide,
+ },
store,
});
};
@@ -68,14 +71,18 @@ describe('MembersFilteredSearchBar', () => {
describe('when `canManageMembers` is false', () => {
it('excludes 2FA token', () => {
createComponent({
- filteredSearchBar: {
- show: true,
- tokens: ['two_factor', 'with_inherited_permissions'],
- searchParam: 'search',
- placeholder: 'Filter members',
- recentSearchesStorageKey: 'group_members',
+ state: {
+ filteredSearchBar: {
+ show: true,
+ tokens: ['two_factor', 'with_inherited_permissions'],
+ searchParam: 'search',
+ placeholder: 'Filter members',
+ recentSearchesStorageKey: 'group_members',
+ },
+ },
+ provide: {
+ canManageMembers: false,
},
- canManageMembers: false,
});
expect(findFilteredSearchBar().props('tokens')).toEqual([
diff --git a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
index 357fad741e9..390e12bc0e5 100644
--- a/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
+++ b/spec/frontend/members/components/filter_sort/sort_dropdown_spec.js
@@ -15,7 +15,6 @@ describe('SortDropdown', () => {
const createComponent = (state) => {
const store = new Vuex.Store({
state: {
- sourceId: 1,
tableSortableFields: ['account', 'granted', 'expires', 'maxRole', 'lastSignIn'],
filteredSearchBar: {
show: true,
@@ -30,6 +29,9 @@ describe('SortDropdown', () => {
wrapper = mount(SortDropdown, {
localVue,
+ provide: {
+ sourceId: 1,
+ },
store,
});
};
diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js
index b7dcd2a9fae..5375ee11736 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -42,21 +42,21 @@ describe('MembersTableCell', () => {
const createStore = (state = {}) => {
return new Vuex.Store({
- state: {
- sourceId: 1,
- currentUserId: 1,
- ...state,
- },
+ state,
});
};
let wrapper;
- const createComponent = (propsData, state = {}) => {
+ const createComponent = (propsData, state) => {
wrapper = mount(MembersTableCell, {
localVue,
propsData,
store: createStore(state),
+ provide: {
+ sourceId: 1,
+ currentUserId: 1,
+ },
scopedSlots: {
default: `
<wrapped-component
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index cf5811e72e7..0395dc39880 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -32,17 +32,20 @@ describe('MembersTable', () => {
table: { 'data-qa-selector': 'members_list' },
tr: { 'data-qa-selector': 'member_row' },
},
- sourceId: 1,
- currentUserId: 1,
...state,
},
});
};
- const createComponent = (state) => {
+ const createComponent = (state, provide = {}) => {
wrapper = mount(MembersTable, {
localVue,
store: createStore(state),
+ provide: {
+ sourceId: 1,
+ currentUserId: 1,
+ ...provide,
+ },
stubs: [
'member-avatar',
'member-source',
@@ -119,7 +122,7 @@ describe('MembersTable', () => {
describe('when user is not logged in', () => {
it('does not render the "Actions" field', () => {
- createComponent({ currentUserId: null, tableFields: ['actions'] });
+ createComponent({ tableFields: ['actions'] }, { currentUserId: null });
expect(within(wrapper.element).queryByTestId('col-actions')).toBe(null);
});
diff --git a/spec/frontend/members/index_spec.js b/spec/frontend/members/index_spec.js
index dd3b9ddd912..f40c08401d4 100644
--- a/spec/frontend/members/index_spec.js
+++ b/spec/frontend/members/index_spec.js
@@ -42,33 +42,6 @@ describe('initMembersApp', () => {
expect(wrapper.find(MembersApp).exists()).toBe(true);
});
- it('sets `currentUserId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.currentUserId).toBe(123);
- });
-
- describe('when `gon.current_user_id` is not set (user is not logged in)', () => {
- it('sets `currentUserId` as `null` in Vuex store', () => {
- window.gon = {};
- setup();
-
- expect(vm.$store.state.currentUserId).toBeNull();
- });
- });
-
- it('parses and sets `data-source-id` as `sourceId` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.sourceId).toBe(234);
- });
-
- it('parses and sets `data-can-manage-members` as `canManageMembers` in Vuex store', () => {
- setup();
-
- expect(vm.$store.state.canManageMembers).toBe(true);
- });
-
it('parses and sets `members` in Vuex store', () => {
setup();
diff --git a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
index 2a4478ded6b..24f5299d357 100644
--- a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
@@ -23,10 +23,10 @@ RSpec.describe Gitlab::ErrorTracking::Processor::ContextPayloadProcessor do
end
it 'merges the context payload into event payload', :aggregate_failures do
- expect(result_hash[:user]).to eq(ip_address: '127.0.0.1', username: 'root')
+ expect(result_hash[:user]).to include(ip_address: '127.0.0.1', username: 'root')
expect(result_hash[:tags])
- .to eq(priority: 'high',
+ .to include(priority: 'high',
locale: 'en',
program: 'test',
feature_category: 'feature_a',
diff --git a/spec/lib/gitlab/legacy_github_import/importer_spec.rb b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
index 56074147854..9a4d7bd996e 100644
--- a/spec/lib/gitlab/legacy_github_import/importer_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/importer_spec.rb
@@ -290,7 +290,7 @@ RSpec.describe Gitlab::LegacyGithubImport::Importer do
subject { described_class.new(project) }
before do
- project.update(import_type: 'gitea', import_url: "#{repo_root}/foo/group/project.git")
+ project.update!(import_type: 'gitea', import_url: "#{repo_root}/foo/group/project.git")
end
it_behaves_like 'Gitlab::LegacyGithubImport::Importer#execute' do
diff --git a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
index 4b1e0d2c144..454bab8846c 100644
--- a/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/issue_formatter_spec.rb
@@ -152,7 +152,7 @@ RSpec.describe Gitlab::LegacyGithubImport::IssueFormatter do
context 'when importing a Gitea project' do
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::IssueFormatter#attributes'
diff --git a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
index 148b59dedab..64fcc46d304 100644
--- a/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/milestone_formatter_spec.rb
@@ -92,7 +92,7 @@ RSpec.describe Gitlab::LegacyGithubImport::MilestoneFormatter do
let(:iid_attr) { :id }
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::MilestoneFormatter#attributes'
diff --git a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
index 3e6b9340d0b..7d8875e36c3 100644
--- a/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
+++ b/spec/lib/gitlab/legacy_github_import/pull_request_formatter_spec.rb
@@ -260,7 +260,7 @@ RSpec.describe Gitlab::LegacyGithubImport::PullRequestFormatter do
context 'when importing a Gitea project' do
before do
- project.update(import_type: 'gitea')
+ project.update!(import_type: 'gitea')
end
it_behaves_like 'Gitlab::LegacyGithubImport::PullRequestFormatter#attributes'
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index 561edbd38f8..dacd08cf12b 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -58,10 +58,16 @@ RSpec.describe Gitlab::Tracking::StandardContext do
end
context 'with extra data' do
- subject { described_class.new(foo: 'bar') }
+ subject { described_class.new(extra_key_1: 'extra value 1', extra_key_2: 'extra value 2') }
- it 'creates a Snowplow context with the given data' do
- expect(snowplow_context.to_json.dig(:data, :foo)).to eq('bar')
+ it 'includes extra data in `extra` hash' do
+ expect(snowplow_context.to_json.dig(:data, :extra)).to eq(extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
+ end
+ end
+
+ context 'without extra data' do
+ it 'contains an empty `extra` hash' do
+ expect(snowplow_context.to_json.dig(:data, :extra)).to be_empty
end
end
diff --git a/spec/lib/gitlab/tracking_spec.rb b/spec/lib/gitlab/tracking_spec.rb
index c1e69b94406..edc19df5e37 100644
--- a/spec/lib/gitlab/tracking_spec.rb
+++ b/spec/lib/gitlab/tracking_spec.rb
@@ -51,7 +51,7 @@ RSpec.describe Gitlab::Tracking do
expect(Gitlab::Tracking::StandardContext)
.to receive(:new)
- .with(project: project, user: user, namespace: namespace)
+ .with(project: project, user: user, namespace: namespace, extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
.and_call_original
expect_any_instance_of(klass).to receive(:event) do |_, category, action, args|
@@ -66,7 +66,8 @@ RSpec.describe Gitlab::Tracking do
end
described_class.event('category', 'action', label: 'label', property: 'property', value: 1.5,
- context: [other_context], project: project, user: user, namespace: namespace)
+ context: [other_context], project: project, user: user, namespace: namespace,
+ extra_key_1: 'extra value 1', extra_key_2: 'extra value 2')
end
end
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index aced094e219..03412fe1b66 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -490,6 +490,36 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state do
{ 'id' => job.id, 'name' => job.name, 'token' => job.token },
{ 'id' => job2.id, 'name' => job2.name, 'token' => job2.token })
end
+
+ describe 'preloading job_artifacts_archive' do
+ context 'when the feature flag is disabled' do
+ before do
+ stub_feature_flags(preload_associations_jobs_request_api_endpoint: false)
+ end
+
+ it 'queries the ci_job_artifacts table multiple times' do
+ expect { request_job }.to exceed_all_query_limit(1).for_model(::Ci::JobArtifact)
+ end
+
+ it 'queries the ci_builds table more than five times' do
+ expect { request_job }.to exceed_all_query_limit(5).for_model(::Ci::Build)
+ end
+ end
+
+ context 'when the feature flag is enabled' do
+ before do
+ stub_feature_flags(preload_associations_jobs_request_api_endpoint: true)
+ end
+
+ it 'queries the ci_job_artifacts table once only' do
+ expect { request_job }.not_to exceed_all_query_limit(1).for_model(::Ci::JobArtifact)
+ end
+
+ it 'queries the ci_builds table five times' do
+ expect { request_job }.not_to exceed_all_query_limit(5).for_model(::Ci::Build)
+ end
+ end
+ end
end
context 'when pipeline have jobs with artifacts' do
diff --git a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
index 380e20905c6..cad3d2e3373 100644
--- a/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_cached_widget_entity_spec.rb
@@ -268,4 +268,49 @@ RSpec.describe MergeRequestPollCachedWidgetEntity do
end
end
end
+
+ describe 'merge_pipeline' do
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+
+ context 'when is merged' do
+ let(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
+ let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it 'returns merge_pipeline' do
+ pipeline.reload
+ pipeline_payload =
+ MergeRequests::PipelineEntity
+ .represent(pipeline, request: request)
+ .as_json
+
+ expect(subject[:merge_pipeline]).to eq(pipeline_payload)
+ end
+
+ context 'when user cannot read pipelines on target project' do
+ before do
+ project.add_guest(user)
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+
+ context 'when merge_request_cached_merge_pipeline_serializer is disabled' do
+ before do
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: false)
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+ end
+ end
end
diff --git a/spec/serializers/merge_request_poll_widget_entity_spec.rb b/spec/serializers/merge_request_poll_widget_entity_spec.rb
index 3bf4f613167..9618624f226 100644
--- a/spec/serializers/merge_request_poll_widget_entity_spec.rb
+++ b/spec/serializers/merge_request_poll_widget_entity_spec.rb
@@ -6,9 +6,9 @@ RSpec.describe MergeRequestPollWidgetEntity do
include ProjectForksHelper
using RSpec::Parameterized::TableSyntax
- let(:project) { create :project, :repository }
- let(:resource) { create(:merge_request, source_project: project, target_project: project) }
- let(:user) { create(:user) }
+ let_it_be(:project) { create :project, :repository }
+ let_it_be(:resource) { create(:merge_request, source_project: project, target_project: project) }
+ let_it_be(:user) { create(:user) }
let(:request) { double('request', current_user: user, project: project) }
@@ -22,20 +22,33 @@ RSpec.describe MergeRequestPollWidgetEntity do
end
describe 'merge_pipeline' do
+ before do
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: false)
+ end
+
it 'returns nil' do
expect(subject[:merge_pipeline]).to be_nil
end
context 'when is merged' do
- let(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
- let(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
+ let_it_be(:resource) { create(:merged_merge_request, source_project: project, merge_commit_sha: project.commit.id) }
+ let_it_be(:pipeline) { create(:ci_empty_pipeline, project: project, ref: resource.target_branch, sha: resource.merge_commit_sha) }
before do
project.add_maintainer(user)
end
+ context 'when user cannot read pipelines on target project' do
+ before do
+ project.team.truncate
+ end
+
+ it 'returns nil' do
+ expect(subject[:merge_pipeline]).to be_nil
+ end
+ end
+
it 'returns merge_pipeline' do
- pipeline.reload
pipeline_payload =
MergeRequests::PipelineEntity
.represent(pipeline, request: request)
@@ -44,9 +57,9 @@ RSpec.describe MergeRequestPollWidgetEntity do
expect(subject[:merge_pipeline]).to eq(pipeline_payload)
end
- context 'when user cannot read pipelines on target project' do
+ context 'when merge_request_cached_merge_pipeline_serializer is enabled' do
before do
- project.add_guest(user)
+ stub_feature_flags(merge_request_cached_merge_pipeline_serializer: true)
end
it 'returns nil' do
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index e18a708e41c..826108a63a5 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -29,7 +29,7 @@ module NavbarStructureHelper
)
end
- def insert_container_nav(within)
+ def insert_container_nav
insert_after_sub_nav_item(
_('Package Registry'),
within: _('Packages & Registries'),
@@ -37,11 +37,19 @@ module NavbarStructureHelper
)
end
- def insert_dependency_proxy_nav(within)
+ def insert_dependency_proxy_nav
insert_after_sub_nav_item(
_('Package Registry'),
within: _('Packages & Registries'),
new_sub_nav_item_name: _('Dependency Proxy')
)
end
+
+ def insert_infrastructure_registry_nav
+ insert_after_sub_nav_item(
+ _('Package Registry'),
+ within: _('Packages & Registries'),
+ new_sub_nav_item_name: _('Infrastructure Registry')
+ )
+ end
end
diff --git a/spec/support/matchers/exceed_query_limit.rb b/spec/support/matchers/exceed_query_limit.rb
index 7a66eff3a41..b48c7f905b2 100644
--- a/spec/support/matchers/exceed_query_limit.rb
+++ b/spec/support/matchers/exceed_query_limit.rb
@@ -20,6 +20,11 @@ module ExceedQueryLimitHelpers
self
end
+ def for_model(model)
+ table = model.table_name if model < ActiveRecord::Base
+ for_query(/(FROM|UPDATE|INSERT INTO|DELETE FROM)\s+"#{table}"/)
+ end
+
def show_common_queries
@show_common_queries = true
self
diff --git a/spec/support/shared_examples/features/sidebar_shared_examples.rb b/spec/support/shared_examples/features/sidebar_shared_examples.rb
new file mode 100644
index 00000000000..558536a80c6
--- /dev/null
+++ b/spec/support/shared_examples/features/sidebar_shared_examples.rb
@@ -0,0 +1,165 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issue boards sidebar' do
+ include MobileHelpers
+
+ before do
+ first_card.click
+ end
+
+ it 'shows sidebar when clicking issue' do
+ expect(page).to have_selector('.issue-boards-sidebar')
+ end
+
+ it 'closes sidebar when clicking issue' do
+ expect(page).to have_selector('.issue-boards-sidebar')
+
+ first_card.click
+
+ expect(page).not_to have_selector('.issue-boards-sidebar')
+ end
+
+ it 'shows issue details when sidebar is open', :aggregate_failures do
+ page.within('.issue-boards-sidebar') do
+ expect(page).to have_content(issue.title)
+ expect(page).to have_content(issue.to_reference)
+ end
+ end
+
+ context 'when clicking close button' do
+ before do
+ find("[data-testid='sidebar-drawer'] .gl-drawer-close-button").click
+ end
+
+ it 'unhighlights the active issue card' do
+ expect(first_card[:class]).not_to include('is-active')
+ expect(first_card[:class]).not_to include('multi-select')
+ end
+
+ it 'closes sidebar when clicking close button' do
+ expect(page).not_to have_selector('.issue-boards-sidebar')
+ end
+ end
+
+ context 'in notifications subscription' do
+ it 'displays notifications toggle', :aggregate_failures do
+ page.within('[data-testid="sidebar-notifications"]') do
+ expect(page).to have_selector('[data-testid="notification-subscribe-toggle"]')
+ expect(page).to have_content('Notifications')
+ expect(page).not_to have_content('Notifications have been disabled by the project or group owner')
+ end
+ end
+
+ it 'shows toggle as on then as off as user toggles to subscribe and unsubscribe', :aggregate_failures do
+ toggle = find('[data-testid="notification-subscribe-toggle"]')
+
+ toggle.click
+
+ expect(toggle).to have_css("button.is-checked")
+
+ toggle.click
+
+ expect(toggle).not_to have_css("button.is-checked")
+ end
+
+ context 'when notifications have been disabled' do
+ before do
+ project.update_attribute(:emails_disabled, true)
+
+ refresh_and_click_first_card
+ end
+
+ it 'displays a message that notifications have been disabled' do
+ page.within('[data-testid="sidebar-notifications"]') do
+ expect(page).not_to have_selector('[data-testid="notification-subscribe-toggle"]')
+ expect(page).to have_content('Notifications have been disabled by the project or group owner')
+ end
+ end
+ end
+ end
+
+ context 'in time tracking' do
+ it 'displays time tracking feature with default message' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Time tracking')
+ expect(page).to have_content('No estimate or time spent')
+ end
+ end
+
+ context 'when only spent time is recorded' do
+ before do
+ issue.timelogs.create!(time_spent: 3600, user: user)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the total time spent only' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent: 1h')
+ expect(page).not_to have_content('Estimated')
+ end
+ end
+ end
+
+ context 'when only estimated time is recorded' do
+ before do
+ issue.update!(time_estimate: 3600)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the estimated time only', :aggregate_failures do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Estimated: 1h')
+ expect(page).not_to have_content('Spent')
+ end
+ end
+ end
+
+ context 'when estimated and spent times are available' do
+ before do
+ issue.timelogs.create!(time_spent: 1800, user: user)
+ issue.update!(time_estimate: 3600)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows time tracking progress bar' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_selector('[data-testid="timeTrackingComparisonPane"]')
+ end
+ end
+
+ it 'shows both estimated and spent time text', :aggregate_failures do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent 30m')
+ expect(page).to have_content('Est 1h')
+ end
+ end
+ end
+
+ context 'when limitedToHours instance option is turned on' do
+ before do
+ # 3600+3600*24 = 1d 1h or 25h
+ issue.timelogs.create!(time_spent: 3600 + 3600 * 24, user: user)
+ stub_application_setting(time_tracking_limit_to_hours: true)
+
+ refresh_and_click_first_card
+ end
+
+ it 'shows the total time spent only' do
+ page.within('[data-testid="time-tracker"]') do
+ expect(page).to have_content('Spent: 25h')
+ end
+ end
+ end
+ end
+
+ def refresh_and_click_first_card
+ page.refresh
+
+ wait_for_requests
+
+ first_card.click
+ end
+end
diff --git a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
index 6d8d9ba0754..67d87fe3c2f 100644
--- a/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
+++ b/spec/support_specs/matchers/exceed_query_limit_helpers_spec.rb
@@ -225,6 +225,16 @@ RSpec.describe ExceedQueryLimitHelpers do
expect(test_matcher.actual_count).to eq(2)
end
+ it 'can filter specific models' do
+ test_matcher = TestMatcher.new.for_model(TestQueries)
+ test_matcher.verify_count do
+ TestQueries.first
+ TestQueries.connection.execute('select 1')
+ end
+
+ expect(test_matcher.actual_count).to eq(1)
+ end
+
it 'can ignore specific queries' do
test_matcher = TestMatcher.new.ignoring(/foobar/)
test_matcher.verify_count do