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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /spec/graphql
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'spec/graphql')
-rw-r--r--spec/graphql/graphql_triggers_spec.rb52
-rw-r--r--spec/graphql/mutations/achievements/award_spec.rb53
-rw-r--r--spec/graphql/mutations/achievements/delete_spec.rb56
-rw-r--r--spec/graphql/mutations/achievements/revoke_spec.rb57
-rw-r--r--spec/graphql/mutations/achievements/update_spec.rb57
-rw-r--r--spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb1
-rw-r--r--spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb1
-rw-r--r--spec/graphql/mutations/alert_management/create_alert_issue_spec.rb2
-rw-r--r--spec/graphql/mutations/alert_management/update_alert_status_spec.rb1
-rw-r--r--spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb52
-rw-r--r--spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb26
-rw-r--r--spec/graphql/mutations/container_repositories/destroy_spec.rb2
-rw-r--r--spec/graphql/mutations/container_repositories/destroy_tags_spec.rb4
-rw-r--r--spec/graphql/mutations/customer_relations/contacts/create_spec.rb12
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/create_spec.rb2
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/update_spec.rb12
-rw-r--r--spec/graphql/mutations/design_management/delete_spec.rb31
-rw-r--r--spec/graphql/mutations/environments/stop_spec.rb72
-rw-r--r--spec/graphql/mutations/members/bulk_update_base_spec.rb16
-rw-r--r--spec/graphql/mutations/release_asset_links/create_spec.rb2
-rw-r--r--spec/graphql/mutations/release_asset_links/delete_spec.rb14
-rw-r--r--spec/graphql/mutations/release_asset_links/update_spec.rb2
-rw-r--r--spec/graphql/mutations/work_items/update_spec.rb21
-rw-r--r--spec/graphql/resolvers/achievements/achievements_resolver_spec.rb44
-rw-r--r--spec/graphql/resolvers/base_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/blobs_resolver_spec.rb8
-rw-r--r--spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/group_runners_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb40
-rw-r--r--spec/graphql/resolvers/ci/jobs_resolver_spec.rb21
-rw-r--r--spec/graphql/resolvers/ci/project_runners_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb26
-rw-r--r--spec/graphql/resolvers/ci/runner_status_resolver_spec.rb28
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/ci/variables_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb13
-rw-r--r--spec/graphql/resolvers/clusters/agents/authorizations/ci_access_resolver_spec.rb28
-rw-r--r--spec/graphql/resolvers/clusters/agents/authorizations/user_access_resolver_spec.rb29
-rw-r--r--spec/graphql/resolvers/crm/contacts_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/crm/organizations_resolver_spec.rb44
-rw-r--r--spec/graphql/resolvers/data_transfer/group_data_transfer_resolver_spec.rb65
-rw-r--r--spec/graphql/resolvers/data_transfer/project_data_transfer_resolver_spec.rb68
-rw-r--r--spec/graphql/resolvers/data_transfer_resolver_spec.rb31
-rw-r--r--spec/graphql/resolvers/group_labels_resolver_spec.rb34
-rw-r--r--spec/graphql/resolvers/group_milestones_resolver_spec.rb66
-rw-r--r--spec/graphql/resolvers/labels_resolver_spec.rb34
-rw-r--r--spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb14
-rw-r--r--spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb16
-rw-r--r--spec/graphql/resolvers/paginated_tree_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/project_issues_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/project_milestones_resolver_spec.rb38
-rw-r--r--spec/graphql/resolvers/timelog_resolver_spec.rb22
-rw-r--r--spec/graphql/types/achievements/achievement_type_spec.rb1
-rw-r--r--spec/graphql/types/achievements/user_achievement_type_spec.rb24
-rw-r--r--spec/graphql/types/ci/catalog/resource_type_spec.rb18
-rw-r--r--spec/graphql/types/ci/config/include_type_enum_spec.rb2
-rw-r--r--spec/graphql/types/ci/inherited_ci_variable_type_spec.rb19
-rw-r--r--spec/graphql/types/ci/job_trace_type_spec.rb27
-rw-r--r--spec/graphql/types/ci/job_type_spec.rb9
-rw-r--r--spec/graphql/types/ci/runner_manager_type_spec.rb18
-rw-r--r--spec/graphql/types/ci/runner_type_spec.rb8
-rw-r--r--spec/graphql/types/ci/variable_sort_enum_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agent_activity_event_type_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agent_token_type_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agent_type_spec.rb2
-rw-r--r--spec/graphql/types/clusters/agents/authorizations/ci_access_type_spec.rb11
-rw-r--r--spec/graphql/types/clusters/agents/authorizations/user_access_type_spec.rb11
-rw-r--r--spec/graphql/types/commit_signature_interface_spec.rb5
-rw-r--r--spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb2
-rw-r--r--spec/graphql/types/data_transfer/project_data_transfer_type_spec.rb38
-rw-r--r--spec/graphql/types/design_management/design_at_version_type_spec.rb2
-rw-r--r--spec/graphql/types/design_management/design_type_spec.rb7
-rw-r--r--spec/graphql/types/group_type_spec.rb2
-rw-r--r--spec/graphql/types/issue_type_spec.rb45
-rw-r--r--spec/graphql/types/key_type_spec.rb2
-rw-r--r--spec/graphql/types/merge_request_type_spec.rb4
-rw-r--r--spec/graphql/types/permission_types/issue_spec.rb2
-rw-r--r--spec/graphql/types/permission_types/work_item_spec.rb3
-rw-r--r--spec/graphql/types/project_member_relation_enum_spec.rb3
-rw-r--r--spec/graphql/types/project_statistics_redirect_type_spec.rb10
-rw-r--r--spec/graphql/types/project_type_spec.rb13
-rw-r--r--spec/graphql/types/projects/fork_details_type_spec.rb2
-rw-r--r--spec/graphql/types/release_asset_link_type_spec.rb2
-rw-r--r--spec/graphql/types/root_storage_statistics_type_spec.rb2
-rw-r--r--spec/graphql/types/time_tracking/timelog_connection_type_spec.rb2
-rw-r--r--spec/graphql/types/timelog_type_spec.rb2
-rw-r--r--spec/graphql/types/user_preferences_type_spec.rb3
-rw-r--r--spec/graphql/types/user_type_spec.rb3
-rw-r--r--spec/graphql/types/visibility_pipeline_id_type_enum_spec.rb13
-rw-r--r--spec/graphql/types/work_item_type_spec.rb5
-rw-r--r--spec/graphql/types/work_items/available_export_fields_enum_spec.rb27
-rw-r--r--spec/graphql/types/work_items/widget_interface_spec.rb13
-rw-r--r--spec/graphql/types/work_items/widgets/award_emoji_type_spec.rb12
-rw-r--r--spec/graphql/types/work_items/widgets/current_user_todos_input_type_spec.rb9
-rw-r--r--spec/graphql/types/work_items/widgets/current_user_todos_type_spec.rb11
-rw-r--r--spec/graphql/types/work_items/widgets/hierarchy_update_input_type_spec.rb8
-rw-r--r--spec/graphql/types/work_items/widgets/notifications_type_spec.rb12
-rw-r--r--spec/graphql/types/work_items/widgets/notifications_update_input_type_spec.rb9
99 files changed, 1325 insertions, 375 deletions
diff --git a/spec/graphql/graphql_triggers_spec.rb b/spec/graphql/graphql_triggers_spec.rb
index 00b5aec366e..a8a37289ddd 100644
--- a/spec/graphql/graphql_triggers_spec.rb
+++ b/spec/graphql/graphql_triggers_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GraphqlTriggers do
+RSpec.describe GraphqlTriggers, feature_category: :shared do
let_it_be(:issuable, refind: true) { create(:work_item) }
describe '.issuable_assignees_updated' do
@@ -12,9 +12,9 @@ RSpec.describe GraphqlTriggers do
issuable.update!(assignees: assignees)
end
- it 'triggers the issuableAssigneesUpdated subscription' do
+ it 'triggers the issuable_assignees_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableAssigneesUpdated',
+ :issuable_assignees_updated,
{ issuable_id: issuable.to_gid },
issuable
)
@@ -24,9 +24,9 @@ RSpec.describe GraphqlTriggers do
end
describe '.issuable_title_updated' do
- it 'triggers the issuableTitleUpdated subscription' do
+ it 'triggers the issuable_title_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableTitleUpdated',
+ :issuable_title_updated,
{ issuable_id: issuable.to_gid },
issuable
).and_call_original
@@ -36,9 +36,9 @@ RSpec.describe GraphqlTriggers do
end
describe '.issuable_description_updated' do
- it 'triggers the issuableDescriptionUpdated subscription' do
+ it 'triggers the issuable_description_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableDescriptionUpdated',
+ :issuable_description_updated,
{ issuable_id: issuable.to_gid },
issuable
).and_call_original
@@ -54,9 +54,9 @@ RSpec.describe GraphqlTriggers do
issuable.update!(labels: labels)
end
- it 'triggers the issuableLabelsUpdated subscription' do
+ it 'triggers the issuable_labels_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableLabelsUpdated',
+ :issuable_labels_updated,
{ issuable_id: issuable.to_gid },
issuable
)
@@ -66,9 +66,9 @@ RSpec.describe GraphqlTriggers do
end
describe '.issuable_dates_updated' do
- it 'triggers the issuableDatesUpdated subscription' do
+ it 'triggers the issuable_dates_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableDatesUpdated',
+ :issuable_dates_updated,
{ issuable_id: issuable.to_gid },
issuable
).and_call_original
@@ -78,9 +78,9 @@ RSpec.describe GraphqlTriggers do
end
describe '.issuable_milestone_updated' do
- it 'triggers the issuableMilestoneUpdated subscription' do
+ it 'triggers the issuable_milestone_updated subscription' do
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'issuableMilestoneUpdated',
+ :issuable_milestone_updated,
{ issuable_id: issuable.to_gid },
issuable
).and_call_original
@@ -90,11 +90,11 @@ RSpec.describe GraphqlTriggers do
end
describe '.merge_request_reviewers_updated' do
- it 'triggers the mergeRequestReviewersUpdated subscription' do
+ it 'triggers the merge_request_reviewers_updated subscription' do
merge_request = build_stubbed(:merge_request)
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'mergeRequestReviewersUpdated',
+ :merge_request_reviewers_updated,
{ issuable_id: merge_request.to_gid },
merge_request
).and_call_original
@@ -104,25 +104,39 @@ RSpec.describe GraphqlTriggers do
end
describe '.merge_request_merge_status_updated' do
- it 'triggers the mergeRequestMergeStatusUpdated subscription' do
+ it 'triggers the merge_request_merge_status_updated subscription' do
merge_request = build_stubbed(:merge_request)
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'mergeRequestMergeStatusUpdated',
+ :merge_request_merge_status_updated,
{ issuable_id: merge_request.to_gid },
merge_request
).and_call_original
GraphqlTriggers.merge_request_merge_status_updated(merge_request)
end
+
+ context 'when realtime_mr_status_change feature flag is disabled' do
+ before do
+ stub_feature_flags(realtime_mr_status_change: false)
+ end
+
+ it 'does not trigger realtime_mr_status_change subscription' do
+ merge_request = build_stubbed(:merge_request)
+
+ expect(GitlabSchema.subscriptions).not_to receive(:trigger)
+
+ GraphqlTriggers.merge_request_merge_status_updated(merge_request)
+ end
+ end
end
describe '.merge_request_approval_state_updated' do
- it 'triggers the mergeRequestApprovalStateUpdated subscription' do
+ it 'triggers the merge_request_approval_state_updated subscription' do
merge_request = build_stubbed(:merge_request)
expect(GitlabSchema.subscriptions).to receive(:trigger).with(
- 'mergeRequestApprovalStateUpdated',
+ :merge_request_approval_state_updated,
{ issuable_id: merge_request.to_gid },
merge_request
).and_call_original
diff --git a/spec/graphql/mutations/achievements/award_spec.rb b/spec/graphql/mutations/achievements/award_spec.rb
new file mode 100644
index 00000000000..1bfad46a616
--- /dev/null
+++ b/spec/graphql/mutations/achievements/award_spec.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Award, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:recipient) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:achievement) { create(:achievement, namespace: group) }
+
+ describe '#resolve' do
+ subject(:resolve_mutation) do
+ described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
+ achievement_id: achievement&.to_global_id, user_id: recipient&.to_global_id
+ )
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:achievement) { nil }
+
+ it 'returns the validation error' do
+ expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
+ end
+ end
+
+ it 'creates user_achievement with correct values' do
+ expect(resolve_mutation[:user_achievement]).to have_attributes({ achievement: achievement, user: recipient })
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:award_achievement) }
+end
diff --git a/spec/graphql/mutations/achievements/delete_spec.rb b/spec/graphql/mutations/achievements/delete_spec.rb
new file mode 100644
index 00000000000..0eb6f5a2e6f
--- /dev/null
+++ b/spec/graphql/mutations/achievements/delete_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:recipient) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:achievement) { create(:achievement, namespace: group) }
+
+ describe '#resolve' do
+ subject(:resolve_mutation) do
+ described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
+ achievement_id: achievement&.to_global_id
+ )
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:achievement) { nil }
+
+ it 'returns the validation error' do
+ expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
+ end
+ end
+
+ it 'deletes the achievement' do
+ resolve_mutation
+
+ expect(Achievements::Achievement.find_by(id: achievement.id)).to be_nil
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_achievement) }
+end
diff --git a/spec/graphql/mutations/achievements/revoke_spec.rb b/spec/graphql/mutations/achievements/revoke_spec.rb
new file mode 100644
index 00000000000..0c221b492af
--- /dev/null
+++ b/spec/graphql/mutations/achievements/revoke_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Revoke, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:recipient) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:achievement) { create(:achievement, namespace: group) }
+ let_it_be(:user_achievement) { create(:user_achievement, achievement: achievement) }
+
+ describe '#resolve' do
+ subject(:resolve_mutation) do
+ described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
+ user_achievement_id: user_achievement&.to_global_id
+ )
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:user_achievement) { nil }
+
+ it 'returns the validation error' do
+ expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
+ end
+ end
+
+ it 'revokes user_achievement' do
+ response = resolve_mutation[:user_achievement]
+
+ expect(response.revoked_at).not_to be_nil
+ expect(response.revoked_by_user_id).to be(current_user.id)
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:award_achievement) }
+end
diff --git a/spec/graphql/mutations/achievements/update_spec.rb b/spec/graphql/mutations/achievements/update_spec.rb
new file mode 100644
index 00000000000..b69c8bef478
--- /dev/null
+++ b/spec/graphql/mutations/achievements/update_spec.rb
@@ -0,0 +1,57 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Achievements::Update, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:recipient) { create(:user) }
+ let_it_be(:group) { create(:group) }
+
+ let(:achievement) { create(:achievement, namespace: group) }
+ let(:name) { 'Hero' }
+
+ describe '#resolve' do
+ subject(:resolve_mutation) do
+ described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
+ achievement_id: achievement&.to_global_id, name: name
+ )
+ end
+
+ before_all do
+ group.add_developer(developer)
+ group.add_maintainer(maintainer)
+ end
+
+ context 'when the user does not have permission' do
+ let(:current_user) { developer }
+
+ it 'raises an error' do
+ expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
+ .with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+
+ context 'when the user has permission' do
+ let(:current_user) { maintainer }
+
+ context 'when the params are invalid' do
+ let(:achievement) { nil }
+
+ it 'returns the validation error' do
+ expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
+ end
+ end
+
+ it 'updates the achievement' do
+ resolve_mutation
+
+ expect(Achievements::Achievement.find_by(id: achievement.id).name).to eq(name)
+ end
+ end
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_achievement) }
+end
diff --git a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
index 125e15b70cf..da5531d2b93 100644
--- a/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
+++ b/spec/graphql/mutations/alert_management/alerts/set_assignees_spec.rb
@@ -58,7 +58,6 @@ RSpec.describe Mutations::AlertManagement::Alerts::SetAssignees do
it_behaves_like 'an incident management tracked event', :incident_management_alert_assigned
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
let(:namespace) { project.namespace.reload }
let(:category) { described_class.to_s }
let(:user) { current_user }
diff --git a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
index bcb7c74fa09..8ba1e785b63 100644
--- a/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
+++ b/spec/graphql/mutations/alert_management/alerts/todo/create_spec.rb
@@ -20,7 +20,6 @@ RSpec.describe Mutations::AlertManagement::Alerts::Todo::Create do
it_behaves_like 'an incident management tracked event', :incident_management_alert_todo
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
let(:namespace) { project.namespace.reload }
let(:category) { described_class.to_s }
let(:user) { current_user }
diff --git a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
index e49596b37c9..f86046bb0d6 100644
--- a/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
+++ b/spec/graphql/mutations/alert_management/create_alert_issue_spec.rb
@@ -32,7 +32,6 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do
it_behaves_like 'an incident management tracked event', :incident_management_alert_create_incident
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
let(:namespace) { project.namespace.reload }
let(:category) { described_class.to_s }
let(:user) { current_user }
@@ -57,7 +56,6 @@ RSpec.describe Mutations::AlertManagement::CreateAlertIssue do
end
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
let(:namespace) { project.namespace.reload }
let(:category) { described_class.to_s }
let(:user) { current_user }
diff --git a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
index 22ad93df79b..fb11ec7065b 100644
--- a/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
+++ b/spec/graphql/mutations/alert_management/update_alert_status_spec.rb
@@ -36,7 +36,6 @@ RSpec.describe Mutations::AlertManagement::UpdateAlertStatus do
end
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
- let(:feature_flag_name) { :route_hll_to_snowplow_phase2 }
let(:namespace) { project.namespace }
let(:category) { described_class.to_s }
let(:user) { current_user }
diff --git a/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb b/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
index 44147987ebb..0485796fe56 100644
--- a/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
+++ b/spec/graphql/mutations/ci/job_token_scope/add_project_spec.rb
@@ -20,6 +20,10 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject, feature_category: :cont
mutation.resolve(**mutation_args)
end
+ before do
+ stub_feature_flags(frozen_outbound_job_token_scopes_override: false)
+ end
+
context 'when user is not logged in' do
let(:current_user) { nil }
@@ -43,10 +47,10 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject, feature_category: :cont
target_project.add_guest(current_user)
end
- it 'adds target project to the outbound job token scope by default' do
+ it 'adds target project to the inbound job token scope by default' do
expect do
expect(subject).to include(ci_job_token_scope: be_present, errors: be_empty)
- end.to change { Ci::JobToken::ProjectScopeLink.outbound.count }.by(1)
+ end.to change { Ci::JobToken::ProjectScopeLink.inbound.count }.by(1)
end
context 'when mutation uses the direction argument' do
@@ -55,10 +59,8 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject, feature_category: :cont
context 'when targeting the outbound allowlist' do
let(:direction) { :outbound }
- it 'adds 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.outbound.count }.by(1)
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Errors::ArgumentError)
end
end
@@ -73,6 +75,42 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject, feature_category: :cont
end
end
+ context 'when FF frozen_outbound_job_token_scopes is disabled' do
+ before do
+ stub_feature_flags(frozen_outbound_job_token_scopes: false)
+ end
+
+ it 'adds target project to the outbound job token scope by default' do
+ expect do
+ expect(subject).to include(ci_job_token_scope: be_present, errors: be_empty)
+ end.to change { Ci::JobToken::ProjectScopeLink.outbound.count }.by(1)
+ end
+
+ context 'when mutation uses the direction argument' do
+ let(:mutation_args) { super().merge!(direction: direction) }
+
+ context 'when targeting the outbound allowlist' do
+ let(:direction) { :outbound }
+
+ it 'adds 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.outbound.count }.by(1)
+ end
+ end
+
+ context 'when targeting the inbound allowlist' do
+ let(:direction) { :inbound }
+
+ it 'adds 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.inbound.count }.by(1)
+ end
+ end
+ end
+ end
+
context 'when the service returns an error' do
let(:service) { double(:service) }
@@ -81,7 +119,7 @@ RSpec.describe Mutations::Ci::JobTokenScope::AddProject, feature_category: :cont
project,
current_user
).and_return(service)
- expect(service).to receive(:execute).with(target_project, direction: :outbound).and_return(ServiceResponse.error(message: 'The error message'))
+ expect(service).to receive(:execute).with(target_project, direction: :inbound).and_return(ServiceResponse.error(message: 'The error message'))
expect(subject.fetch(:ci_job_token_scope)).to be_nil
expect(subject.fetch(:errors)).to include("The error message")
diff --git a/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb b/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb
deleted file mode 100644
index 451f6d1fe06..00000000000
--- a/spec/graphql/mutations/concerns/mutations/finds_by_gid_spec.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Mutations::FindsByGid do
- include GraphqlHelpers
-
- let(:mutation_class) do
- Class.new(Mutations::BaseMutation) do
- authorize :read_user
-
- include Mutations::FindsByGid
- end
- end
-
- let(:query) { query_double(schema: GitlabSchema) }
- let(:context) { GraphQL::Query::Context.new(query: query, object: nil, values: { current_user: user }) }
- let(:user) { create(:user) }
- let(:gid) { user.to_global_id }
-
- subject(:mutation) { mutation_class.new(object: nil, context: context, field: nil) }
-
- it 'calls GitlabSchema.find_by_gid to find objects during authorized_find!' do
- expect(mutation.authorized_find!(id: gid)).to eq(user)
- end
-end
diff --git a/spec/graphql/mutations/container_repositories/destroy_spec.rb b/spec/graphql/mutations/container_repositories/destroy_spec.rb
index 50e83ccdd30..85e0ac96e55 100644
--- a/spec/graphql/mutations/container_repositories/destroy_spec.rb
+++ b/spec/graphql/mutations/container_repositories/destroy_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Mutations::ContainerRepositories::Destroy do
.to receive(:new).with(nil, user, event_name: :delete_repository, scope: :container).and_call_original
expect(DeleteContainerRepositoryWorker).not_to receive(:perform_async)
- expect { subject }.to change { ::Packages::Event.count }.by(1)
+ subject
expect(container_repository.reload.delete_scheduled?).to be true
end
end
diff --git a/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb b/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb
index 3e5f28ee244..96dd1754155 100644
--- a/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb
+++ b/spec/graphql/mutations/container_repositories/destroy_tags_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe Mutations::ContainerRepositories::DestroyTags do
it 'creates a package event' do
expect(::Packages::CreateEventService)
.to receive(:new).with(nil, user, event_name: :delete_tag_bulk, scope: :tag).and_call_original
- expect { subject }.to change { ::Packages::Event.count }.by(1)
+ subject
end
end
@@ -87,7 +87,7 @@ RSpec.describe Mutations::ContainerRepositories::DestroyTags do
it 'does not create a package event' do
expect(::Packages::CreateEventService).not_to receive(:new)
- expect { subject }.not_to change { ::Packages::Event.count }
+ subject
end
end
end
diff --git a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
index f2bbf0949fb..3ee898c2079 100644
--- a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
@@ -57,10 +57,10 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
end
end
- context 'when attaching to an organization' do
+ context 'when attaching to an crm_organization' do
context 'when all ok' do
before do
- organization = create(:organization, group: group)
+ organization = create(:crm_organization, group: group)
valid_params[:organization_id] = organization.to_global_id
end
@@ -69,7 +69,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
end
end
- context 'when organization does not exist' do
+ context 'when crm_organization does not exist' do
before do
valid_params[:organization_id] = global_id_of(model_name: 'CustomerRelations::Organization', id: non_existing_record_id)
end
@@ -79,10 +79,10 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
end
end
- context 'when organzation belongs to a different group' do
+ context 'when crm_organzation belongs to a different group' do
before do
- organization = create(:organization)
- valid_params[:organization_id] = organization.to_global_id
+ crm_organization = create(:crm_organization)
+ valid_params[:organization_id] = crm_organization.to_global_id
end
it 'returns the relevant error' do
diff --git a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
index ffc9632350a..cf1ff2d5653 100644
--- a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Create do
let_it_be(:group) { create(:group, :crm_enabled) }
let(:valid_params) do
- attributes_for(:organization,
+ attributes_for(:crm_organization,
group: group,
description: 'This company is super important!',
default_rate: 1_000
diff --git a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
index f0f37ee9c47..2fad320b497 100644
--- a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
@@ -10,10 +10,10 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
let(:default_rate) { 1000.to_f }
let(:description) { 'VIP' }
let(:does_not_exist_or_no_permission) { Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR }
- let(:organization) { create(:organization, group: group) }
+ let(:crm_organization) { create(:crm_organization, group: group) }
let(:attributes) do
{
- id: organization.to_global_id,
+ id: crm_organization.to_global_id,
name: name,
default_rate: default_rate,
description: description
@@ -27,7 +27,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
)
end
- context 'when the user does not have permission to update an organization' do
+ context 'when the user does not have permission to update an crm_organization' do
before do
group.add_reporter(user)
end
@@ -38,7 +38,7 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
end
end
- context 'when the organization does not exist' do
+ context 'when the crm_organization does not exist' do
it 'raises an error' do
attributes[:id] = "gid://gitlab/CustomerRelations::Organization/#{non_existing_record_id}"
@@ -47,12 +47,12 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
end
end
- context 'when the user has permission to update an organization' do
+ context 'when the user has permission to update an crm_organization' do
before_all do
group.add_developer(user)
end
- it 'updates the organization with correct values' do
+ it 'updates the crm_organization with correct values' do
expect(resolve_mutation[:organization]).to have_attributes(attributes)
end
diff --git a/spec/graphql/mutations/design_management/delete_spec.rb b/spec/graphql/mutations/design_management/delete_spec.rb
index 79196d4965d..a76943b9ff8 100644
--- a/spec/graphql/mutations/design_management/delete_spec.rb
+++ b/spec/graphql/mutations/design_management/delete_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe Mutations::DesignManagement::Delete do
end
end
- it 'runs no more than 30 queries' do
+ it 'runs no more than 31 queries' do
allow(Gitlab::Tracking).to receive(:event) # rubocop:disable RSpec/ExpectGitlabTracking
filenames.each(&:present?) # ignore setup
@@ -107,22 +107,23 @@ RSpec.describe Mutations::DesignManagement::Delete do
# 14. project.authorizations for user (same query as 5)
# 15. current designs by filename and issue
# 16, 17 project.authorizations for user (same query as 5)
- # 18. find route by id and source_type
- # 19. find plan for standard context
+ # 18. find design_management_repository for project
+ # 19. find route by id and source_type
+ # 20. find plan for standard context
# ------------- our queries are below:
- # 20. start transaction 1
- # 21. start transaction 2
- # 22. find version by sha and issue
- # 23. exists version with sha and issue?
- # 24. leave transaction 2
- # 25. create version with sha and issue
- # 26. create design-version links
- # 27. validate version.actions.present?
- # 28. validate version.issue.present?
- # 29. validate version.sha is unique
- # 30. leave transaction 1
+ # 21. start transaction 1
+ # 22. start transaction 2
+ # 23. find version by sha and issue
+ # 24. exists version with sha and issue?
+ # 25. leave transaction 2
+ # 26. create version with sha and issue
+ # 27. create design-version links
+ # 28. validate version.actions.present?
+ # 29. validate version.issue.present?
+ # 30. validate version.sha is unique
+ # 31. leave transaction 1
#
- expect { run_mutation }.not_to exceed_query_limit(30)
+ expect { run_mutation }.not_to exceed_query_limit(31)
end
end
diff --git a/spec/graphql/mutations/environments/stop_spec.rb b/spec/graphql/mutations/environments/stop_spec.rb
new file mode 100644
index 00000000000..085d168bc53
--- /dev/null
+++ b/spec/graphql/mutations/environments/stop_spec.rb
@@ -0,0 +1,72 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Environments::Stop, feature_category: :environment_management do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:environment) { create(:environment, project: project, state: 'available') }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+
+ let(:user) { maintainer }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: user }, field: nil) }
+
+ before_all do
+ project.add_maintainer(maintainer)
+ project.add_reporter(reporter)
+ end
+
+ describe '#resolve' do
+ subject { mutation.resolve(id: environment_id, force: force) }
+
+ let(:environment_id) { environment.to_global_id }
+ let(:force) { false }
+
+ context 'when service execution succeeded' do
+ it 'returns no errors' do
+ expect(subject[:errors]).to be_empty
+ end
+
+ it 'stops the environment' do
+ expect(subject[:environment]).to be_stopped
+ end
+ end
+
+ context 'when service cannot change the status without force' do
+ before do
+ environment.update!(state: 'stopping')
+ end
+
+ it 'returns an error' do
+ expect(subject)
+ .to eq({
+ environment: environment,
+ errors: ['Attemped to stop the environment but failed to change the status']
+ })
+ end
+ end
+
+ context 'when force is set to true' do
+ let(:force) { true }
+
+ context 'and state transition would fail without force' do
+ before do
+ environment.update!(state: 'stopping')
+ end
+
+ it 'stops the environment' do
+ expect(subject[:environment]).to be_stopped
+ end
+ end
+ end
+
+ context 'when user is reporter who does not have permission to access the environment' do
+ let(:user) { reporter }
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/members/bulk_update_base_spec.rb b/spec/graphql/mutations/members/bulk_update_base_spec.rb
new file mode 100644
index 00000000000..61a27984824
--- /dev/null
+++ b/spec/graphql/mutations/members/bulk_update_base_spec.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::Members::BulkUpdateBase, feature_category: :subgroups do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group).tap { |group| group.add_owner(user) } }
+
+ it 'raises a NotImplementedError error if the source_type method is called on the base class' do
+ mutation = described_class.new(context: { current_user: user }, object: nil, field: nil)
+
+ expect { mutation.resolve(group_id: group.to_gid.to_s) }.to raise_error(NotImplementedError)
+ end
+end
diff --git a/spec/graphql/mutations/release_asset_links/create_spec.rb b/spec/graphql/mutations/release_asset_links/create_spec.rb
index a5291a00799..cc6c1554866 100644
--- a/spec/graphql/mutations/release_asset_links/create_spec.rb
+++ b/spec/graphql/mutations/release_asset_links/create_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Mutations::ReleaseAssetLinks::Create do
+RSpec.describe Mutations::ReleaseAssetLinks::Create, feature_category: :release_orchestration do
include GraphqlHelpers
let_it_be(:project) { create(:project, :private, :repository) }
diff --git a/spec/graphql/mutations/release_asset_links/delete_spec.rb b/spec/graphql/mutations/release_asset_links/delete_spec.rb
index cca7bd2ba38..3aecc44afd1 100644
--- a/spec/graphql/mutations/release_asset_links/delete_spec.rb
+++ b/spec/graphql/mutations/release_asset_links/delete_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Mutations::ReleaseAssetLinks::Delete do
+RSpec.describe Mutations::ReleaseAssetLinks::Delete, feature_category: :release_orchestration do
include GraphqlHelpers
let_it_be(:project) { create(:project, :private, :repository) }
@@ -60,6 +60,18 @@ RSpec.describe Mutations::ReleaseAssetLinks::Delete do
expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
end
end
+
+ context 'when destroy process fails' do
+ before do
+ allow_next_instance_of(::Releases::Links::DestroyService) do |service|
+ allow(service).to receive(:execute).and_return(ServiceResponse.error(message: 'error'))
+ end
+ end
+
+ it 'returns errors' do
+ expect(resolve).to include(errors: 'error')
+ end
+ end
end
context 'when the current user does not have access to delete the link' do
diff --git a/spec/graphql/mutations/release_asset_links/update_spec.rb b/spec/graphql/mutations/release_asset_links/update_spec.rb
index e119cf9cc77..abb091fc68d 100644
--- a/spec/graphql/mutations/release_asset_links/update_spec.rb
+++ b/spec/graphql/mutations/release_asset_links/update_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Mutations::ReleaseAssetLinks::Update do
+RSpec.describe Mutations::ReleaseAssetLinks::Update, feature_category: :release_orchestration do
include GraphqlHelpers
let_it_be(:project) { create(:project, :private, :repository) }
diff --git a/spec/graphql/mutations/work_items/update_spec.rb b/spec/graphql/mutations/work_items/update_spec.rb
new file mode 100644
index 00000000000..3acb06346a4
--- /dev/null
+++ b/spec/graphql/mutations/work_items/update_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::WorkItems::Update, feature_category: :portfolio_management do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+ let_it_be(:current_work_item) { create(:work_item, :task, project: project) }
+ let_it_be(:parent_work_item) { create(:work_item, project: project) }
+
+ subject(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ describe '#ready?' do
+ let(:current_user) { developer }
+ let(:current_gid) { current_work_item.to_gid.to_s }
+ let(:parent_gid) { parent_work_item.to_gid.to_s }
+ let(:valid_arguments) { { id: current_gid, parent_id: parent_gid } }
+
+ it { is_expected.to be_ready(**valid_arguments) }
+ end
+end
diff --git a/spec/graphql/resolvers/achievements/achievements_resolver_spec.rb b/spec/graphql/resolvers/achievements/achievements_resolver_spec.rb
new file mode 100644
index 00000000000..a70c89aa7c7
--- /dev/null
+++ b/spec/graphql/resolvers/achievements/achievements_resolver_spec.rb
@@ -0,0 +1,44 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Achievements::AchievementsResolver, feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group, :public) }
+ let_it_be(:achievements) { create_list(:achievement, 3, namespace: group) }
+
+ let(:args) { {} }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::Achievements::AchievementType.connection_type)
+ end
+
+ describe '#resolve' do
+ it 'returns all achievements' do
+ expect(resolve_achievements.items).to match_array(achievements)
+ end
+
+ context 'with ids argument' do
+ let(:args) { { ids: [achievements[0].to_global_id, achievements[1].to_global_id] } }
+
+ it 'returns the specified achievement' do
+ expect(resolve_achievements.items).to contain_exactly(achievements[0], achievements[1])
+ end
+ end
+
+ context 'when `achievements` feature flag is diabled' do
+ before do
+ stub_feature_flags(achievements: false)
+ end
+
+ it 'is empty' do
+ expect(resolve_achievements).to be_empty
+ end
+ end
+ end
+
+ def resolve_achievements
+ resolve(described_class, args: args, obj: group)
+ end
+end
diff --git a/spec/graphql/resolvers/base_resolver_spec.rb b/spec/graphql/resolvers/base_resolver_spec.rb
index 39b00c14161..d80a61fd318 100644
--- a/spec/graphql/resolvers/base_resolver_spec.rb
+++ b/spec/graphql/resolvers/base_resolver_spec.rb
@@ -112,7 +112,7 @@ RSpec.describe Resolvers::BaseResolver do
end
def resolve(foo: 1)
- [foo * foo] # rubocop: disable Lint/BinaryOperatorWithIdenticalOperands
+ [foo * foo]
end
end
end
diff --git a/spec/graphql/resolvers/blobs_resolver_spec.rb b/spec/graphql/resolvers/blobs_resolver_spec.rb
index a666ed2a9fc..26eb6dc0abe 100644
--- a/spec/graphql/resolvers/blobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/blobs_resolver_spec.rb
@@ -71,6 +71,14 @@ RSpec.describe Resolvers::BlobsResolver do
end
end
+ context 'when specifying HEAD ref' do
+ let(:ref) { 'HEAD' }
+
+ it 'returns the specified blobs for HEAD' do
+ is_expected.to contain_exactly(have_attributes(path: 'README.md'))
+ end
+ end
+
context 'when specifying an invalid ref' do
let(:ref) { 'ma:in' }
diff --git a/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb
index 5c632ed3443..fddc73fadfe 100644
--- a/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/all_jobs_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Ci::AllJobsResolver do
+RSpec.describe Resolvers::Ci::AllJobsResolver, feature_category: :continuous_integration do
include GraphqlHelpers
let_it_be(:successful_job) { create(:ci_build, :success, name: 'Job One') }
diff --git a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
index 5d06db904d5..ff343f3f43d 100644
--- a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
@@ -78,7 +78,7 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver, feature_category: :runner_fl
status_status: 'active',
type_type: :group_type,
tag_name: ['active_runner'],
- preload: { tag_name: false },
+ preload: false,
search: 'abc',
sort: 'contacted_asc',
membership: :descendants,
diff --git a/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb b/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb
new file mode 100644
index 00000000000..6837d4b0459
--- /dev/null
+++ b/spec/graphql/resolvers/ci/inherited_variables_resolver_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Ci::InheritedVariablesResolver, feature_category: :secrets_management do
+ include GraphqlHelpers
+
+ describe '#resolve' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+ let_it_be(:project) { create(:project, group: subgroup) }
+ let_it_be(:project_without_group) { create(:project) }
+
+ let_it_be(:inherited_ci_variables) do
+ [
+ create(:ci_group_variable, group: group, key: 'GROUP_VAR_A'),
+ create(:ci_group_variable, group: subgroup, key: 'SUBGROUP_VAR_B')
+ ]
+ end
+
+ subject(:resolve_variables) { resolve(described_class, obj: obj, ctx: { current_user: user }, args: {}) }
+
+ context 'when project does not have a group' do
+ let_it_be(:obj) { project_without_group }
+
+ it 'returns an empty array' do
+ expect(resolve_variables.items.to_a).to match_array([])
+ end
+ end
+
+ context 'when project belongs to a group' do
+ let_it_be(:obj) { project }
+
+ it 'returns variables from parent group and ancestors' do
+ expect(resolve_variables.items.to_a).to match_array(inherited_ci_variables)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
index 581652a8cea..b99eb56d6ab 100644
--- a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Ci::JobsResolver do
+RSpec.describe Resolvers::Ci::JobsResolver, feature_category: :continuous_integration do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository, :public) }
@@ -14,10 +14,11 @@ RSpec.describe Resolvers::Ci::JobsResolver do
create(:ci_build, :dast, name: 'SAST job', pipeline: pipeline)
create(:ci_build, :container_scanning, name: 'Container scanning job', pipeline: pipeline)
create(:ci_build, name: 'Job with tags', pipeline: pipeline, tag_list: ['review'])
+ create(:ci_bridge, name: 'Bridge job', pipeline: pipeline)
end
describe '#resolve' do
- context 'when security_report_types is empty' do
+ context 'when none of the optional params are given' do
it "returns all of the pipeline's jobs" do
jobs = resolve(described_class, obj: pipeline, arg_style: :internal)
@@ -26,7 +27,8 @@ RSpec.describe Resolvers::Ci::JobsResolver do
have_attributes(name: 'DAST job'),
have_attributes(name: 'SAST job'),
have_attributes(name: 'Container scanning job'),
- have_attributes(name: 'Job with tags')
+ have_attributes(name: 'Job with tags'),
+ have_attributes(name: 'Bridge job')
)
end
end
@@ -50,12 +52,14 @@ RSpec.describe Resolvers::Ci::JobsResolver do
context 'when a job has tags' do
it "returns jobs with tags when applicable" do
jobs = resolve(described_class, obj: pipeline, arg_style: :internal)
+
expect(jobs).to contain_exactly(
have_attributes(tag_list: []),
have_attributes(tag_list: []),
have_attributes(tag_list: []),
have_attributes(tag_list: []),
- have_attributes(tag_list: ['review'])
+ have_attributes(tag_list: ['review']),
+ have_attributes(name: 'Bridge job') # A bridge job has no tag list
)
end
end
@@ -72,5 +76,14 @@ RSpec.describe Resolvers::Ci::JobsResolver do
)
end
end
+
+ context 'when filtering by job kind' do
+ it "returns jobs with that type" do
+ jobs = resolve(described_class, obj: pipeline, arg_style: :internal, args: { job_kind: ::Ci::Bridge })
+ expect(jobs).to contain_exactly(
+ have_attributes(name: 'Bridge job')
+ )
+ end
+ end
end
end
diff --git a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
index 4cc00ced104..83435db2ea7 100644
--- a/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/project_runners_resolver_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe Resolvers::Ci::ProjectRunnersResolver, feature_category: :runner_
status_status: 'active',
type_type: :group_type,
tag_name: ['active_runner'],
- preload: { tag_name: false },
+ preload: false,
search: 'abc',
sort: 'contacted_asc',
project: project
diff --git a/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb
index 6c69cdc19cc..44203fb2912 100644
--- a/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runner_projects_resolver_spec.rb
@@ -27,6 +27,28 @@ RSpec.describe Resolvers::Ci::RunnerProjectsResolver, feature_category: :runner_
end
end
+ context 'with sort argument' do
+ let(:args) { { sort: sort } }
+
+ context 'when :id_asc' do
+ let(:sort) { :id_asc }
+
+ it 'returns a lazy value with projects sorted by :id_asc' do
+ expect(subject).to be_a(GraphQL::Execution::Lazy)
+ expect(subject.value.items).to eq([project1, project2, project3])
+ end
+ end
+
+ context 'when :id_desc' do
+ let(:sort) { :id_desc }
+
+ it 'returns a lazy value with projects sorted by :id_desc' do
+ expect(subject).to be_a(GraphQL::Execution::Lazy)
+ expect(subject.value.items).to eq([project3, project2, project1])
+ end
+ end
+ end
+
context 'with supported arguments' do
let(:args) { { membership: true, search_namespaces: true, topics: %w[xyz] } }
@@ -47,9 +69,9 @@ RSpec.describe Resolvers::Ci::RunnerProjectsResolver, feature_category: :runner_
end
context 'without arguments' do
- it 'returns a lazy value with all projects' do
+ it 'returns a lazy value with all projects sorted by :id_asc' do
expect(subject).to be_a(GraphQL::Execution::Lazy)
- expect(subject.value).to contain_exactly(project1, project2, project3)
+ expect(subject.value.items).to eq([project1, project2, project3])
end
end
end
diff --git a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb
index 2bea256856d..97a10a7da33 100644
--- a/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runner_status_resolver_spec.rb
@@ -9,32 +9,12 @@ RSpec.describe Resolvers::Ci::RunnerStatusResolver, feature_category: :runner_fl
let(:user) { build(:user) }
let(:runner) { build(:ci_runner) }
- subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, obj: runner, args: args) }
+ subject(:resolve_subject) { resolve(described_class, ctx: { current_user: user }, obj: runner) }
- context 'with legacy_mode' do
- context 'set to 14.5' do
- let(:args) do
- { legacy_mode: '14.5' }
- end
+ it 'calls runner.status and returns it' do
+ expect(runner).to receive(:status).once.and_return(:stale)
- it 'calls runner.status with specified legacy_mode' do
- expect(runner).to receive(:status).with('14.5').once.and_return(:online)
-
- expect(resolve_subject).to eq(:online)
- end
- end
-
- context 'set to nil' do
- let(:args) do
- { legacy_mode: nil }
- end
-
- it 'calls runner.status with specified legacy_mode' do
- expect(runner).to receive(:status).with(nil).once.and_return(:stale)
-
- expect(resolve_subject).to eq(:stale)
- end
- end
+ expect(resolve_subject).to eq(:stale)
end
end
end
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index d6da8222234..e4620b96cae 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
upgrade_status: 'recommended',
type_type: :instance_type,
tag_name: ['active_runner'],
- preload: { tag_name: false },
+ preload: false,
search: 'abc',
sort: 'contacted_asc'
}
@@ -108,7 +108,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
let(:expected_params) do
{
active: false,
- preload: { tag_name: false }
+ preload: false
}
end
@@ -128,7 +128,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
let(:expected_params) do
{
active: false,
- preload: { tag_name: false }
+ preload: false
}
end
@@ -146,9 +146,7 @@ RSpec.describe Resolvers::Ci::RunnersResolver, feature_category: :runner_fleet d
end
let(:expected_params) do
- {
- preload: { tag_name: false }
- }
+ { preload: false }
end
it 'calls RunnersFinder with expected arguments' do
diff --git a/spec/graphql/resolvers/ci/variables_resolver_spec.rb b/spec/graphql/resolvers/ci/variables_resolver_spec.rb
index 16b72e8cb7f..42227df1fe5 100644
--- a/spec/graphql/resolvers/ci/variables_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/variables_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Ci::VariablesResolver, feature_category: :pipeline_authoring do
+RSpec.describe Resolvers::Ci::VariablesResolver, feature_category: :secrets_management do
include GraphqlHelpers
describe '#resolve' do
diff --git a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
index 866f4ce7b5a..dfd1addff71 100644
--- a/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
+++ b/spec/graphql/resolvers/clusters/agent_tokens_resolver_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
it { expect(described_class.type).to eq(Types::Clusters::AgentTokenType) }
it { expect(described_class.null).to be_truthy }
- it { expect(described_class.arguments.keys).to contain_exactly('status') }
+ it { expect(described_class.arguments.keys).to be_empty }
describe '#resolve' do
let(:agent) { create(:cluster_agent) }
@@ -16,22 +16,15 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
let!(:matching_token1) { create(:cluster_agent_token, agent: agent, last_used_at: 5.days.ago) }
let!(:matching_token2) { create(:cluster_agent_token, agent: agent, last_used_at: 2.days.ago) }
+ let!(:revoked_token) { create(:cluster_agent_token, :revoked, agent: agent) }
let!(:other_token) { create(:cluster_agent_token) }
subject { resolve(described_class, obj: agent, ctx: ctx) }
- it 'returns tokens associated with the agent, ordered by last_used_at' do
+ it 'returns active tokens associated with the agent, ordered by last_used_at' do
expect(subject).to eq([matching_token2, matching_token1])
end
- context 'token status is specified' do
- let!(:revoked_token) { create(:cluster_agent_token, :revoked, agent: agent) }
-
- subject { resolve(described_class, obj: agent, ctx: ctx, args: { status: 'revoked' }) }
-
- it { is_expected.to contain_exactly(revoked_token) }
- end
-
context 'user does not have permission' do
let(:user) { create(:user) }
diff --git a/spec/graphql/resolvers/clusters/agents/authorizations/ci_access_resolver_spec.rb b/spec/graphql/resolvers/clusters/agents/authorizations/ci_access_resolver_spec.rb
new file mode 100644
index 00000000000..b5280365794
--- /dev/null
+++ b/spec/graphql/resolvers/clusters/agents/authorizations/ci_access_resolver_spec.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Clusters::Agents::Authorizations::CiAccessResolver,
+ feature_category: :deployment_management do
+ include GraphqlHelpers
+
+ it { expect(described_class.type).to eq(Types::Clusters::Agents::Authorizations::CiAccessType) }
+ it { expect(described_class.null).to be_truthy }
+
+ describe '#resolve' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ let(:ctx) { { current_user: user } }
+
+ subject { resolve(described_class, obj: project, ctx: ctx) }
+
+ it 'calls the finder' do
+ expect_next_instance_of(::Clusters::Agents::Authorizations::CiAccess::Finder, project) do |finder|
+ expect(finder).to receive(:execute)
+ end
+
+ subject
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/clusters/agents/authorizations/user_access_resolver_spec.rb b/spec/graphql/resolvers/clusters/agents/authorizations/user_access_resolver_spec.rb
new file mode 100644
index 00000000000..b7e2fef78eb
--- /dev/null
+++ b/spec/graphql/resolvers/clusters/agents/authorizations/user_access_resolver_spec.rb
@@ -0,0 +1,29 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Clusters::Agents::Authorizations::UserAccessResolver,
+ feature_category: :deployment_management do
+ include GraphqlHelpers
+
+ it { expect(described_class.type).to eq(Types::Clusters::Agents::Authorizations::UserAccessType) }
+ it { expect(described_class.null).to be_truthy }
+
+ describe '#resolve' do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { create(:user, maintainer_projects: [project]) }
+
+ let(:ctx) { { current_user: user } }
+
+ subject { resolve(described_class, obj: project, ctx: ctx) }
+
+ it 'calls the finder' do
+ expect_next_instance_of(::Clusters::Agents::Authorizations::UserAccess::Finder,
+ user, project: project) do |finder|
+ expect(finder).to receive(:execute)
+ end
+
+ subject
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
index c7c2d11e114..1a53f42633f 100644
--- a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
+++ b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
@@ -16,7 +16,7 @@ RSpec.describe Resolvers::Crm::ContactsResolver do
last_name: "DEF",
email: "ghi@test.com",
description: "LMNO",
- organization: create(:organization, group: group),
+ organization: create(:crm_organization, group: group),
state: "inactive"
)
end
diff --git a/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb b/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb
index c6ad4beeee0..f6c2040b7d0 100644
--- a/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb
@@ -9,10 +9,10 @@ RSpec.describe Resolvers::Crm::OrganizationStateCountsResolver do
let_it_be(:group) { create(:group, :crm_enabled) }
before_all do
- create(:organization, group: group, name: "ABC Corp")
- create(:organization, group: group, name: "123 Corp", state: 'inactive')
- create_list(:organization, 3, group: group)
- create_list(:organization, 2, group: group, state: 'inactive')
+ create(:crm_organization, group: group, name: "ABC Corp")
+ create(:crm_organization, group: group, name: "123 Corp", state: 'inactive')
+ create_list(:crm_organization, 3, group: group)
+ create_list(:crm_organization, 2, group: group, state: 'inactive')
end
describe '#resolve' do
@@ -36,7 +36,7 @@ RSpec.describe Resolvers::Crm::OrganizationStateCountsResolver do
context 'with a group' do
context 'when no filter is provided' do
- it 'returns the count of all organizations' do
+ it 'returns the count of all crm_organizations' do
counts = resolve_counts(group)
expect(counts['active']).to eq(4)
expect(counts['inactive']).to eq(3)
diff --git a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb
index d5980bf3c41..edc1986799a 100644
--- a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb
+++ b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb
@@ -8,18 +8,18 @@ RSpec.describe Resolvers::Crm::OrganizationsResolver do
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :crm_enabled) }
- let_it_be(:organization_a) do
+ let_it_be(:crm_organization_a) do
create(
- :organization,
+ :crm_organization,
group: group,
name: "ABC",
state: "inactive"
)
end
- let_it_be(:organization_b) do
+ let_it_be(:crm_organization_b) do
create(
- :organization,
+ :crm_organization,
group: group,
name: "DEF",
state: "active"
@@ -28,23 +28,23 @@ RSpec.describe Resolvers::Crm::OrganizationsResolver do
describe '#resolve' do
context 'with unauthorized user' do
- it 'does not rise an error and returns no organizations' do
+ it 'does not rise an error and returns no crm_organizations' do
expect { resolve_organizations(group) }.not_to raise_error
expect(resolve_organizations(group)).to be_empty
end
end
context 'with authorized user' do
- it 'does not rise an error and returns all organizations in the correct order' do
+ it 'does not rise an error and returns all crm_organizations in the correct order' do
group.add_reporter(user)
expect { resolve_organizations(group) }.not_to raise_error
- expect(resolve_organizations(group)).to eq([organization_a, organization_b])
+ expect(resolve_organizations(group)).to eq([crm_organization_a, crm_organization_b])
end
end
context 'without parent' do
- it 'returns no organizations' do
+ it 'returns no crm_organizations' do
expect(resolve_organizations(nil)).to be_empty
end
end
@@ -55,40 +55,42 @@ RSpec.describe Resolvers::Crm::OrganizationsResolver do
end
context 'when no filter is provided' do
- it 'returns all the organizations in the default order' do
- expect(resolve_organizations(group)).to eq([organization_a, organization_b])
+ it 'returns all the crm_organizations in the default order' do
+ expect(resolve_organizations(group)).to eq([crm_organization_a, crm_organization_b])
end
end
context 'when a sort is provided' do
- it 'returns all the organizations in the correct order' do
- expect(resolve_organizations(group, { sort: 'NAME_DESC' })).to eq([organization_b, organization_a])
+ it 'returns all the crm_organizations in the correct order' do
+ expect(resolve_organizations(group, { sort: 'NAME_DESC' })).to eq([crm_organization_b, crm_organization_a])
end
end
context 'when filtering for all states' do
- it 'returns all the organizations' do
- expect(resolve_organizations(group, { state: 'all' })).to contain_exactly(organization_a, organization_b)
+ it 'returns all the crm_organizations' do
+ expect(resolve_organizations(group, { state: 'all' })).to contain_exactly(
+ crm_organization_a, crm_organization_b
+ )
end
end
context 'when search term is provided' do
- it 'returns the correct organizations' do
- expect(resolve_organizations(group, { search: "def" })).to contain_exactly(organization_b)
+ it 'returns the correct crm_organizations' do
+ expect(resolve_organizations(group, { search: "def" })).to contain_exactly(crm_organization_b)
end
end
context 'when state is provided' do
- it 'returns the correct organizations' do
- expect(resolve_organizations(group, { state: :inactive })).to contain_exactly(organization_a)
+ it 'returns the correct crm_organizations' do
+ expect(resolve_organizations(group, { state: :inactive })).to contain_exactly(crm_organization_a)
end
end
context 'when ids are provided' do
- it 'returns the correct organizations' do
+ it 'returns the correct crm_organizations' do
expect(resolve_organizations(group, {
- ids: [organization_b.to_global_id]
- })).to contain_exactly(organization_b)
+ ids: [crm_organization_b.to_global_id]
+ })).to contain_exactly(crm_organization_b)
end
end
end
diff --git a/spec/graphql/resolvers/data_transfer/group_data_transfer_resolver_spec.rb b/spec/graphql/resolvers/data_transfer/group_data_transfer_resolver_spec.rb
new file mode 100644
index 00000000000..4ea3d287454
--- /dev/null
+++ b/spec/graphql/resolvers/data_transfer/group_data_transfer_resolver_spec.rb
@@ -0,0 +1,65 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::DataTransfer::GroupDataTransferResolver, feature_category: :source_code_management do
+ include GraphqlHelpers
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:from) { Date.new(2022, 1, 1) }
+ let(:to) { Date.new(2023, 1, 1) }
+ let(:finder_results) do
+ [
+ build(:project_data_transfer, date: to, repository_egress: 250000)
+ ]
+ end
+
+ context 'with anonymous access' do
+ let_it_be(:current_user) { nil }
+
+ it 'does not raise an error and returns no data' do
+ expect { resolve_egress }.not_to raise_error
+ expect(resolve_egress).to be_nil
+ end
+ end
+
+ context 'with authorized user but without enough permissions' do
+ it 'does not raise an error and returns no data' do
+ group.add_developer(current_user)
+
+ expect { resolve_egress }.not_to raise_error
+ expect(resolve_egress).to be_nil
+ end
+ end
+
+ context 'when user has permissions to see data transfer' do
+ before do
+ group.add_owner(current_user)
+ end
+
+ include_examples 'Data transfer resolver'
+
+ context 'when data_transfer_monitoring_mock_data is disabled' do
+ let(:finder) { instance_double(::DataTransfer::GroupDataTransferFinder) }
+
+ before do
+ stub_feature_flags(data_transfer_monitoring_mock_data: false)
+ end
+
+ it 'calls GroupDataTransferFinder with expected arguments' do
+ expect(::DataTransfer::GroupDataTransferFinder).to receive(:new).with(
+ group: group, from: from, to: to, user: current_user
+ ).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return(finder_results)
+
+ expect(resolve_egress).to eq({ egress_nodes: finder_results.map(&:attributes) })
+ end
+ end
+ end
+
+ def resolve_egress
+ resolve(described_class, obj: group, args: { from: from, to: to }, ctx: { current_user: current_user })
+ end
+end
diff --git a/spec/graphql/resolvers/data_transfer/project_data_transfer_resolver_spec.rb b/spec/graphql/resolvers/data_transfer/project_data_transfer_resolver_spec.rb
new file mode 100644
index 00000000000..7307c1a54a9
--- /dev/null
+++ b/spec/graphql/resolvers/data_transfer/project_data_transfer_resolver_spec.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::DataTransfer::ProjectDataTransferResolver, feature_category: :source_code_management do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:current_user) { create(:user) }
+
+ let(:from) { Date.new(2022, 1, 1) }
+ let(:to) { Date.new(2023, 1, 1) }
+ let(:finder_results) do
+ [
+ {
+ date: to,
+ repository_egress: 250000
+ }
+ ]
+ end
+
+ context 'with anonymous access' do
+ let_it_be(:current_user) { nil }
+
+ it 'does not raise an error and returns no data' do
+ expect { resolve_egress }.not_to raise_error
+ expect(resolve_egress).to be_nil
+ end
+ end
+
+ context 'with authorized user but without enough permissions' do
+ it 'does not raise an error and returns no data' do
+ project.add_developer(current_user)
+
+ expect { resolve_egress }.not_to raise_error
+ expect(resolve_egress).to be_nil
+ end
+ end
+
+ context 'when user has permissions to see data transfer' do
+ before do
+ project.add_owner(current_user)
+ end
+
+ include_examples 'Data transfer resolver'
+
+ context 'when data_transfer_monitoring_mock_data is disabled' do
+ let(:finder) { instance_double(::DataTransfer::ProjectDataTransferFinder) }
+
+ before do
+ stub_feature_flags(data_transfer_monitoring_mock_data: false)
+ end
+
+ it 'calls ProjectDataTransferFinder with expected arguments' do
+ expect(::DataTransfer::ProjectDataTransferFinder).to receive(:new).with(
+ project: project, from: from, to: to, user: current_user
+ ).once.and_return(finder)
+ allow(finder).to receive(:execute).once.and_return(finder_results)
+
+ expect(resolve_egress).to eq({ egress_nodes: finder_results })
+ end
+ end
+ end
+
+ def resolve_egress
+ resolve(described_class, obj: project, args: { from: from, to: to }, ctx: { current_user: current_user })
+ end
+end
diff --git a/spec/graphql/resolvers/data_transfer_resolver_spec.rb b/spec/graphql/resolvers/data_transfer_resolver_spec.rb
deleted file mode 100644
index f5a088dc1c3..00000000000
--- a/spec/graphql/resolvers/data_transfer_resolver_spec.rb
+++ /dev/null
@@ -1,31 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Resolvers::DataTransferResolver, feature_category: :source_code_management do
- include GraphqlHelpers
-
- describe '.source' do
- context 'with base DataTransferResolver' do
- it 'raises NotImplementedError' do
- expect { described_class.source }.to raise_error ::NotImplementedError
- end
- end
-
- context 'with projects DataTransferResolver' do
- let(:source) { described_class.project.source }
-
- it 'outputs "Project"' do
- expect(source).to eq 'Project'
- end
- end
-
- context 'with groups DataTransferResolver' do
- let(:source) { described_class.group.source }
-
- it 'outputs "Group"' do
- expect(source).to eq 'Group'
- end
- end
- end
-end
diff --git a/spec/graphql/resolvers/group_labels_resolver_spec.rb b/spec/graphql/resolvers/group_labels_resolver_spec.rb
index 71290885e6b..341448d7add 100644
--- a/spec/graphql/resolvers/group_labels_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_labels_resolver_spec.rb
@@ -48,6 +48,40 @@ RSpec.describe Resolvers::GroupLabelsResolver do
end
end
+ describe 'association preloading', :saas do
+ let(:params) do
+ {
+ include_ancestor_groups: true,
+ include_descendant_groups: true,
+ only_group_labels: false
+ }
+ end
+
+ before do
+ group.add_developer(current_user)
+
+ # warmup
+ resolve_labels(group, params).to_a
+ end
+
+ it 'prevents N+1 queries' do
+ control = Gitlab::WithRequestStore.with_request_store do
+ ActiveRecord::QueryRecorder.new { resolve_labels(group, params).to_a }
+ end
+
+ another_project = create(:project, :private, group: sub_subgroup)
+ another_subgroup = create(:group, :private, parent: group)
+ create(:label, project: another_project, name: 'another project feature')
+ create(:group_label, group: another_subgroup, name: 'another group feature')
+
+ expect do
+ Gitlab::WithRequestStore.with_request_store do
+ resolve_labels(group, params).to_a
+ end
+ end.not_to exceed_query_limit(control.count)
+ end
+ end
+
context 'at group level' do
before_all do
group.add_developer(current_user)
diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
index a32a031a88f..b9b8ef1870b 100644
--- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
@@ -2,15 +2,15 @@
require 'spec_helper'
-RSpec.describe Resolvers::GroupMilestonesResolver do
+RSpec.describe Resolvers::GroupMilestonesResolver, feature_category: :team_planning do
using RSpec::Parameterized::TableSyntax
include GraphqlHelpers
describe '#resolve' do
let_it_be(:current_user) { create(:user) }
- def resolve_group_milestones(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: group, args: args, ctx: context, arg_style: :internal)
+ def resolve_group_milestones(args: {}, context: { current_user: current_user }, arg_style: :internal)
+ resolve(described_class, obj: group, args: args, ctx: context, arg_style: arg_style)
end
let_it_be(:now) { Time.now }
@@ -45,18 +45,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
end
context 'with parameters' do
- it 'calls MilestonesFinder with correct parameters' do
- start_date = now
- end_date = start_date + 1.hour
-
- expect(MilestonesFinder).to receive(:new)
- .with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
- .and_call_original
-
- resolve_group_milestones(start_date: start_date, end_date: end_date, state: 'closed')
- end
-
- it 'understands the timeframe argument' do
+ it 'timeframe argument' do
start_date = now
end_date = start_date + 1.hour
@@ -64,7 +53,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(group_ids: group.id, state: 'closed', start_date: start_date, end_date: end_date))
.and_call_original
- resolve_group_milestones(timeframe: { start: start_date, end: end_date }, state: 'closed')
+ resolve_group_milestones(args: { timeframe: { start: start_date, end: end_date }, state: 'closed' })
end
end
@@ -76,7 +65,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(ids: [milestone.id.to_s], group_ids: group.id, state: 'all'))
.and_call_original
- resolve_group_milestones(ids: [milestone.to_global_id])
+ resolve_group_milestones(args: { ids: [milestone.to_global_id] })
end
end
@@ -86,12 +75,12 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
.with(args(group_ids: group.id, state: 'all', sort: :due_date_desc))
.and_call_original
- resolve_group_milestones(sort: :due_date_desc)
+ resolve_group_milestones(args: { sort: :due_date_desc })
end
%i[expired_last_due_date_asc expired_last_due_date_desc].each do |sort_by|
it "uses offset-pagination when sorting by #{sort_by}" do
- resolved = resolve_group_milestones(sort: sort_by)
+ resolved = resolve_group_milestones(args: { sort: sort_by })
expect(resolved).to be_a(::Gitlab::Graphql::Pagination::OffsetActiveRecordRelationConnection)
end
@@ -99,31 +88,18 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
end
context 'by timeframe' do
- context 'when start_date and end_date are present' do
- context 'when start date is after end_date' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, "startDate is after endDate") do
- resolve_group_milestones(start_date: now, end_date: now - 2.days)
+ context 'when timeframe start and end are present' do
+ context 'when start is after end' do
+ it 'raises error' do
+ expect_graphql_error_to_be_created(::Gitlab::Graphql::Errors::ArgumentError, 'start must be before end') do
+ resolve_group_milestones(
+ args: { timeframe: { start: now.to_date, end: now.to_date - 2.days } },
+ arg_style: :internal_prepared
+ )
end
end
end
end
-
- context 'when only start_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_group_milestones(start_date: now)
- end
- end
- end
-
- context 'when only end_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_group_milestones(end_date: now)
- end
- end
- end
end
context 'when including descendant milestones in a public group' do
@@ -143,7 +119,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
create(:milestone, group: inaccessible_group)
create(:milestone, project: inaccessible_project)
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
end
end
@@ -169,7 +145,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { {} }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1])
end
end
@@ -177,7 +153,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_descendants: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3])
end
end
@@ -185,7 +161,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_ancestors: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone6])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone6])
end
end
@@ -193,7 +169,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
let(:args) { { include_descendants: true, include_ancestors: true } }
it 'finds milestones only in accessible projects and groups' do
- expect(resolve_group_milestones(args)).to match_array([milestone1, milestone2, milestone3, milestone6])
+ expect(resolve_group_milestones(args: args)).to match_array([milestone1, milestone2, milestone3, milestone6])
end
end
end
diff --git a/spec/graphql/resolvers/labels_resolver_spec.rb b/spec/graphql/resolvers/labels_resolver_spec.rb
index efd2596b9eb..8196315dd7c 100644
--- a/spec/graphql/resolvers/labels_resolver_spec.rb
+++ b/spec/graphql/resolvers/labels_resolver_spec.rb
@@ -48,6 +48,40 @@ RSpec.describe Resolvers::LabelsResolver do
end
end
+ describe 'association preloading' do
+ let_it_be(:project) { create(:project, :private, group: sub_subgroup) }
+
+ let(:params) do
+ {
+ include_ancestor_groups: true
+ }
+ end
+
+ before do
+ group.add_developer(current_user)
+
+ # warmup
+ resolve_labels(project, params).to_a
+ end
+
+ it 'prevents N+1 queries' do
+ control = Gitlab::WithRequestStore.with_request_store do
+ ActiveRecord::QueryRecorder.new { resolve_labels(project, params).to_a }
+ end
+
+ another_project = create(:project, :private, group: subgroup)
+ another_subgroup = create(:group, :private, parent: group)
+ create(:label, project: another_project, name: 'another project feature')
+ create(:group_label, group: another_subgroup, name: 'another group feature')
+
+ expect do
+ Gitlab::WithRequestStore.with_request_store do
+ resolve_labels(project, params).to_a
+ end
+ end.not_to exceed_query_limit(control.count)
+ end
+ end
+
context 'with a parent project' do
before_all do
group.add_developer(current_user)
diff --git a/spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb b/spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb
index 4112e3d4fe6..354fd350aa7 100644
--- a/spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb
+++ b/spec/graphql/resolvers/metrics/dashboard_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Metrics::DashboardResolver do
+RSpec.describe Resolvers::Metrics::DashboardResolver, feature_category: :metrics do
include GraphqlHelpers
let_it_be(:current_user) { create(:user) }
@@ -21,6 +21,7 @@ RSpec.describe Resolvers::Metrics::DashboardResolver do
let(:parent_object) { create(:environment, project: project) }
before do
+ stub_feature_flags(remove_monitor_metrics: false)
project.add_developer(current_user)
end
@@ -39,6 +40,17 @@ RSpec.describe Resolvers::Metrics::DashboardResolver do
expect(resolve_dashboard).to be_nil
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns nil', :aggregate_failures do
+ expect(PerformanceMonitoring::PrometheusDashboard).not_to receive(:find_for)
+ expect(resolve_dashboard).to be_nil
+ end
+ end
end
end
end
diff --git a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
index a83cef40bdf..2ca194d519c 100644
--- a/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
+++ b/spec/graphql/resolvers/metrics/dashboards/annotation_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
+RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver, feature_category: :metrics do
include GraphqlHelpers
describe '#resolve' do
@@ -25,6 +25,10 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
environment.project.add_developer(current_user)
end
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
context 'with annotation records' do
let_it_be(:annotation_1) { create(:metrics_dashboard_annotation, environment: environment, starting_at: 9.minutes.ago, dashboard_path: path) }
@@ -55,6 +59,16 @@ RSpec.describe Resolvers::Metrics::Dashboards::AnnotationResolver do
expect(resolve_annotations).to be_empty
end
end
+
+ context 'when metrics dashboard feature is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ it 'returns nothing' do
+ expect(resolve_annotations).to be_nil
+ end
+ end
end
end
end
diff --git a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
index 9a04b716001..931d4ba132c 100644
--- a/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
+++ b/spec/graphql/resolvers/paginated_tree_resolver_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Resolvers::PaginatedTreeResolver do
+RSpec.describe Resolvers::PaginatedTreeResolver, feature_category: :source_code_management do
include GraphqlHelpers
let_it_be(:project) { create(:project, :repository) }
@@ -61,6 +61,16 @@ RSpec.describe Resolvers::PaginatedTreeResolver do
end
end
+ context 'when repository is empty' do
+ before do
+ allow(repository).to receive(:empty?).and_return(true)
+ end
+
+ it 'returns nil' do
+ is_expected.to be(nil)
+ end
+ end
+
describe 'Cursor pagination' do
context 'when cursor is invalid' do
let(:args) { super().merge(after: 'invalid') }
diff --git a/spec/graphql/resolvers/project_issues_resolver_spec.rb b/spec/graphql/resolvers/project_issues_resolver_spec.rb
index b2796ad9b18..a510baab5a9 100644
--- a/spec/graphql/resolvers/project_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_issues_resolver_spec.rb
@@ -359,9 +359,9 @@ RSpec.describe Resolvers::ProjectIssuesResolver do
end
describe 'filtering by crm' do
- let_it_be(:organization) { create(:organization, group: group) }
- let_it_be(:contact1) { create(:contact, group: group, organization: organization) }
- let_it_be(:contact2) { create(:contact, group: group, organization: organization) }
+ let_it_be(:crm_organization) { create(:crm_organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: crm_organization) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: crm_organization) }
let_it_be(:contact3) { create(:contact, group: group) }
let_it_be(:crm_issue1) { create(:issue, project: project) }
let_it_be(:crm_issue2) { create(:issue, project: project) }
@@ -381,9 +381,9 @@ RSpec.describe Resolvers::ProjectIssuesResolver do
end
end
- context 'when filtering by organization' do
+ context 'when filtering by crm_organization' do
it 'returns only the issues for the contact' do
- expect(resolve_issues({ crm_organization_id: organization.id })).to contain_exactly(crm_issue1, crm_issue2)
+ expect(resolve_issues({ crm_organization_id: crm_organization.id })).to contain_exactly(crm_issue1, crm_issue2)
end
end
end
diff --git a/spec/graphql/resolvers/project_milestones_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
index ad1190e3df7..af6b16804b0 100644
--- a/spec/graphql/resolvers/project_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
@@ -94,44 +94,6 @@ RSpec.describe 'Resolvers::ProjectMilestonesResolver' do
end
context 'by timeframe' do
- context 'when start_date and end_date are present' do
- it 'calls MilestonesFinder with correct parameters' do
- start_date = now
- end_date = now + 5.days
-
- expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'all',
- start_date: start_date, end_date: end_date, sort: :due_date_asc))
- .and_call_original
-
- resolve_project_milestones(start_date: start_date, end_date: end_date)
- end
-
- context 'when start date is after end_date' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'startDate is after endDate') do
- resolve_project_milestones(start_date: now, end_date: now - 2.days)
- end
- end
- end
- end
-
- context 'when only start_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_project_milestones(start_date: now)
- end
- end
- end
-
- context 'when only end_date is present' do
- it 'generates an error' do
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, /Both startDate and endDate/) do
- resolve_project_milestones(end_date: now)
- end
- end
- end
-
context 'when passing a timeframe' do
it 'calls MilestonesFinder with correct parameters' do
start_date = now_date
diff --git a/spec/graphql/resolvers/timelog_resolver_spec.rb b/spec/graphql/resolvers/timelog_resolver_spec.rb
index cd52308d895..5177873321c 100644
--- a/spec/graphql/resolvers/timelog_resolver_spec.rb
+++ b/spec/graphql/resolvers/timelog_resolver_spec.rb
@@ -214,7 +214,11 @@ RSpec.describe Resolvers::TimelogResolver, feature_category: :team_planning do
let_it_be(:timelog3) { create(:merge_request_timelog, merge_request: merge_request, user: current_user) }
it 'blah' do
- expect(timelogs).to contain_exactly(timelog1, timelog3)
+ if user_found
+ expect(timelogs).to contain_exactly(timelog1, timelog3)
+ else
+ expect(timelogs).to be_empty
+ end
end
end
@@ -250,16 +254,28 @@ RSpec.describe Resolvers::TimelogResolver, feature_category: :team_planning do
let(:object) { current_user }
let(:extra_args) { {} }
let(:args) { {} }
+ let(:user_found) { true }
it_behaves_like 'with a user'
end
context 'with a user filter' do
let(:object) { nil }
- let(:extra_args) { { username: current_user.username } }
let(:args) { {} }
- it_behaves_like 'with a user'
+ context 'when the user has timelogs' do
+ let(:extra_args) { { username: current_user.username } }
+ let(:user_found) { true }
+
+ it_behaves_like 'with a user'
+ end
+
+ context 'when the user doest not have timelogs' do
+ let(:extra_args) { { username: 'not_existing_user' } }
+ let(:user_found) { false }
+
+ it_behaves_like 'with a user'
+ end
end
context 'when no object or arguments provided' do
diff --git a/spec/graphql/types/achievements/achievement_type_spec.rb b/spec/graphql/types/achievements/achievement_type_spec.rb
index f967dc8e25e..08fadcdff22 100644
--- a/spec/graphql/types/achievements/achievement_type_spec.rb
+++ b/spec/graphql/types/achievements/achievement_type_spec.rb
@@ -14,6 +14,7 @@ RSpec.describe GitlabSchema.types['Achievement'], feature_category: :user_profil
description
created_at
updated_at
+ user_achievements
]
end
diff --git a/spec/graphql/types/achievements/user_achievement_type_spec.rb b/spec/graphql/types/achievements/user_achievement_type_spec.rb
new file mode 100644
index 00000000000..b7fe4d815f7
--- /dev/null
+++ b/spec/graphql/types/achievements/user_achievement_type_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['UserAchievement'], feature_category: :user_profile do
+ include GraphqlHelpers
+
+ let(:fields) do
+ %w[
+ id
+ achievement
+ user
+ awarded_by_user
+ revoked_by_user
+ created_at
+ updated_at
+ revoked_at
+ ]
+ end
+
+ it { expect(described_class.graphql_name).to eq('UserAchievement') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+ it { expect(described_class).to require_graphql_authorizations(:read_user_achievement) }
+end
diff --git a/spec/graphql/types/ci/catalog/resource_type_spec.rb b/spec/graphql/types/ci/catalog/resource_type_spec.rb
new file mode 100644
index 00000000000..d0bb45a4f1d
--- /dev/null
+++ b/spec/graphql/types/ci/catalog/resource_type_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::Ci::Catalog::ResourceType, feature_category: :pipeline_composition do
+ specify { expect(described_class.graphql_name).to eq('CiCatalogResource') }
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[
+ id
+ name
+ description
+ icon
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/config/include_type_enum_spec.rb b/spec/graphql/types/ci/config/include_type_enum_spec.rb
index a88316ae6f2..a75b9018a2e 100644
--- a/spec/graphql/types/ci/config/include_type_enum_spec.rb
+++ b/spec/graphql/types/ci/config/include_type_enum_spec.rb
@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['CiConfigIncludeType'] do
it { expect(described_class.graphql_name).to eq('CiConfigIncludeType') }
it 'exposes all the existing include types' do
- expect(described_class.values.keys).to match_array(%w[remote local file template])
+ expect(described_class.values.keys).to match_array(%w[remote local file template component])
end
end
diff --git a/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb
new file mode 100644
index 00000000000..daf80ff9978
--- /dev/null
+++ b/spec/graphql/types/ci/inherited_ci_variable_type_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['InheritedCiVariable'], feature_category: :secrets_management do
+ specify do
+ expect(described_class).to have_graphql_fields(
+ :id,
+ :key,
+ :raw,
+ :variable_type,
+ :environment_scope,
+ :masked,
+ :protected,
+ :group_name,
+ :group_ci_cd_settings_path
+ ).at_least
+ end
+end
diff --git a/spec/graphql/types/ci/job_trace_type_spec.rb b/spec/graphql/types/ci/job_trace_type_spec.rb
new file mode 100644
index 00000000000..71803aa9ece
--- /dev/null
+++ b/spec/graphql/types/ci/job_trace_type_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiJobTrace'], feature_category: :continuous_integration do
+ include GraphqlHelpers
+
+ let_it_be(:job) { create(:ci_build) }
+
+ it 'has the correct fields' do
+ expected_fields = [:html_summary]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+
+ it 'shows the correct trace contents' do
+ job.trace.set('BUILD TRACE')
+
+ expect_next_instance_of(Gitlab::Ci::Trace) do |trace|
+ expect(trace).to receive(:html).with(last_lines: 10).and_call_original
+ end
+
+ resolved_field = resolve_field(:html_summary, job.trace)
+
+ expect(resolved_field).to eq("<span>BUILD TRACE</span>")
+ end
+end
diff --git a/spec/graphql/types/ci/job_type_spec.rb b/spec/graphql/types/ci/job_type_spec.rb
index 714eaebfe73..e927bac431c 100644
--- a/spec/graphql/types/ci/job_type_spec.rb
+++ b/spec/graphql/types/ci/job_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Types::Ci::JobType do
+RSpec.describe Types::Ci::JobType, feature_category: :continuous_integration do
include GraphqlHelpers
specify { expect(described_class.graphql_name).to eq('CiJob') }
@@ -40,6 +40,8 @@ RSpec.describe Types::Ci::JobType do
refPath
retryable
retried
+ runner
+ runnerManager
scheduledAt
schedulingType
shortSha
@@ -51,6 +53,11 @@ RSpec.describe Types::Ci::JobType do
triggered
userPermissions
webPath
+ playPath
+ canPlayJob
+ scheduled
+ trace
+ failure_message
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/runner_manager_type_spec.rb b/spec/graphql/types/ci/runner_manager_type_spec.rb
new file mode 100644
index 00000000000..240e1edbf78
--- /dev/null
+++ b/spec/graphql/types/ci/runner_manager_type_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['CiRunnerManager'], feature_category: :runner_fleet do
+ specify { expect(described_class.graphql_name).to eq('CiRunnerManager') }
+
+ specify { expect(described_class).to require_graphql_authorizations(:read_runner_manager) }
+
+ it 'contains attributes related to a runner manager' do
+ expected_fields = %w[
+ architecture_name contacted_at created_at executor_name id ip_address platform_name revision
+ runner status system_id version
+ ]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/ci/runner_type_spec.rb b/spec/graphql/types/ci/runner_type_spec.rb
index a2d107ae295..dc664f281b7 100644
--- a/spec/graphql/types/ci/runner_type_spec.rb
+++ b/spec/graphql/types/ci/runner_type_spec.rb
@@ -9,11 +9,11 @@ RSpec.describe GitlabSchema.types['CiRunner'], feature_category: :runner do
it 'contains attributes related to a runner' do
expected_fields = %w[
- id description created_at contacted_at maximum_timeout access_level active paused status
+ id description created_by created_at contacted_at managers maximum_timeout access_level active paused status
version short_sha revision locked run_untagged ip_address runner_type tag_list
- project_count job_count admin_url edit_admin_url user_permissions executor_name architecture_name platform_name
- maintenance_note maintenance_note_html groups projects jobs token_expires_at owner_project job_execution_status
- ephemeral_authentication_token
+ project_count job_count admin_url edit_admin_url register_admin_url user_permissions executor_name
+ architecture_name platform_name maintenance_note maintenance_note_html groups projects jobs token_expires_at
+ owner_project job_execution_status ephemeral_authentication_token ephemeral_register_url
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/variable_sort_enum_spec.rb b/spec/graphql/types/ci/variable_sort_enum_spec.rb
index 1702360a21f..8bfe6dde915 100644
--- a/spec/graphql/types/ci/variable_sort_enum_spec.rb
+++ b/spec/graphql/types/ci/variable_sort_enum_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Types::Ci::VariableSortEnum, feature_category: :pipeline_authoring do
+RSpec.describe Types::Ci::VariableSortEnum, feature_category: :secrets_management do
it 'exposes the available order methods' do
expect(described_class.values).to match(
'KEY_ASC' => have_attributes(value: :key_asc),
diff --git a/spec/graphql/types/clusters/agent_activity_event_type_spec.rb b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
index cae75485846..f89bd877920 100644
--- a/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_activity_event_type_spec.rb
@@ -6,6 +6,6 @@ RSpec.describe GitlabSchema.types['ClusterAgentActivityEvent'] do
let(:fields) { %i[recorded_at kind level user agent_token] }
it { expect(described_class.graphql_name).to eq('ClusterAgentActivityEvent') }
- it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster_agent) }
it { expect(described_class).to have_graphql_fields(fields) }
end
diff --git a/spec/graphql/types/clusters/agent_token_type_spec.rb b/spec/graphql/types/clusters/agent_token_type_spec.rb
index 1ca6d690c80..e04b33f92f8 100644
--- a/spec/graphql/types/clusters/agent_token_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_token_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ClusterAgentToken'] do
it { expect(described_class.graphql_name).to eq('ClusterAgentToken') }
- it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster_agent) }
it { expect(described_class).to have_graphql_fields(fields) }
end
diff --git a/spec/graphql/types/clusters/agent_type_spec.rb b/spec/graphql/types/clusters/agent_type_spec.rb
index bb1006c55c0..4bae0ea5602 100644
--- a/spec/graphql/types/clusters/agent_type_spec.rb
+++ b/spec/graphql/types/clusters/agent_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ClusterAgent'] do
it { expect(described_class.graphql_name).to eq('ClusterAgent') }
- it { expect(described_class).to require_graphql_authorizations(:read_cluster) }
+ it { expect(described_class).to require_graphql_authorizations(:read_cluster_agent) }
it { expect(described_class).to include_graphql_fields(*fields) }
end
diff --git a/spec/graphql/types/clusters/agents/authorizations/ci_access_type_spec.rb b/spec/graphql/types/clusters/agents/authorizations/ci_access_type_spec.rb
new file mode 100644
index 00000000000..17725ec11e0
--- /dev/null
+++ b/spec/graphql/types/clusters/agents/authorizations/ci_access_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ClusterAgentAuthorizationCiAccess'],
+ feature_category: :deployment_management do
+ let(:fields) { %i[agent config] }
+
+ it { expect(described_class.graphql_name).to eq('ClusterAgentAuthorizationCiAccess') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/clusters/agents/authorizations/user_access_type_spec.rb b/spec/graphql/types/clusters/agents/authorizations/user_access_type_spec.rb
new file mode 100644
index 00000000000..0e798cd1b18
--- /dev/null
+++ b/spec/graphql/types/clusters/agents/authorizations/user_access_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ClusterAgentAuthorizationUserAccess'],
+ feature_category: :deployment_management do
+ let(:fields) { %i[agent config] }
+
+ it { expect(described_class.graphql_name).to eq('ClusterAgentAuthorizationUserAccess') }
+ it { expect(described_class).to have_graphql_fields(fields) }
+end
diff --git a/spec/graphql/types/commit_signature_interface_spec.rb b/spec/graphql/types/commit_signature_interface_spec.rb
index 4962131d9b5..d37c0d1b4fa 100644
--- a/spec/graphql/types/commit_signature_interface_spec.rb
+++ b/spec/graphql/types/commit_signature_interface_spec.rb
@@ -18,6 +18,11 @@ RSpec.describe GitlabSchema.types['CommitSignature'] do
Types::CommitSignatures::X509SignatureType)
end
+ it 'resolves SSH signatures' do
+ expect(described_class.resolve_type(build(:ssh_signature), {})).to eq(
+ Types::CommitSignatures::SshSignatureType)
+ end
+
it 'raises an error when type is not known' do
expect { described_class.resolve_type(Class, {}) }.to raise_error('Unsupported commit signature type')
end
diff --git a/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb b/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
index 4ffb70a0b22..c16e29312a3 100644
--- a/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
+++ b/spec/graphql/types/commit_signatures/ssh_signature_type_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe GitlabSchema.types['SshSignature'], feature_category: :source_cod
it 'contains attributes related to SSH signatures' do
expect(described_class).to have_graphql_fields(
- :user, :verification_status, :commit_sha, :project, :key
+ :user, :verification_status, :commit_sha, :project, :key, :key_fingerprint_sha256
)
end
end
diff --git a/spec/graphql/types/data_transfer/project_data_transfer_type_spec.rb b/spec/graphql/types/data_transfer/project_data_transfer_type_spec.rb
new file mode 100644
index 00000000000..a93da279b7f
--- /dev/null
+++ b/spec/graphql/types/data_transfer/project_data_transfer_type_spec.rb
@@ -0,0 +1,38 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ProjectDataTransfer'], feature_category: :source_code_management do
+ include GraphqlHelpers
+
+ it 'includes the specific fields' do
+ expect(described_class).to have_graphql_fields(
+ :total_egress, :egress_nodes)
+ end
+
+ describe '#total_egress' do
+ let_it_be(:project) { create(:project) }
+ let(:from) { Date.new(2022, 1, 1) }
+ let(:to) { Date.new(2023, 1, 1) }
+ let(:finder_result) { 40_000_000 }
+
+ it 'returns mock data' do
+ expect(resolve_field(:total_egress, { from: from, to: to }, extras: { parent: project },
+ arg_style: :internal)).to eq(finder_result)
+ end
+
+ context 'when data_transfer_monitoring_mock_data is disabled' do
+ let(:relation) { instance_double(ActiveRecord::Relation) }
+
+ before do
+ allow(relation).to receive(:sum).and_return(10)
+ stub_feature_flags(data_transfer_monitoring_mock_data: false)
+ end
+
+ it 'calls sum on active record relation' do
+ expect(resolve_field(:total_egress, { egress_nodes: relation }, extras: { parent: project },
+ arg_style: :internal)).to eq(10)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/design_management/design_at_version_type_spec.rb b/spec/graphql/types/design_management/design_at_version_type_spec.rb
index 4d61ecf62cc..06aefb6fea3 100644
--- a/spec/graphql/types/design_management/design_at_version_type_spec.rb
+++ b/spec/graphql/types/design_management/design_at_version_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['DesignAtVersion'] do
+RSpec.describe GitlabSchema.types['DesignAtVersion'], feature_category: :portfolio_management do
it_behaves_like 'a GraphQL type with design fields' do
let(:extra_design_fields) { %i[version design] }
let_it_be(:design) { create(:design, :with_versions) }
diff --git a/spec/graphql/types/design_management/design_type_spec.rb b/spec/graphql/types/design_management/design_type_spec.rb
index 24b007a6b33..a093f785eb7 100644
--- a/spec/graphql/types/design_management/design_type_spec.rb
+++ b/spec/graphql/types/design_management/design_type_spec.rb
@@ -2,13 +2,16 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['Design'] do
+RSpec.describe GitlabSchema.types['Design'], feature_category: :portfolio_management do
specify { expect(described_class.interfaces).to include(Types::CurrentUserTodos) }
specify { expect(described_class.interfaces).to include(Types::TodoableInterface) }
it_behaves_like 'a GraphQL type with design fields' do
- let(:extra_design_fields) { %i[notes current_user_todos discussions versions web_url commenters] }
+ let(:extra_design_fields) do
+ %i[notes current_user_todos discussions versions web_url commenters description descriptionHtml]
+ end
+
let_it_be(:design) { create(:design, :with_versions) }
let(:object_id) { GitlabSchema.id_from_object(design) }
let_it_be(:object_id_b) { GitlabSchema.id_from_object(create(:design, :with_versions)) }
diff --git a/spec/graphql/types/group_type_spec.rb b/spec/graphql/types/group_type_spec.rb
index 6820cf2738e..0fbf50fe258 100644
--- a/spec/graphql/types/group_type_spec.rb
+++ b/spec/graphql/types/group_type_spec.rb
@@ -22,7 +22,7 @@ RSpec.describe GitlabSchema.types['Group'] do
merge_requests container_repositories container_repositories_count
packages dependency_proxy_setting dependency_proxy_manifests
dependency_proxy_blobs dependency_proxy_image_count
- dependency_proxy_blob_count dependency_proxy_total_size
+ dependency_proxy_blob_count dependency_proxy_total_size dependency_proxy_total_size_in_bytes
dependency_proxy_image_prefix dependency_proxy_image_ttl_policy
shared_runners_setting timelogs organization_state_counts organizations
contact_state_counts contacts work_item_types
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index 7c6cf137a1e..a9fe85ac62f 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -265,7 +265,10 @@ RSpec.describe GitlabSchema.types['Issue'] do
context 'for an incident' do
before do
- issue.update!(issue_type: Issue.issue_types[:incident])
+ issue.update!(
+ issue_type: WorkItems::Type.base_types[:incident],
+ work_item_type: WorkItems::Type.default_by_type(:incident)
+ )
end
it { is_expected.to be_nil }
@@ -277,44 +280,4 @@ RSpec.describe GitlabSchema.types['Issue'] do
end
end
end
-
- describe 'type' do
- let_it_be(:issue) { create(:issue, project: project) }
-
- let(:query) do
- %(
- query {
- issue(id: "#{issue.to_gid}") {
- type
- }
- }
- )
- end
-
- subject(:execute) { GitlabSchema.execute(query, context: { current_user: user }).as_json }
-
- context 'when the issue_type_uses_work_item_types_table feature flag is enabled' do
- it 'gets the type field from the work_item_types table' do
- expect_next_instance_of(::IssuePresenter) do |presented_issue|
- expect(presented_issue).to receive_message_chain(:work_item_type, :base_type)
- end
-
- execute
- end
- end
-
- context 'when the issue_type_uses_work_item_types_table feature flag is disabled' do
- before do
- stub_feature_flags(issue_type_uses_work_item_types_table: false)
- end
-
- it 'does not get the type field from the work_item_types table' do
- expect_next_instance_of(::IssuePresenter) do |presented_issue|
- expect(presented_issue).not_to receive(:work_item_type)
- end
-
- execute
- end
- end
- end
end
diff --git a/spec/graphql/types/key_type_spec.rb b/spec/graphql/types/key_type_spec.rb
index 78144076467..13c00d94b37 100644
--- a/spec/graphql/types/key_type_spec.rb
+++ b/spec/graphql/types/key_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['Key'], feature_category: :authentication_and_authorization do
+RSpec.describe GitlabSchema.types['Key'], feature_category: :system_access do
specify { expect(described_class.graphql_name).to eq('Key') }
it 'contains attributes for SSH keys' do
diff --git a/spec/graphql/types/merge_request_type_spec.rb b/spec/graphql/types/merge_request_type_spec.rb
index 8a4c89fc340..bd271da55a9 100644
--- a/spec/graphql/types/merge_request_type_spec.rb
+++ b/spec/graphql/types/merge_request_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['MergeRequest'] do
+RSpec.describe GitlabSchema.types['MergeRequest'], feature_category: :code_review_workflow do
include GraphqlHelpers
specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::MergeRequest) }
@@ -36,7 +36,7 @@ RSpec.describe GitlabSchema.types['MergeRequest'] do
commit_count current_user_todos conflicts auto_merge_enabled approved_by source_branch_protected
squash_on_merge available_auto_merge_strategies
has_ci mergeable commits committers commits_without_merge_commits squash security_auto_fix default_squash_commit_message
- auto_merge_strategy merge_user
+ auto_merge_strategy merge_user award_emoji prepared_at
]
expect(described_class).to have_graphql_fields(*expected_fields).at_least
diff --git a/spec/graphql/types/permission_types/issue_spec.rb b/spec/graphql/types/permission_types/issue_spec.rb
index 58c5808cbcc..8f43a4a44a0 100644
--- a/spec/graphql/types/permission_types/issue_spec.rb
+++ b/spec/graphql/types/permission_types/issue_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Types::PermissionTypes::Issue do
expected_permissions = [
:read_issue, :admin_issue, :update_issue, :reopen_issue,
:read_design, :create_design, :destroy_design,
- :create_note
+ :create_note, :update_design
]
expected_permissions.each do |permission|
diff --git a/spec/graphql/types/permission_types/work_item_spec.rb b/spec/graphql/types/permission_types/work_item_spec.rb
index db6d78b1538..7e16b43a12f 100644
--- a/spec/graphql/types/permission_types/work_item_spec.rb
+++ b/spec/graphql/types/permission_types/work_item_spec.rb
@@ -5,7 +5,8 @@ require 'spec_helper'
RSpec.describe Types::PermissionTypes::WorkItem do
it do
expected_permissions = [
- :read_work_item, :update_work_item, :delete_work_item, :admin_work_item
+ :read_work_item, :update_work_item, :delete_work_item, :admin_work_item,
+ :admin_parent_link, :set_work_item_metadata
]
expected_permissions.each do |permission|
diff --git a/spec/graphql/types/project_member_relation_enum_spec.rb b/spec/graphql/types/project_member_relation_enum_spec.rb
index 3c947bf8406..a486844a687 100644
--- a/spec/graphql/types/project_member_relation_enum_spec.rb
+++ b/spec/graphql/types/project_member_relation_enum_spec.rb
@@ -6,6 +6,7 @@ RSpec.describe Types::ProjectMemberRelationEnum do
specify { expect(described_class.graphql_name).to eq('ProjectMemberRelation') }
it 'exposes all the existing project member relation type values' do
- expect(described_class.values.keys).to contain_exactly('DIRECT', 'INHERITED', 'DESCENDANTS', 'INVITED_GROUPS')
+ relation_types = %w[DIRECT INHERITED DESCENDANTS INVITED_GROUPS SHARED_INTO_ANCESTORS]
+ expect(described_class.values.keys).to contain_exactly(*relation_types)
end
end
diff --git a/spec/graphql/types/project_statistics_redirect_type_spec.rb b/spec/graphql/types/project_statistics_redirect_type_spec.rb
new file mode 100644
index 00000000000..3600a5b932f
--- /dev/null
+++ b/spec/graphql/types/project_statistics_redirect_type_spec.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['ProjectStatisticsRedirect'], feature_category: :consumables_cost_management do
+ it 'has all the required fields' do
+ expect(described_class).to have_graphql_fields(:repository, :build_artifacts, :packages,
+ :wiki, :snippets, :container_registry)
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index 7f26190830e..bcfdb05ca90 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe GitlabSchema.types['Project'] do
snippets_enabled jobs_enabled public_jobs open_issues_count import_status
only_allow_merge_if_pipeline_succeeds request_access_enabled
only_allow_merge_if_all_discussions_are_resolved printing_merge_request_link_enabled
- namespace group statistics repository merge_requests merge_request issues
+ namespace group statistics statistics_details_paths repository merge_requests merge_request issues
issue milestones pipelines removeSourceBranchAfterMerge pipeline_counts sentryDetailedError snippets
grafanaIntegration autocloseReferencedIssues suggestion_commit_message environments
environment boards jira_import_status jira_imports services releases release
@@ -34,11 +34,11 @@ RSpec.describe GitlabSchema.types['Project'] do
issue_status_counts terraform_states alert_management_integrations
container_repositories container_repositories_count
pipeline_analytics squash_read_only sast_ci_configuration
- cluster_agent cluster_agents agent_configurations
+ cluster_agent cluster_agents agent_configurations ci_access_authorized_agents user_access_authorized_agents
ci_template timelogs merge_commit_template squash_commit_template work_item_types
recent_issue_boards ci_config_path_or_default packages_cleanup_policy ci_variables
timelog_categories fork_targets branch_rules ci_config_variables pipeline_schedules languages
- incident_management_timeline_event_tags visible_forks
+ incident_management_timeline_event_tags visible_forks inherited_ci_variables
]
expect(described_class).to include_graphql_fields(*expected_fields)
@@ -291,7 +291,7 @@ RSpec.describe GitlabSchema.types['Project'] do
let_it_be(:project) { create(:project_empty_repo) }
it 'raises an error' do
- expect(subject['errors'][0]['message']).to eq('You must <a target="_blank" rel="noopener noreferrer" ' \
+ expect(subject['errors'][0]['message']).to eq('UF You must <a target="_blank" rel="noopener noreferrer" ' \
'href="http://localhost/help/user/project/repository/index.md#' \
'add-files-to-a-repository">add at least one file to the ' \
'repository</a> before using Security features.')
@@ -333,6 +333,7 @@ RSpec.describe GitlabSchema.types['Project'] do
:target_branches,
:state,
:draft,
+ :approved,
:labels,
:before,
:after,
@@ -676,8 +677,8 @@ RSpec.describe GitlabSchema.types['Project'] do
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
- allow(::Gitlab::ServiceDeskEmail).to receive(:enabled?) { true }
- allow(::Gitlab::ServiceDeskEmail).to receive(:address_for_key) { 'address-suffix@example.com' }
+ allow(::Gitlab::Email::ServiceDeskEmail).to receive(:enabled?) { true }
+ allow(::Gitlab::Email::ServiceDeskEmail).to receive(:address_for_key) { 'address-suffix@example.com' }
end
context 'when a user can admin issues' do
diff --git a/spec/graphql/types/projects/fork_details_type_spec.rb b/spec/graphql/types/projects/fork_details_type_spec.rb
index 8e20e2c8299..f79371ce4ca 100644
--- a/spec/graphql/types/projects/fork_details_type_spec.rb
+++ b/spec/graphql/types/projects/fork_details_type_spec.rb
@@ -9,6 +9,8 @@ RSpec.describe GitlabSchema.types['ForkDetails'], feature_category: :source_code
fields = %i[
ahead
behind
+ isSyncing
+ hasConflicts
]
expect(described_class).to have_graphql_fields(*fields)
diff --git a/spec/graphql/types/release_asset_link_type_spec.rb b/spec/graphql/types/release_asset_link_type_spec.rb
index 0c903b8d27a..57a42a3966f 100644
--- a/spec/graphql/types/release_asset_link_type_spec.rb
+++ b/spec/graphql/types/release_asset_link_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['ReleaseAssetLink'] do
it 'has the expected fields' do
expected_fields = %w[
- id name url external link_type direct_asset_url direct_asset_path
+ id name url link_type direct_asset_url direct_asset_path
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/root_storage_statistics_type_spec.rb b/spec/graphql/types/root_storage_statistics_type_spec.rb
index 07c8378e7a6..5dde6aa8b14 100644
--- a/spec/graphql/types/root_storage_statistics_type_spec.rb
+++ b/spec/graphql/types/root_storage_statistics_type_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['RootStorageStatistics'] do
expect(described_class).to have_graphql_fields(:storage_size, :repository_size, :lfs_objects_size,
:build_artifacts_size, :packages_size, :wiki_size, :snippets_size,
:pipeline_artifacts_size, :uploads_size, :dependency_proxy_size,
- :container_registry_size)
+ :container_registry_size, :registry_size_estimated)
end
specify { expect(described_class).to require_graphql_authorizations(:read_statistics) }
diff --git a/spec/graphql/types/time_tracking/timelog_connection_type_spec.rb b/spec/graphql/types/time_tracking/timelog_connection_type_spec.rb
index 5cfe561b42c..db1ffd4f59d 100644
--- a/spec/graphql/types/time_tracking/timelog_connection_type_spec.rb
+++ b/spec/graphql/types/time_tracking/timelog_connection_type_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe GitlabSchema.types['TimelogConnection'], feature_category: :team_
context 'when requested' do
it 'returns the total spent time' do
- expect(total_spent_time).to eq(5064)
+ expect(total_spent_time).to eq('5064')
end
end
end
diff --git a/spec/graphql/types/timelog_type_spec.rb b/spec/graphql/types/timelog_type_spec.rb
index 59a0e373c5d..aa05c5ffd94 100644
--- a/spec/graphql/types/timelog_type_spec.rb
+++ b/spec/graphql/types/timelog_type_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe GitlabSchema.types['Timelog'], feature_category: :team_planning do
- let_it_be(:fields) { %i[id spent_at time_spent user issue merge_request note summary userPermissions] }
+ let_it_be(:fields) { %i[id spent_at time_spent user issue merge_request note summary userPermissions project] }
it { expect(described_class.graphql_name).to eq('Timelog') }
it { expect(described_class).to have_graphql_fields(fields) }
diff --git a/spec/graphql/types/user_preferences_type_spec.rb b/spec/graphql/types/user_preferences_type_spec.rb
index fac45443290..06749dda239 100644
--- a/spec/graphql/types/user_preferences_type_spec.rb
+++ b/spec/graphql/types/user_preferences_type_spec.rb
@@ -2,12 +2,13 @@
require 'spec_helper'
-RSpec.describe Types::UserPreferencesType do
+RSpec.describe Types::UserPreferencesType, feature_category: :user_profile do
specify { expect(described_class.graphql_name).to eq('UserPreferences') }
it 'exposes the expected fields' do
expected_fields = %i[
issues_sort
+ visibility_pipeline_id_type
]
expect(described_class).to have_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index a6b5d454b60..0b0dcf2fb6a 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -47,9 +47,10 @@ RSpec.describe GitlabSchema.types['User'], feature_category: :user_profile do
profileEnableGitpodPath
savedReplies
savedReply
+ user_achievements
]
- expect(described_class).to have_graphql_fields(*expected_fields)
+ expect(described_class).to include_graphql_fields(*expected_fields)
end
describe 'name field' do
diff --git a/spec/graphql/types/visibility_pipeline_id_type_enum_spec.rb b/spec/graphql/types/visibility_pipeline_id_type_enum_spec.rb
new file mode 100644
index 00000000000..f1dc6a79b29
--- /dev/null
+++ b/spec/graphql/types/visibility_pipeline_id_type_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::VisibilityPipelineIdTypeEnum, feature_category: :user_profile do
+ specify { expect(described_class.graphql_name).to eq('VisibilityPipelineIdType') }
+
+ it 'exposes all visibility pipeline id types' do
+ expect(described_class.values.keys).to contain_exactly(
+ *UserPreference.visibility_pipeline_id_types.keys.map(&:upcase)
+ )
+ end
+end
diff --git a/spec/graphql/types/work_item_type_spec.rb b/spec/graphql/types/work_item_type_spec.rb
index 42d56598944..328450084c2 100644
--- a/spec/graphql/types/work_item_type_spec.rb
+++ b/spec/graphql/types/work_item_type_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe GitlabSchema.types['WorkItem'] do
+RSpec.describe GitlabSchema.types['WorkItem'], feature_category: :team_planning do
specify { expect(described_class.graphql_name).to eq('WorkItem') }
specify { expect(described_class).to require_graphql_authorizations(:read_work_item) }
@@ -18,6 +18,7 @@ RSpec.describe GitlabSchema.types['WorkItem'] do
id
iid
lock_version
+ namespace
project
state title
title_html
@@ -28,6 +29,8 @@ RSpec.describe GitlabSchema.types['WorkItem'] do
updated_at
closed_at
web_url
+ create_note_email
+ reference
]
expect(described_class).to have_graphql_fields(*fields)
diff --git a/spec/graphql/types/work_items/available_export_fields_enum_spec.rb b/spec/graphql/types/work_items/available_export_fields_enum_spec.rb
new file mode 100644
index 00000000000..9010aabe3cc
--- /dev/null
+++ b/spec/graphql/types/work_items/available_export_fields_enum_spec.rb
@@ -0,0 +1,27 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['AvailableExportFields'], feature_category: :team_planning do
+ specify { expect(described_class.graphql_name).to eq('AvailableExportFields') }
+
+ describe 'enum values' do
+ using RSpec::Parameterized::TableSyntax
+
+ where(:field_name, :field_value) do
+ 'ID' | 'id'
+ 'TYPE' | 'type'
+ 'TITLE' | 'title'
+ 'DESCRIPTION' | 'description'
+ 'AUTHOR' | 'author'
+ 'AUTHOR_USERNAME' | 'author username'
+ 'CREATED_AT' | 'created_at'
+ end
+
+ with_them do
+ it 'exposes correct available fields' do
+ expect(described_class.values[field_name].value).to eq(field_value)
+ end
+ end
+ end
+end
diff --git a/spec/graphql/types/work_items/widget_interface_spec.rb b/spec/graphql/types/work_items/widget_interface_spec.rb
index a2b12ed52dc..d955ec5023e 100644
--- a/spec/graphql/types/work_items/widget_interface_spec.rb
+++ b/spec/graphql/types/work_items/widget_interface_spec.rb
@@ -15,11 +15,14 @@ RSpec.describe Types::WorkItems::WidgetInterface do
using RSpec::Parameterized::TableSyntax
where(:widget_class, :widget_type_name) do
- WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType
- WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType
- WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType
- WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType
- WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType
+ WorkItems::Widgets::Description | Types::WorkItems::Widgets::DescriptionType
+ WorkItems::Widgets::Hierarchy | Types::WorkItems::Widgets::HierarchyType
+ WorkItems::Widgets::Assignees | Types::WorkItems::Widgets::AssigneesType
+ WorkItems::Widgets::Labels | Types::WorkItems::Widgets::LabelsType
+ WorkItems::Widgets::Notes | Types::WorkItems::Widgets::NotesType
+ WorkItems::Widgets::Notifications | Types::WorkItems::Widgets::NotificationsType
+ WorkItems::Widgets::CurrentUserTodos | Types::WorkItems::Widgets::CurrentUserTodosType
+ WorkItems::Widgets::AwardEmoji | Types::WorkItems::Widgets::AwardEmojiType
end
with_them do
diff --git a/spec/graphql/types/work_items/widgets/award_emoji_type_spec.rb b/spec/graphql/types/work_items/widgets/award_emoji_type_spec.rb
new file mode 100644
index 00000000000..493e628ac83
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/award_emoji_type_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::AwardEmojiType, feature_category: :team_planning do
+ it 'exposes the expected fields' do
+ expected_fields = %i[award_emoji downvotes upvotes type]
+
+ expect(described_class.graphql_name).to eq('WorkItemWidgetAwardEmoji')
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/current_user_todos_input_type_spec.rb b/spec/graphql/types/work_items/widgets/current_user_todos_input_type_spec.rb
new file mode 100644
index 00000000000..0ae660ffac0
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/current_user_todos_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::WorkItems::Widgets::CurrentUserTodosInputType, feature_category: :team_planning do
+ it { expect(described_class.graphql_name).to eq('WorkItemWidgetCurrentUserTodosInput') }
+
+ it { expect(described_class.arguments.keys).to match_array(%w[action todoId]) }
+end
diff --git a/spec/graphql/types/work_items/widgets/current_user_todos_type_spec.rb b/spec/graphql/types/work_items/widgets/current_user_todos_type_spec.rb
new file mode 100644
index 00000000000..b39adefbd87
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/current_user_todos_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::CurrentUserTodosType, feature_category: :team_planning do
+ it 'exposes the expected fields' do
+ expected_fields = %i[current_user_todos type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/hierarchy_update_input_type_spec.rb b/spec/graphql/types/work_items/widgets/hierarchy_update_input_type_spec.rb
index 6221580605e..0d4d31faee1 100644
--- a/spec/graphql/types/work_items/widgets/hierarchy_update_input_type_spec.rb
+++ b/spec/graphql/types/work_items/widgets/hierarchy_update_input_type_spec.rb
@@ -5,5 +5,11 @@ require 'spec_helper'
RSpec.describe ::Types::WorkItems::Widgets::HierarchyUpdateInputType do
it { expect(described_class.graphql_name).to eq('WorkItemWidgetHierarchyUpdateInput') }
- it { expect(described_class.arguments.keys).to match_array(%w[parentId childrenIds]) }
+ it 'accepts documented arguments' do
+ expect(described_class.arguments.keys).to match_array(%w[parentId childrenIds adjacentWorkItemId relativePosition])
+ end
+
+ it 'sets the type of relative_position argument to RelativePositionTypeEnum' do
+ expect(described_class.arguments['relativePosition'].type).to eq(Types::RelativePositionTypeEnum)
+ end
end
diff --git a/spec/graphql/types/work_items/widgets/notifications_type_spec.rb b/spec/graphql/types/work_items/widgets/notifications_type_spec.rb
new file mode 100644
index 00000000000..4f457a24710
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/notifications_type_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::NotificationsType, feature_category: :team_planning do
+ it 'exposes the expected fields' do
+ expected_fields = %i[subscribed type]
+
+ expect(described_class.graphql_name).to eq('WorkItemWidgetNotifications')
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/notifications_update_input_type_spec.rb b/spec/graphql/types/work_items/widgets/notifications_update_input_type_spec.rb
new file mode 100644
index 00000000000..db0d02c597c
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/notifications_update_input_type_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe ::Types::WorkItems::Widgets::NotificationsUpdateInputType, feature_category: :team_planning do
+ it { expect(described_class.graphql_name).to eq('WorkItemWidgetNotificationsUpdateInput') }
+
+ it { expect(described_class.arguments.keys).to contain_exactly('subscribed') }
+end