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-02-16 15:08:03 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-16 15:08:03 +0300
commit12166c0faf75479889bc0ac432b85b9dae91552b (patch)
treefc5a3140e12c815beb6c34d44e2ad423a4f302ad /spec
parentb1a0a71628cb4531f3b9a2999f5aa4d22f6ac5fb (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/projects/raw_controller_spec.rb15
-rw-r--r--spec/controllers/projects/repositories_controller_spec.rb39
-rw-r--r--spec/db/development/create_base_work_item_types_spec.rb2
-rw-r--r--spec/db/production/create_base_work_item_types_spec.rb2
-rw-r--r--spec/factories/work_items/widget_definitions.rb11
-rw-r--r--spec/features/calendar_spec.rb6
-rw-r--r--spec/features/unsubscribe_links_spec.rb2
-rw-r--r--spec/features/users/user_browses_projects_on_user_page_spec.rb2
-rw-r--r--spec/frontend/environments/deploy_board_component_spec.js4
-rw-r--r--spec/frontend/environments/folder/environments_folder_view_spec.js45
-rw-r--r--spec/frontend/environments/mixins/environments_pagination_api_mixin_spec.js69
-rw-r--r--spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb15
-rw-r--r--spec/graphql/resolvers/users/participants_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/work_items_resolver_spec.rb4
-rw-r--r--spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb2
-rw-r--r--spec/models/integrations/microsoft_teams_spec.rb2
-rw-r--r--spec/models/work_items/type_spec.rb51
-rw-r--r--spec/models/work_items/widget_definition_spec.rb92
-rw-r--r--spec/policies/issue_policy_spec.rb16
-rw-r--r--spec/policies/note_policy_spec.rb4
-rw-r--r--spec/requests/api/discussions_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb35
-rw-r--r--spec/requests/api/graphql/mutations/notes/create/note_spec.rb4
-rw-r--r--spec/requests/api/graphql/mutations/notes/destroy_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/notes/update/note_spec.rb3
-rw-r--r--spec/requests/api/graphql/mutations/work_items/update_spec.rb9
-rw-r--r--spec/requests/api/graphql/notes/note_spec.rb3
-rw-r--r--spec/requests/api/graphql/notes/synthetic_note_resolver_spec.rb3
-rw-r--r--spec/requests/api/notes_spec.rb3
-rw-r--r--spec/services/concerns/rate_limited_service_spec.rb4
-rw-r--r--spec/services/issuable/discussions_list_service_spec.rb3
-rw-r--r--spec/services/issues/create_service_spec.rb46
-rw-r--r--spec/services/work_items/create_service_spec.rb6
-rw-r--r--spec/support/db_cleaner.rb2
-rw-r--r--spec/support/shared_examples/models/chat_integration_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/work_item_base_types_importer.rb60
-rw-r--r--spec/workers/pipeline_schedule_worker_spec.rb16
-rw-r--r--spec/workers/run_pipeline_schedule_worker_spec.rb40
38 files changed, 333 insertions, 299 deletions
diff --git a/spec/controllers/projects/raw_controller_spec.rb b/spec/controllers/projects/raw_controller_spec.rb
index a21727e5691..40252cf65cd 100644
--- a/spec/controllers/projects/raw_controller_spec.rb
+++ b/spec/controllers/projects/raw_controller_spec.rb
@@ -295,21 +295,6 @@ RSpec.describe Projects::RawController, feature_category: :source_code_managemen
expect(response).to have_gitlab_http_status(:not_modified)
end
end
-
- context 'when improve_blobs_cache_headers disabled' do
- before do
- stub_feature_flags(improve_blobs_cache_headers: false)
- end
-
- it 'uses weak etags with a restricted set of headers' do
- sign_in create(:user)
- request_file
-
- expect(response.headers['ETag']).to eq("W/\"bdd5aa537c1e1f6d1b66de4bac8a6132\"")
- expect(response.cache_control[:no_store]).to be_nil
- expect(response.header['Cache-Control']).to eq('max-age=60, public')
- end
- end
end
end
end
diff --git a/spec/controllers/projects/repositories_controller_spec.rb b/spec/controllers/projects/repositories_controller_spec.rb
index bc2a3abc2d6..8186176a46b 100644
--- a/spec/controllers/projects/repositories_controller_spec.rb
+++ b/spec/controllers/projects/repositories_controller_spec.rb
@@ -174,45 +174,6 @@ RSpec.describe Projects::RepositoriesController, feature_category: :source_code_
end
end
- context 'when improve_blobs_cache_headers is disabled' do
- before do
- stub_feature_flags(improve_blobs_cache_headers: false)
- end
-
- context 'when project is public' do
- let(:project) { create(:project, :repository, :public) }
-
- it 'sets appropriate caching headers' do
- get_archive
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.header['ETag']).to be_present
- expect(response.header['Cache-Control']).to eq('max-age=60, public')
- end
-
- context 'and repo is private' do
- let(:project) { create(:project, :repository, :public, :repository_private) }
-
- it 'sets appropriate caching headers' do
- get_archive
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.header['ETag']).to be_present
- expect(response.header['Cache-Control']).to eq('max-age=60, private')
- end
- end
- end
-
- context 'when ref is a commit SHA' do
- it 'max-age is set to 3600 in Cache-Control header' do
- get_archive('ddd0f15ae83993f5cb66a927a28673882e99100b')
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.header['Cache-Control']).to eq('max-age=3600, private')
- end
- end
- end
-
context 'when If-None-Modified header is set' do
it 'returns a 304 status' do
# Get the archive cached first
diff --git a/spec/db/development/create_base_work_item_types_spec.rb b/spec/db/development/create_base_work_item_types_spec.rb
index 914b84d8668..7652ccdc487 100644
--- a/spec/db/development/create_base_work_item_types_spec.rb
+++ b/spec/db/development/create_base_work_item_types_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Create base work item types in development' do
+RSpec.describe 'Create base work item types in development', feature_category: :team_planning do
subject { load Rails.root.join('db', 'fixtures', 'development', '001_create_base_work_item_types.rb') }
it_behaves_like 'work item base types importer'
diff --git a/spec/db/production/create_base_work_item_types_spec.rb b/spec/db/production/create_base_work_item_types_spec.rb
index 81d80104bb4..f6c3b0f6395 100644
--- a/spec/db/production/create_base_work_item_types_spec.rb
+++ b/spec/db/production/create_base_work_item_types_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Create base work item types in production' do
+RSpec.describe 'Create base work item types in production', feature_category: :team_planning do
subject { load Rails.root.join('db', 'fixtures', 'production', '003_create_base_work_item_types.rb') }
it_behaves_like 'work item base types importer'
diff --git a/spec/factories/work_items/widget_definitions.rb b/spec/factories/work_items/widget_definitions.rb
new file mode 100644
index 00000000000..bbd7c1e7432
--- /dev/null
+++ b/spec/factories/work_items/widget_definitions.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+FactoryBot.define do
+ factory :widget_definition, class: 'WorkItems::WidgetDefinition' do
+ work_item_type
+ namespace
+
+ name { 'Description' }
+ widget_type { 'description' }
+ end
+end
diff --git a/spec/features/calendar_spec.rb b/spec/features/calendar_spec.rb
index b09e1f16b7b..b2a29c88b68 100644
--- a/spec/features/calendar_spec.rb
+++ b/spec/features/calendar_spec.rb
@@ -146,9 +146,9 @@ RSpec.describe 'Contributions Calendar', :js, feature_category: :user_profile do
describe '1 issue and 1 work item creation calendar activity' do
before do
- Issues::CreateService.new(project: contributed_project, current_user: user, params: issue_params, spam_params: nil).execute
+ Issues::CreateService.new(container: contributed_project, current_user: user, params: issue_params, spam_params: nil).execute
WorkItems::CreateService.new(
- project: contributed_project,
+ container: contributed_project,
current_user: user,
params: { title: 'new task' },
spam_params: nil
@@ -190,7 +190,7 @@ RSpec.describe 'Contributions Calendar', :js, feature_category: :user_profile do
push_code_contribution
travel_to(Date.yesterday) do
- Issues::CreateService.new(project: contributed_project, current_user: user, params: issue_params, spam_params: nil).execute
+ Issues::CreateService.new(container: contributed_project, current_user: user, params: issue_params, spam_params: nil).execute
end
end
include_context 'visit user page'
diff --git a/spec/features/unsubscribe_links_spec.rb b/spec/features/unsubscribe_links_spec.rb
index bcab35335cb..23fa6261bd5 100644
--- a/spec/features/unsubscribe_links_spec.rb
+++ b/spec/features/unsubscribe_links_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'Unsubscribe links', :sidekiq_inline, feature_category: :not_owne
let_it_be(:recipient) { create(:user) }
let(:params) { { title: 'A bug!', description: 'Fix it!', assignee_ids: [recipient.id] } }
- let(:issue) { Issues::CreateService.new(project: project, current_user: author, params: params, spam_params: nil).execute[:issue] }
+ let(:issue) { Issues::CreateService.new(container: project, current_user: author, params: params, spam_params: nil).execute[:issue] }
let(:mail) { ActionMailer::Base.deliveries.last }
let(:body) { Capybara::Node::Simple.new(mail.default_part_body.to_s) }
diff --git a/spec/features/users/user_browses_projects_on_user_page_spec.rb b/spec/features/users/user_browses_projects_on_user_page_spec.rb
index b31e2a054fe..52ca2397582 100644
--- a/spec/features/users/user_browses_projects_on_user_page_spec.rb
+++ b/spec/features/users/user_browses_projects_on_user_page_spec.rb
@@ -129,7 +129,7 @@ RSpec.describe 'Users > User browses projects on user page', :js, feature_catego
end
before do
- Issues::CreateService.new(project: contributed_project, current_user: user, params: { title: 'Bug in old browser' }, spam_params: nil).execute
+ Issues::CreateService.new(container: contributed_project, current_user: user, params: { title: 'Bug in old browser' }, spam_params: nil).execute
event = create(:push_event, project: contributed_project, author: user)
create(:push_event_payload, event: event, commit_count: 3)
end
diff --git a/spec/frontend/environments/deploy_board_component_spec.js b/spec/frontend/environments/deploy_board_component_spec.js
index c005ca22070..73a366457fb 100644
--- a/spec/frontend/environments/deploy_board_component_spec.js
+++ b/spec/frontend/environments/deploy_board_component_spec.js
@@ -1,6 +1,6 @@
import { GlTooltip, GlIcon, GlLoadingIcon } from '@gitlab/ui';
import { mount } from '@vue/test-utils';
-import Vue, { nextTick } from 'vue';
+import { nextTick } from 'vue';
import CanaryIngress from '~/environments/components/canary_ingress.vue';
import DeployBoard from '~/environments/components/deploy_board.vue';
import { deployBoardMockData } from './mock_data';
@@ -10,7 +10,7 @@ describe('Deploy Board', () => {
let wrapper;
const createComponent = (props = {}) =>
- mount(Vue.extend(DeployBoard), {
+ mount(DeployBoard, {
propsData: {
deployBoardData: deployBoardMockData,
isLoading: false,
diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js
index ac9d857e6bd..23506eb018d 100644
--- a/spec/frontend/environments/folder/environments_folder_view_spec.js
+++ b/spec/frontend/environments/folder/environments_folder_view_spec.js
@@ -55,7 +55,6 @@ describe('Environments Folder View', () => {
afterEach(() => {
mock.restore();
- wrapper.destroy();
});
describe('successful request', () => {
@@ -96,26 +95,6 @@ describe('Environments Folder View', () => {
it('should render pagination', () => {
expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
});
-
- it('should make an API request when changing page', () => {
- jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
- wrapper.find('.gl-pagination .page-item:nth-last-of-type(2) .page-link').trigger('click');
- expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
- scope: wrapper.vm.scope,
- page: '10',
- nested: true,
- });
- });
-
- it('should make an API request when using tabs', () => {
- jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
- findEnvironmentsTabStopped().trigger('click');
- expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
- scope: 'stopped',
- page: '1',
- nested: true,
- });
- });
});
});
@@ -161,29 +140,5 @@ describe('Environments Folder View', () => {
expect(wrapper.vm.requestData.page).toEqual('4');
}));
});
-
- describe('onChangeTab', () => {
- it('should set page to 1', () => {
- jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
- wrapper.vm.onChangeTab('stopped');
- expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
- scope: 'stopped',
- page: '1',
- nested: true,
- });
- });
- });
-
- describe('onChangePage', () => {
- it('should update page and keep scope', () => {
- jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
- wrapper.vm.onChangePage(4);
- expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
- scope: wrapper.vm.scope,
- page: '4',
- nested: true,
- });
- });
- });
});
});
diff --git a/spec/frontend/environments/mixins/environments_pagination_api_mixin_spec.js b/spec/frontend/environments/mixins/environments_pagination_api_mixin_spec.js
new file mode 100644
index 00000000000..b624178e3db
--- /dev/null
+++ b/spec/frontend/environments/mixins/environments_pagination_api_mixin_spec.js
@@ -0,0 +1,69 @@
+import { shallowMount } from '@vue/test-utils';
+import environmentsPaginationApiMixin from '~/environments/mixins/environments_pagination_api_mixin';
+
+describe('environments_pagination_api_mixin', () => {
+ const updateContentMock = jest.fn();
+ const mockComponent = {
+ template: `
+ <div>
+ <button id='change-page' @click="changePageClick" />
+ <button id='change-tab' @click="changeTabClick" />
+ </div>
+ `,
+ methods: {
+ updateContent: updateContentMock,
+ changePageClick() {
+ this.onChangePage(this.nextPage);
+ },
+ changeTabClick() {
+ this.onChangeTab(this.nextScope);
+ },
+ },
+ data() {
+ return {
+ scope: 'test',
+ };
+ },
+ };
+
+ let wrapper;
+
+ const createWrapper = ({ scope, nextPage, nextScope }) =>
+ shallowMount(mockComponent, {
+ mixins: [environmentsPaginationApiMixin],
+ data() {
+ return {
+ nextPage,
+ nextScope,
+ scope,
+ };
+ },
+ });
+
+ it.each([
+ ['test-scope', 2],
+ ['test-scope', 10],
+ ['test-scope-2', 3],
+ ])('should call updateContent when calling onChangePage', async (scopeName, pageNumber) => {
+ wrapper = createWrapper({ scope: scopeName, nextPage: pageNumber });
+
+ await wrapper.find('#change-page').trigger('click');
+
+ expect(updateContentMock).toHaveBeenCalledWith({
+ scope: scopeName,
+ page: pageNumber.toString(),
+ nested: true,
+ });
+ });
+
+ it('should call updateContent when calling onChageTab', async () => {
+ wrapper = createWrapper({ nextScope: 'stopped' });
+ await wrapper.find('#change-tab').trigger('click');
+
+ expect(updateContentMock).toHaveBeenCalledWith({
+ scope: 'stopped',
+ page: '1',
+ nested: true,
+ });
+ });
+});
diff --git a/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb b/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
index a5294e96d71..5385b6ca1cf 100644
--- a/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
+++ b/spec/graphql/mutations/ci/job_token_scope/remove_project_spec.rb
@@ -46,19 +46,20 @@ RSpec.describe Mutations::Ci::JobTokenScope::RemoveProject, feature_category: :c
target_project.add_guest(current_user)
end
+ let(:service) { instance_double('Ci::JobTokenScope::RemoveProjectService') }
+
context 'with no direction specified' do
- it 'defaults to removing an outbound link to the target project' do
- expect do
- expect(subject).to include(ci_job_token_scope: be_present, errors: be_empty)
- end.to change { Ci::JobToken::ProjectScopeLink.count }.by(-1)
+ it 'defaults to asking the RemoveProjectService to remove the outbound link' do
+ expect(::Ci::JobTokenScope::RemoveProjectService)
+ .to receive(:new).with(project, current_user).and_return(service)
+ expect(service).to receive(:execute).with(target_project, :outbound)
+ .and_return(instance_double('ServiceResponse', "success?": true))
- expect(links_relation.outbound.reload).to be_empty
+ subject
end
end
context 'with direction specified' do
- let(:service) { instance_double('Ci::JobTokenScope::RemoveProjectService') }
-
subject do
mutation.resolve(project_path: project.full_path, target_project_path: target_project_path, direction: 'inbound')
end
diff --git a/spec/graphql/resolvers/users/participants_resolver_spec.rb b/spec/graphql/resolvers/users/participants_resolver_spec.rb
index 27c3b9643ce..224213d1521 100644
--- a/spec/graphql/resolvers/users/participants_resolver_spec.rb
+++ b/spec/graphql/resolvers/users/participants_resolver_spec.rb
@@ -115,8 +115,8 @@ RSpec.describe Resolvers::Users::ParticipantsResolver do
create(:award_emoji, name: 'thumbsup', awardable: public_note)
# 1 extra query per source (3 emojis + 2 notes) to fetch participables collection
- # 1 extra query to load work item widgets collection
- expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(6)
+ # 2 extra queries to load work item widgets collection
+ expect { query.call }.not_to exceed_query_limit(control_count).with_threshold(7)
end
it 'does not execute N+1 for system note metadata relation' do
diff --git a/spec/graphql/resolvers/work_items_resolver_spec.rb b/spec/graphql/resolvers/work_items_resolver_spec.rb
index d89ccc7f806..6da62e3adb7 100644
--- a/spec/graphql/resolvers/work_items_resolver_spec.rb
+++ b/spec/graphql/resolvers/work_items_resolver_spec.rb
@@ -101,7 +101,7 @@ RSpec.describe Resolvers::WorkItemsResolver do
end
it 'batches queries that only include IIDs', :request_store do
- result = batch_sync(max_queries: 7) do
+ result = batch_sync(max_queries: 8) do
[item1, item2]
.map { |item| resolve_items(iid: item.iid.to_s) }
.flat_map(&:to_a)
@@ -111,7 +111,7 @@ RSpec.describe Resolvers::WorkItemsResolver do
end
it 'finds a specific item with iids', :request_store do
- result = batch_sync(max_queries: 7) do
+ result = batch_sync(max_queries: 8) do
resolve_items(iids: [item1.iid]).to_a
end
diff --git a/spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb b/spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb
index d044170dc75..3b6d10f4a7e 100644
--- a/spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb
+++ b/spec/lib/gitlab/database_importers/work_items/base_type_importer_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter do
+RSpec.describe Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter, feature_category: :team_planning do
subject { described_class.upsert_types }
it_behaves_like 'work item base types importer'
diff --git a/spec/models/integrations/microsoft_teams_spec.rb b/spec/models/integrations/microsoft_teams_spec.rb
index fa8900497d7..4d5f4065420 100644
--- a/spec/models/integrations/microsoft_teams_spec.rb
+++ b/spec/models/integrations/microsoft_teams_spec.rb
@@ -53,7 +53,7 @@ RSpec.describe Integrations::MicrosoftTeams do
context 'with issue events' do
let(:opts) { { title: 'Awesome issue', description: 'please fix' } }
let(:issues_sample_data) do
- service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil)
+ service = Issues::CreateService.new(container: project, current_user: user, params: opts, spam_params: nil)
issue = service.execute[:issue]
service.hook_data(issue, 'open')
end
diff --git a/spec/models/work_items/type_spec.rb b/spec/models/work_items/type_spec.rb
index 65c6b22f5c2..e5c88634b26 100644
--- a/spec/models/work_items/type_spec.rb
+++ b/spec/models/work_items/type_spec.rb
@@ -10,6 +10,20 @@ RSpec.describe WorkItems::Type do
describe 'associations' do
it { is_expected.to have_many(:work_items).with_foreign_key('work_item_type_id') }
it { is_expected.to belong_to(:namespace) }
+
+ it 'has many `widget_definitions`' do
+ is_expected.to have_many(:widget_definitions)
+ .class_name('::WorkItems::WidgetDefinition')
+ .with_foreign_key('work_item_type_id')
+ end
+
+ it 'has many `enabled_widget_definitions`' do
+ type = create(:work_item_type)
+ widget1 = create(:widget_definition, work_item_type: type)
+ create(:widget_definition, work_item_type: type, disabled: true)
+
+ expect(type.enabled_widget_definitions).to match_array([widget1])
+ end
end
describe 'scopes' do
@@ -60,29 +74,14 @@ RSpec.describe WorkItems::Type do
it { is_expected.not_to allow_value('s' * 256).for(:icon_name) }
end
- describe '.available_widgets' do
- subject { described_class.available_widgets }
-
- it 'returns list of all possible widgets' do
- is_expected.to include(
- ::WorkItems::Widgets::Description,
- ::WorkItems::Widgets::Hierarchy,
- ::WorkItems::Widgets::Labels,
- ::WorkItems::Widgets::Assignees,
- ::WorkItems::Widgets::StartAndDueDate,
- ::WorkItems::Widgets::Milestone,
- ::WorkItems::Widgets::Notes
- )
- end
- end
-
describe '.default_by_type' do
let(:default_issue_type) { described_class.find_by(namespace_id: nil, base_type: :issue) }
subject { described_class.default_by_type(:issue) }
it 'returns default work item type by base type without calling importer' do
- expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).not_to receive(:upsert_types)
+ expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).not_to receive(:upsert_types).and_call_original
+ expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).not_to receive(:upsert_widgets)
expect(Gitlab::DatabaseImporters::WorkItems::HierarchyRestrictionsImporter).not_to receive(:upsert_restrictions)
expect(subject).to eq(default_issue_type)
@@ -94,7 +93,8 @@ RSpec.describe WorkItems::Type do
end
it 'creates types and restrictions and returns default work item type by base type' do
- expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).to receive(:upsert_types)
+ expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).to receive(:upsert_types).and_call_original
+ expect(Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter).to receive(:upsert_widgets)
expect(Gitlab::DatabaseImporters::WorkItems::HierarchyRestrictionsImporter).to receive(:upsert_restrictions)
expect(subject).to eq(default_issue_type)
@@ -128,19 +128,18 @@ RSpec.describe WorkItems::Type do
end
describe '#supports_assignee?' do
- subject(:supports_assignee) { build(:work_item_type, :task).supports_assignee? }
+ let_it_be_with_reload(:work_item_type) { create(:work_item_type) }
+ let_it_be_with_reload(:widget_definition) do
+ create(:widget_definition, work_item_type: work_item_type, widget_type: :assignees)
+ end
- context 'when the assignees widget is supported' do
- before do
- stub_const('::WorkItems::Type::WIDGETS_FOR_TYPE', { task: [::WorkItems::Widgets::Assignees] })
- end
+ subject(:supports_assignee) { work_item_type.supports_assignee? }
- it { is_expected.to be_truthy }
- end
+ it { is_expected.to be_truthy }
context 'when the assignees widget is not supported' do
before do
- stub_const('::WorkItems::Type::WIDGETS_FOR_TYPE', { task: [] })
+ widget_definition.update!(disabled: true)
end
it { is_expected.to be_falsey }
diff --git a/spec/models/work_items/widget_definition_spec.rb b/spec/models/work_items/widget_definition_spec.rb
new file mode 100644
index 00000000000..08f8f4d9663
--- /dev/null
+++ b/spec/models/work_items/widget_definition_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe WorkItems::WidgetDefinition, feature_category: :team_planning do
+ let(:all_widget_classes) do
+ list = [
+ ::WorkItems::Widgets::Description,
+ ::WorkItems::Widgets::Hierarchy,
+ ::WorkItems::Widgets::Labels,
+ ::WorkItems::Widgets::Assignees,
+ ::WorkItems::Widgets::StartAndDueDate,
+ ::WorkItems::Widgets::Milestone,
+ ::WorkItems::Widgets::Notes
+ ]
+
+ if Gitlab.ee?
+ list += [
+ ::WorkItems::Widgets::Iteration,
+ ::WorkItems::Widgets::Weight,
+ ::WorkItems::Widgets::Status,
+ ::WorkItems::Widgets::HealthStatus,
+ ::WorkItems::Widgets::Progress,
+ ::WorkItems::Widgets::RequirementLegacy,
+ ::WorkItems::Widgets::TestReports
+ ]
+ end
+
+ list
+ end
+
+ describe 'associations' do
+ it { is_expected.to belong_to(:namespace) }
+ it { is_expected.to belong_to(:work_item_type) }
+ end
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:name) }
+ it { is_expected.to validate_uniqueness_of(:name).case_insensitive.scoped_to([:namespace_id, :work_item_type_id]) }
+ it { is_expected.to validate_length_of(:name).is_at_most(255) }
+ end
+
+ context 'with some widgets disabled' do
+ before do
+ described_class.global.where(widget_type: :notes).update_all(disabled: true)
+ end
+
+ describe '.available_widgets' do
+ subject { described_class.available_widgets }
+
+ it 'returns all global widgets excluding the disabled ones' do
+ # WorkItems::Widgets::Notes is excluded from widget class because:
+ # * although widget_definition below is enabled and uses notes widget, it's namespaced (has namespace != nil)
+ # * available_widgets takes into account only global definitions (which have namespace=nil)
+ namespace = create(:namespace)
+ create(:widget_definition, namespace: namespace, widget_type: :notes)
+
+ is_expected.to match_array(all_widget_classes - [::WorkItems::Widgets::Notes])
+ end
+
+ it 'returns all global widgets if there is at least one global widget definition which is enabled' do
+ create(:widget_definition, namespace: nil, widget_type: :notes)
+
+ is_expected.to match_array(all_widget_classes)
+ end
+ end
+
+ describe '.widget_classes' do
+ subject { described_class.widget_classes }
+
+ it 'returns all widget classes no matter if disabled or not' do
+ is_expected.to match_array(all_widget_classes)
+ end
+ end
+ end
+
+ describe '#widget_class' do
+ it 'returns widget class based on widget_type' do
+ expect(build(:widget_definition, widget_type: :description).widget_class).to eq(::WorkItems::Widgets::Description)
+ end
+
+ it 'returns nil if there is no class for the widget_type' do
+ described_class.first.update_column(:widget_type, -1)
+
+ expect(described_class.first.widget_class).to be_nil
+ end
+
+ it 'returns nil if there is no class for the widget_type' do
+ expect(build(:widget_definition, widget_type: nil).widget_class).to be_nil
+ end
+ end
+end
diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb
index 0040d9dff7e..17558787966 100644
--- a/spec/policies/issue_policy_spec.rb
+++ b/spec/policies/issue_policy_spec.rb
@@ -425,19 +425,15 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do
context 'when accounting for notes widget' do
let(:policy) { described_class.new(reporter, note) }
- before do
- widgets_per_type = WorkItems::Type::WIDGETS_FOR_TYPE.dup
- widgets_per_type[:task] = [::WorkItems::Widgets::Description]
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', widgets_per_type)
- end
-
- context 'and notes widget is disabled for task' do
- let(:task) { create(:work_item, :task, project: project) }
+ context 'and notes widget is disabled for issue' do
+ before do
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
+ end
it 'does not allow accessing notes' do
# if notes widget is disabled not even maintainer can access notes
- expect(permissions(maintainer, task)).to be_disallowed(:create_note, :read_note, :mark_note_as_internal, :read_internal_note)
- expect(permissions(admin, task)).to be_disallowed(:create_note, :read_note, :read_internal_note, :mark_note_as_internal, :set_note_created_at)
+ expect(permissions(maintainer, issue)).to be_disallowed(:create_note, :read_note, :mark_note_as_internal, :read_internal_note)
+ expect(permissions(admin, issue)).to be_disallowed(:create_note, :read_note, :read_internal_note, :mark_note_as_internal, :set_note_created_at)
end
end
diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb
index f4abe3a223c..b2191e6925d 100644
--- a/spec/policies/note_policy_spec.rb
+++ b/spec/policies/note_policy_spec.rb
@@ -260,9 +260,7 @@ RSpec.describe NotePolicy, feature_category: :team_planning do
let(:policy) { described_class.new(developer, note) }
before do
- widgets_per_type = WorkItems::Type::WIDGETS_FOR_TYPE.dup
- widgets_per_type[:task] = [::WorkItems::Widgets::Description]
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', widgets_per_type)
+ WorkItems::Type.default_by_type(:task).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
context 'when noteable is task' do
diff --git a/spec/requests/api/discussions_spec.rb b/spec/requests/api/discussions_spec.rb
index 38016375b8f..c5126dbd1c2 100644
--- a/spec/requests/api/discussions_spec.rb
+++ b/spec/requests/api/discussions_spec.rb
@@ -42,8 +42,7 @@ RSpec.describe API::Discussions, feature_category: :team_planning do
context 'with work item without notes widget' do
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
context 'when fetching discussions' do
diff --git a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb
index 9161304cfc3..492c6946c99 100644
--- a/spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb
+++ b/spec/requests/api/graphql/mutations/ci/pipeline_schedule_play_spec.rb
@@ -76,40 +76,5 @@ RSpec.describe 'PipelineSchedulePlay', feature_category: :continuous_integration
expect(mutation_response['errors']).to match_array(['Unable to schedule a pipeline to run immediately.'])
end
end
-
- context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do
- before do
- stub_feature_flags(ci_use_run_pipeline_schedule_worker: false)
- end
-
- context 'when mutation succeeds' do
- let(:service_response) { instance_double('ServiceResponse', payload: new_pipeline) }
- let(:new_pipeline) { instance_double('Ci::Pipeline', persisted?: true) }
-
- it do
- expect(Ci::CreatePipelineService).to receive_message_chain(:new, :execute).and_return(service_response)
- post_graphql_mutation(mutation, current_user: user)
-
- expect(mutation_response['pipelineSchedule']['id']).to include(pipeline_schedule.id.to_s)
- new_next_run_at = DateTime.parse(mutation_response['pipelineSchedule']['nextRunAt'])
- expect(new_next_run_at).not_to eq(pipeline_schedule.next_run_at)
- expect(new_next_run_at).to eq(pipeline_schedule.reset.next_run_at)
- expect(mutation_response['errors']).to eq([])
- end
- end
-
- context 'when mutation fails' do
- it do
- expect(RunPipelineScheduleWorker)
- .to receive(:perform_async)
- .with(pipeline_schedule.id, user.id).and_return(nil)
-
- post_graphql_mutation(mutation, current_user: user)
-
- expect(mutation_response['pipelineSchedule']).to be_nil
- expect(mutation_response['errors']).to match_array(['Unable to schedule a pipeline to run immediately.'])
- end
- end
- end
end
end
diff --git a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
index 00e25909746..a6253ba424b 100644
--- a/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/create/note_spec.rb
@@ -122,8 +122,8 @@ RSpec.describe 'Adding a Note', feature_category: :team_planning do
let(:variables_extra) { {} }
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes)
+ .update!(disabled: true)
end
it_behaves_like 'a Note mutation that does not create a Note'
diff --git a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
index eb45e2aa033..f40518a574b 100644
--- a/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/destroy_spec.rb
@@ -57,8 +57,7 @@ RSpec.describe 'Destroying a Note', feature_category: :team_planning do
context 'without notes widget' do
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
it 'does not update the Note' do
diff --git a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
index dff8a87314b..7918bc860fe 100644
--- a/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
+++ b/spec/requests/api/graphql/mutations/notes/update/note_spec.rb
@@ -50,8 +50,7 @@ RSpec.describe 'Updating a Note', feature_category: :team_planning do
context 'without notes widget' do
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
it 'does not update the Note' do
diff --git a/spec/requests/api/graphql/mutations/work_items/update_spec.rb b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
index 271c2b917ad..ddd294e8f82 100644
--- a/spec/requests/api/graphql/mutations/work_items/update_spec.rb
+++ b/spec/requests/api/graphql/mutations/work_items/update_spec.rb
@@ -252,7 +252,8 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do
let(:input) { { 'descriptionWidget' => { 'description' => "Updating labels.\n/labels ~\"#{label1.name}\"" } } }
before do
- stub_const('::WorkItems::Type::WIDGETS_FOR_TYPE', { task: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:task).widget_definitions
+ .find_by_widget_type(:labels).update!(disabled: true)
end
it 'ignores the quick action' do
@@ -370,7 +371,8 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do
let(:input) { { 'descriptionWidget' => { 'description' => "Updating due date.\n/due today" } } }
before do
- stub_const('::WorkItems::Type::WIDGETS_FOR_TYPE', { task: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:task).widget_definitions
+ .find_by_widget_type(:start_and_due_date).update!(disabled: true)
end
it 'ignores the quick action' do
@@ -736,7 +738,8 @@ RSpec.describe 'Update a work item', feature_category: :team_planning do
end
before do
- stub_const('::WorkItems::Type::WIDGETS_FOR_TYPE', { task: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:task).widget_definitions
+ .find_by_widget_type(:assignees).update!(disabled: true)
end
it 'ignores the quick action' do
diff --git a/spec/requests/api/graphql/notes/note_spec.rb b/spec/requests/api/graphql/notes/note_spec.rb
index 180e54290f8..daceaec0b94 100644
--- a/spec/requests/api/graphql/notes/note_spec.rb
+++ b/spec/requests/api/graphql/notes/note_spec.rb
@@ -66,7 +66,8 @@ RSpec.describe 'Query.note(id)', feature_category: :team_planning do
context 'and notes widget is not available' do
before do
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions
+ .find_by_widget_type(:notes).update!(disabled: true)
end
it 'returns nil' do
diff --git a/spec/requests/api/graphql/notes/synthetic_note_resolver_spec.rb b/spec/requests/api/graphql/notes/synthetic_note_resolver_spec.rb
index 9b11406ae00..1199aeb4c39 100644
--- a/spec/requests/api/graphql/notes/synthetic_note_resolver_spec.rb
+++ b/spec/requests/api/graphql/notes/synthetic_note_resolver_spec.rb
@@ -44,7 +44,8 @@ RSpec.describe 'Query.synthetic_note(noteable_id, sha)', feature_category: :team
context 'and notes widget is not available' do
before do
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions
+ .find_by_widget_type(:notes).update!(disabled: true)
end
it 'returns nil' do
diff --git a/spec/requests/api/notes_spec.rb b/spec/requests/api/notes_spec.rb
index c2d9db1e6fb..c0276e02eb7 100644
--- a/spec/requests/api/notes_spec.rb
+++ b/spec/requests/api/notes_spec.rb
@@ -210,8 +210,7 @@ RSpec.describe API::Notes, feature_category: :team_planning do
let(:request_path) { "/projects/#{ext_proj.id}/issues/#{ext_issue.iid}/notes" }
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
it 'does not fetch notes' do
diff --git a/spec/services/concerns/rate_limited_service_spec.rb b/spec/services/concerns/rate_limited_service_spec.rb
index 04007e8e75a..d913cd17067 100644
--- a/spec/services/concerns/rate_limited_service_spec.rb
+++ b/spec/services/concerns/rate_limited_service_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
RSpec.describe RateLimitedService do
let(:key) { :issues_create }
- let(:scope) { [:project, :current_user] }
+ let(:scope) { [:container, :current_user] }
let(:opts) { { scope: scope, users_allowlist: -> { [User.support_bot.username] } } }
let(:rate_limiter) { ::Gitlab::ApplicationRateLimiter }
@@ -39,7 +39,7 @@ RSpec.describe RateLimitedService do
let_it_be(:project) { create(:project) }
let_it_be(:current_user) { create(:user) }
- let(:service) { instance_double(Issues::CreateService, project: project, current_user: current_user) }
+ let(:service) { instance_double(Issues::CreateService, container: project, current_user: current_user) }
let(:evaluated_scope) { [project, current_user] }
let(:evaluated_opts) { { scope: evaluated_scope, users_allowlist: %w[support-bot] } }
diff --git a/spec/services/issuable/discussions_list_service_spec.rb b/spec/services/issuable/discussions_list_service_spec.rb
index a53bf602d40..a6f57088ad1 100644
--- a/spec/services/issuable/discussions_list_service_spec.rb
+++ b/spec/services/issuable/discussions_list_service_spec.rb
@@ -23,8 +23,7 @@ RSpec.describe Issuable::DiscussionsListService do
let_it_be(:issuable) { create(:work_item, :issue, project: project) }
before do
- stub_const('WorkItems::Type::BASE_TYPES', { issue: { name: 'NoNotesWidget', enum_value: 0 } })
- stub_const('WorkItems::Type::WIDGETS_FOR_TYPE', { issue: [::WorkItems::Widgets::Description] })
+ WorkItems::Type.default_by_type(:issue).widget_definitions.find_by_widget_type(:notes).update!(disabled: true)
end
it "returns no notes" do
diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb
index abb59ad7ebf..ada5b300d7a 100644
--- a/spec/services/issues/create_service_spec.rb
+++ b/spec/services/issues/create_service_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe Issues::CreateService do
let(:opts) { { title: 'title' } }
let(:spam_params) { double }
- let(:service) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params) }
+ let(:service) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params) }
it_behaves_like 'rate limited service' do
let(:key) { :issues_create }
@@ -147,7 +147,7 @@ RSpec.describe Issues::CreateService do
end
context 'when a build_service is provided' do
- let(:result) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute }
+ let(:result) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute }
let(:issue_from_builder) { WorkItem.new(project: project, title: 'Issue from builder') }
let(:build_service) { double(:build_service, execute: issue_from_builder) }
@@ -160,7 +160,7 @@ RSpec.describe Issues::CreateService do
end
context 'when skip_system_notes is true' do
- let(:issue) { described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute(skip_system_notes: true) }
+ let(:issue) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute(skip_system_notes: true) }
it 'does not call Issuable::CommonSystemNotesService' do
expect(Issuable::CommonSystemNotesService).not_to receive(:new)
@@ -256,7 +256,7 @@ RSpec.describe Issues::CreateService do
let_it_be(:non_member) { create(:user) }
it 'filters out params that cannot be set without the :set_issue_metadata permission' do
- result = described_class.new(project: project, current_user: non_member, params: opts, spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: non_member, params: opts, spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -270,7 +270,7 @@ RSpec.describe Issues::CreateService do
end
it 'can create confidential issues' do
- result = described_class.new(project: project, current_user: non_member, params: opts.merge(confidential: true), spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: non_member, params: opts.merge(confidential: true), spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -281,7 +281,7 @@ RSpec.describe Issues::CreateService do
it 'moves the issue to the end, in an asynchronous worker' do
expect(Issues::PlacementWorker).to receive(:perform_async).with(be_nil, Integer)
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
end
context 'when label belongs to project group' do
@@ -368,7 +368,7 @@ RSpec.describe Issues::CreateService do
it 'invalidates open issues counter for assignees when issue is assigned' do
project.add_maintainer(assignee)
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
expect(assignee.assigned_open_issues_count).to eq 1
end
@@ -439,7 +439,7 @@ RSpec.describe Issues::CreateService do
expect(project).to receive(:execute_hooks).with(expected_payload, :issue_hooks)
expect(project).to receive(:execute_integrations).with(expected_payload, :issue_hooks)
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
end
context 'when issue is confidential' do
@@ -462,7 +462,7 @@ RSpec.describe Issues::CreateService do
expect(project).to receive(:execute_hooks).with(expected_payload, :confidential_issue_hooks)
expect(project).to receive(:execute_integrations).with(expected_payload, :confidential_issue_hooks)
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
end
end
end
@@ -508,7 +508,7 @@ RSpec.describe Issues::CreateService do
it 'removes assignee when user id is invalid' do
opts = { title: 'Title', description: 'Description', assignee_ids: [-1] }
- result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -518,7 +518,7 @@ RSpec.describe Issues::CreateService do
it 'removes assignee when user id is 0' do
opts = { title: 'Title', description: 'Description', assignee_ids: [0] }
- result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -529,7 +529,7 @@ RSpec.describe Issues::CreateService do
project.add_maintainer(assignee)
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
- result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -549,7 +549,7 @@ RSpec.describe Issues::CreateService do
project.update!(visibility_level: level)
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
- result = described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
issue = result[:issue]
expect(result).to be_success
@@ -561,7 +561,7 @@ RSpec.describe Issues::CreateService do
end
it_behaves_like 'issuable record that supports quick actions' do
- let(:issuable) { described_class.new(project: project, current_user: user, params: params, spam_params: spam_params).execute[:issue] }
+ let(:issuable) { described_class.new(container: project, current_user: user, params: params, spam_params: spam_params).execute[:issue] }
end
context 'Quick actions' do
@@ -702,14 +702,14 @@ RSpec.describe Issues::CreateService do
let(:opts) { { discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid } }
it 'resolves the discussion' do
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
discussion.first_note.reload
expect(discussion.resolved?).to be(true)
end
it 'added a system note to the discussion' do
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
reloaded_discussion = MergeRequest.find(merge_request.id).discussions.first
@@ -718,7 +718,7 @@ RSpec.describe Issues::CreateService do
it 'sets default title and description values if not provided' do
result = described_class.new(
- project: project, current_user: user,
+ container: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
@@ -732,7 +732,7 @@ RSpec.describe Issues::CreateService do
it 'takes params from the request over the default values' do
result = described_class.new(
- project: project,
+ container: project,
current_user: user,
params: opts.merge(
description: 'Custom issue description',
@@ -753,14 +753,14 @@ RSpec.describe Issues::CreateService do
let(:opts) { { merge_request_to_resolve_discussions_of: merge_request.iid } }
it 'resolves the discussion' do
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
discussion.first_note.reload
expect(discussion.resolved?).to be(true)
end
it 'added a system note to the discussion' do
- described_class.new(project: project, current_user: user, params: opts, spam_params: spam_params).execute
+ described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
reloaded_discussion = MergeRequest.find(merge_request.id).discussions.first
@@ -769,7 +769,7 @@ RSpec.describe Issues::CreateService do
it 'sets default title and description values if not provided' do
result = described_class.new(
- project: project, current_user: user,
+ container: project, current_user: user,
params: opts,
spam_params: spam_params
).execute
@@ -783,7 +783,7 @@ RSpec.describe Issues::CreateService do
it 'takes params from the request over the default values' do
result = described_class.new(
- project: project,
+ container: project,
current_user: user,
params: opts.merge(
description: 'Custom issue description',
@@ -836,7 +836,7 @@ RSpec.describe Issues::CreateService do
end
subject do
- described_class.new(project: project, current_user: user, params: params, spam_params: spam_params)
+ described_class.new(container: project, current_user: user, params: params, spam_params: spam_params)
end
it 'executes SpamActionService' do
diff --git a/spec/services/work_items/create_service_spec.rb b/spec/services/work_items/create_service_spec.rb
index 049c90f20b0..1b134c308f2 100644
--- a/spec/services/work_items/create_service_spec.rb
+++ b/spec/services/work_items/create_service_spec.rb
@@ -29,7 +29,7 @@ RSpec.describe WorkItems::CreateService do
describe '#execute' do
let(:service) do
described_class.new(
- project: project,
+ container: project,
current_user: current_user,
params: opts,
spam_params: spam_params,
@@ -118,7 +118,7 @@ RSpec.describe WorkItems::CreateService do
let(:service) do
described_class.new(
- project: project,
+ container: project,
current_user: current_user,
params: opts,
spam_params: spam_params,
@@ -188,7 +188,7 @@ RSpec.describe WorkItems::CreateService do
{
title: 'Awesome work_item',
description: 'please fix',
- work_item_type: create(:work_item_type, :task)
+ work_item_type: WorkItems::Type.default_by_type(:task)
}
end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index 588fe466a42..b9a99eff413 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -12,7 +12,7 @@ module DbCleaner
end
def deletion_except_tables
- %w[work_item_types work_item_hierarchy_restrictions]
+ %w[work_item_types work_item_hierarchy_restrictions work_item_widget_definitions]
end
def setup_database_cleaner
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
index fe880e4b31b..085fec6ff1e 100644
--- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -165,7 +165,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
context "with issue events" do
let(:opts) { { title: "Awesome issue", description: "please fix" } }
let(:sample_data) do
- service = Issues::CreateService.new(project: project, current_user: user, params: opts, spam_params: nil)
+ service = Issues::CreateService.new(container: project, current_user: user, params: opts, spam_params: nil)
issue = service.execute[:issue]
service.hook_data(issue, "open")
end
diff --git a/spec/support/shared_examples/work_item_base_types_importer.rb b/spec/support/shared_examples/work_item_base_types_importer.rb
index b1011037584..1703d400aea 100644
--- a/spec/support/shared_examples/work_item_base_types_importer.rb
+++ b/spec/support/shared_examples/work_item_base_types_importer.rb
@@ -15,6 +15,22 @@ RSpec.shared_examples 'work item base types importer' do
expect(WorkItems::Type.all).to all(be_valid)
end
+ it 'creates all default widget definitions' do
+ WorkItems::WidgetDefinition.delete_all
+ widget_mapping = ::Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter::WIDGETS_FOR_TYPE
+
+ expect { subject }.to change { WorkItems::WidgetDefinition.count }.from(0).to(widget_mapping.values.flatten.count)
+
+ created_widgets = WorkItems::WidgetDefinition.global.map do |widget|
+ { name: widget.work_item_type.name, type: widget.widget_type }
+ end
+ expected_widgets = widget_mapping.flat_map do |type_sym, widget_types|
+ widget_types.map { |type| { name: ::WorkItems::Type::TYPE_NAMES[type_sym], type: type.to_s } }
+ end
+
+ expect(created_widgets).to match_array(expected_widgets)
+ end
+
it 'upserts base work item types if they already exist' do
first_type = WorkItems::Type.first
original_name = first_type.name
@@ -29,8 +45,34 @@ RSpec.shared_examples 'work item base types importer' do
)
end
- it 'executes a single INSERT query' do
- expect { subject }.to make_queries_matching(/INSERT/, 1)
+ it 'upserts default widget definitions if they already exist and type changes' do
+ widget = WorkItems::WidgetDefinition.global.find_by_widget_type(:labels)
+
+ widget.update!(widget_type: :weight)
+
+ expect do
+ subject
+ widget.reload
+ end.to not_change(WorkItems::WidgetDefinition, :count).and(
+ change { widget.widget_type }.from('weight').to('labels')
+ )
+ end
+
+ it 'does not change default widget definitions if they already exist with changed disabled status' do
+ widget = WorkItems::WidgetDefinition.global.find_by_widget_type(:labels)
+
+ widget.update!(disabled: true)
+
+ expect do
+ subject
+ widget.reload
+ end.to not_change(WorkItems::WidgetDefinition, :count).and(
+ not_change { widget.disabled }
+ )
+ end
+
+ it 'executes single INSERT query per types and widget definitions' do
+ expect { subject }.to make_queries_matching(/INSERT/, 2)
end
context 'when some base types exist' do
@@ -39,10 +81,22 @@ RSpec.shared_examples 'work item base types importer' do
end
it 'inserts all types and does nothing if some already existed' do
- expect { subject }.to make_queries_matching(/INSERT/, 1).and(
+ expect { subject }.to make_queries_matching(/INSERT/, 2).and(
change { WorkItems::Type.count }.by(1)
)
expect(WorkItems::Type.count).to eq(WorkItems::Type::BASE_TYPES.count)
end
end
+
+ context 'when some widget definitions exist' do
+ before do
+ WorkItems::WidgetDefinition.limit(1).delete_all
+ end
+
+ it 'inserts all widget definitions and does nothing if some already existed' do
+ expect { subject }.to make_queries_matching(/INSERT/, 2).and(
+ change { WorkItems::WidgetDefinition.count }.by(1)
+ )
+ end
+ end
end
diff --git a/spec/workers/pipeline_schedule_worker_spec.rb b/spec/workers/pipeline_schedule_worker_spec.rb
index db58dc00338..da6a0254a17 100644
--- a/spec/workers/pipeline_schedule_worker_spec.rb
+++ b/spec/workers/pipeline_schedule_worker_spec.rb
@@ -49,19 +49,7 @@ RSpec.describe PipelineScheduleWorker, :sidekiq_inline, feature_category: :conti
end
end
- shared_examples 'successful scheduling with/without ci_use_run_pipeline_schedule_worker' do
- it_behaves_like 'successful scheduling'
-
- context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do
- before do
- stub_feature_flags(ci_use_run_pipeline_schedule_worker: false)
- end
-
- it_behaves_like 'successful scheduling'
- end
- end
-
- it_behaves_like 'successful scheduling with/without ci_use_run_pipeline_schedule_worker'
+ it_behaves_like 'successful scheduling'
context 'when the latest commit contains [ci skip]' do
before do
@@ -70,7 +58,7 @@ RSpec.describe PipelineScheduleWorker, :sidekiq_inline, feature_category: :conti
.and_return('some commit [ci skip]')
end
- it_behaves_like 'successful scheduling with/without ci_use_run_pipeline_schedule_worker'
+ it_behaves_like 'successful scheduling'
end
end
diff --git a/spec/workers/run_pipeline_schedule_worker_spec.rb b/spec/workers/run_pipeline_schedule_worker_spec.rb
index 377333b39e8..75938d3b793 100644
--- a/spec/workers/run_pipeline_schedule_worker_spec.rb
+++ b/spec/workers/run_pipeline_schedule_worker_spec.rb
@@ -79,16 +79,6 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
expect { worker.perform(pipeline_schedule.id, user.id) }.not_to change { pipeline_schedule.reload.next_run_at }
end
- context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do
- before do
- stub_feature_flags(ci_use_run_pipeline_schedule_worker: false)
- end
-
- it 'does not change the next_run_at' do
- expect { worker.perform(pipeline_schedule.id, user.id) }.not_to change { pipeline_schedule.reload.next_run_at }
- end
- end
-
context 'when scheduling option is given as true' do
it "returns the service response" do
expect(worker.perform(pipeline_schedule.id, user.id, scheduling: true)).to eq(service_response)
@@ -103,16 +93,6 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
it "changes the next_run_at" do
expect { worker.perform(pipeline_schedule.id, user.id, scheduling: true) }.to change { pipeline_schedule.reload.next_run_at }.by(1.day)
end
-
- context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do
- before do
- stub_feature_flags(ci_use_run_pipeline_schedule_worker: false)
- end
-
- it 'does not change the next_run_at' do
- expect { worker.perform(pipeline_schedule.id, user.id, scheduling: true) }.not_to change { pipeline_schedule.reload.next_run_at }
- end
- end
end
end
@@ -148,26 +128,6 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
worker.perform(pipeline_schedule.id, user.id)
end
-
- context 'when feature flag ci_use_run_pipeline_schedule_worker is disabled' do
- let(:pipeline) { instance_double(Ci::Pipeline, persisted?: true) }
-
- before do
- stub_feature_flags(ci_use_run_pipeline_schedule_worker: false)
-
- expect(Ci::CreatePipelineService).to receive(:new).with(project, user, ref: pipeline_schedule.ref).and_return(create_pipeline_service)
-
- expect(create_pipeline_service).to receive(:execute).with(:schedule, ignore_skip_ci: true, save_on_errors: false, schedule: pipeline_schedule).and_return(service_response)
- end
-
- it 'does not change the next_run_at' do
- expect { worker.perform(pipeline_schedule.id, user.id) }.to not_change { pipeline_schedule.reload.next_run_at }
- end
-
- it "returns the service response" do
- expect(worker.perform(pipeline_schedule.id, user.id)).to eq(service_response)
- end
- end
end
end