summaryrefslogtreecommitdiff
path: root/spec/graphql
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-06-20 11:10:13 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2022-06-20 11:10:13 +0000
commit0ea3fcec397b69815975647f5e2aa5fe944a8486 (patch)
tree7979381b89d26011bcf9bdc989a40fcc2f1ed4ff /spec/graphql
parent72123183a20411a36d607d70b12d57c484394c8e (diff)
downloadgitlab-ce-0ea3fcec397b69815975647f5e2aa5fe944a8486.tar.gz
Add latest changes from gitlab-org/gitlab@15-1-stable-eev15.1.0-rc42
Diffstat (limited to 'spec/graphql')
-rw-r--r--spec/graphql/features/authorization_spec.rb76
-rw-r--r--spec/graphql/gitlab_schema_spec.rb11
-rw-r--r--spec/graphql/mutations/boards/issues/issue_move_list_spec.rb4
-rw-r--r--spec/graphql/mutations/branches/create_spec.rb7
-rw-r--r--spec/graphql/mutations/ci/runner/update_spec.rb14
-rw-r--r--spec/graphql/mutations/clusters/agent_tokens/create_spec.rb4
-rw-r--r--spec/graphql/mutations/clusters/agents/create_spec.rb4
-rw-r--r--spec/graphql/mutations/clusters/agents/delete_spec.rb4
-rw-r--r--spec/graphql/mutations/commits/create_spec.rb4
-rw-r--r--spec/graphql/mutations/customer_relations/contacts/create_spec.rb11
-rw-r--r--spec/graphql/mutations/customer_relations/contacts/update_spec.rb11
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/create_spec.rb11
-rw-r--r--spec/graphql/mutations/customer_relations/organizations/update_spec.rb11
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/create_spec.rb3
-rw-r--r--spec/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb3
-rw-r--r--spec/graphql/mutations/issues/set_escalation_status_spec.rb10
-rw-r--r--spec/graphql/mutations/release_asset_links/create_spec.rb2
-rw-r--r--spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb4
-rw-r--r--spec/graphql/mutations/terraform/state/delete_spec.rb10
-rw-r--r--spec/graphql/mutations/work_items/update_task_spec.rb40
-rw-r--r--spec/graphql/mutations/work_items/update_widgets_spec.rb58
-rw-r--r--spec/graphql/resolvers/alert_management/alert_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/board_list_issues_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/board_lists_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/ci/group_runners_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/ci/jobs_resolver_spec.rb7
-rw-r--r--spec/graphql/resolvers/ci/runners_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/concerns/resolves_groups_spec.rb2
-rw-r--r--spec/graphql/resolvers/container_repositories_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/container_repository_tags_resolver_spec.rb5
-rw-r--r--spec/graphql/resolvers/crm/contacts_resolver_spec.rb92
-rw-r--r--spec/graphql/resolvers/crm/organizations_resolver_spec.rb88
-rw-r--r--spec/graphql/resolvers/design_management/versions_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/group_labels_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/group_milestones_resolver_spec.rb12
-rw-r--r--spec/graphql/resolvers/group_packages_resolver_spec.rb9
-rw-r--r--spec/graphql/resolvers/incident_management/timeline_events_resolver_spec.rb3
-rw-r--r--spec/graphql/resolvers/issue_status_counts_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/issues_resolver_spec.rb34
-rw-r--r--spec/graphql/resolvers/merge_requests_resolver_spec.rb4
-rw-r--r--spec/graphql/resolvers/namespace_projects_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/packages_base_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/project_milestones_resolver_spec.rb58
-rw-r--r--spec/graphql/resolvers/project_packages_resolver_spec.rb10
-rw-r--r--spec/graphql/resolvers/releases_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/user_resolver_spec.rb37
-rw-r--r--spec/graphql/resolvers/users/groups_resolver_spec.rb2
-rw-r--r--spec/graphql/resolvers/users_resolver_spec.rb14
-rw-r--r--spec/graphql/resolvers/work_items_resolver_spec.rb190
-rw-r--r--spec/graphql/subscriptions/issuable_updated_spec.rb3
-rw-r--r--spec/graphql/types/base_edge_spec.rb1
-rw-r--r--spec/graphql/types/base_field_spec.rb86
-rw-r--r--spec/graphql/types/base_object_spec.rb1
-rw-r--r--spec/graphql/types/ci/detailed_status_type_spec.rb6
-rw-r--r--spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb14
-rw-r--r--spec/graphql/types/ci/pipeline_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/runner_type_spec.rb2
-rw-r--r--spec/graphql/types/ci/status_action_type_spec.rb8
-rw-r--r--spec/graphql/types/issue_type_spec.rb10
-rw-r--r--spec/graphql/types/limited_countable_connection_type_spec.rb11
-rw-r--r--spec/graphql/types/packages/cleanup/keep_duplicated_package_files_enum_spec.rb15
-rw-r--r--spec/graphql/types/packages/cleanup/policy_type_spec.rb26
-rw-r--r--spec/graphql/types/project_type_spec.rb36
-rw-r--r--spec/graphql/types/terraform/state_type_spec.rb3
-rw-r--r--spec/graphql/types/time_type_spec.rb5
-rw-r--r--spec/graphql/types/todo_type_spec.rb14
-rw-r--r--spec/graphql/types/user_type_spec.rb8
-rw-r--r--spec/graphql/types/work_item_type_spec.rb13
-rw-r--r--spec/graphql/types/work_items/widget_interface_spec.rb37
-rw-r--r--spec/graphql/types/work_items/widget_type_enum_spec.rb13
-rw-r--r--spec/graphql/types/work_items/widgets/description_type_spec.rb11
-rw-r--r--spec/graphql/types/work_items/widgets/hierarchy_type_spec.rb11
73 files changed, 1006 insertions, 246 deletions
diff --git a/spec/graphql/features/authorization_spec.rb b/spec/graphql/features/authorization_spec.rb
index 514f63a6f5a..4f8ae92ff99 100644
--- a/spec/graphql/features/authorization_spec.rb
+++ b/spec/graphql/features/authorization_spec.rb
@@ -10,17 +10,14 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
let(:permission_single) { :foo }
let(:permission_collection) { [:foo, :bar] }
- let(:test_object) { double(name: 'My name') }
+ let(:test_object) { double(name: 'My name', address: 'Worldwide') }
let(:authorizing_object) { test_object }
# to override when combining permissions
let(:permission_object_one) { authorizing_object }
let(:permission_object_two) { authorizing_object }
let(:query_string) { '{ item { name } }' }
- let(:result) do
- schema = empty_schema
- execute_query(query_type, schema: schema)
- end
+ let(:result) { execute_query(query_type) }
subject { result.dig('data', 'item') }
@@ -103,47 +100,47 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
end
describe 'with a single permission' do
+ let(:query_string) { '{ item { name address } }' }
let(:type) do
type_factory do |type|
- type.field :name, GraphQL::Types::String, null: true, authorize: permission_single
+ type.field :address, GraphQL::Types::String, null: true, authorize: permission_single
end
end
it 'returns the protected field when user has permission' do
permit(permission_single)
- expect(subject).to eq('name' => test_object.name)
+ expect(subject).to include('address' => test_object.address)
end
it 'returns nil when user is not authorized' do
- expect(subject).to eq('name' => nil)
+ expect(subject).to include('address' => nil)
end
end
describe 'with a collection of permissions' do
+ let(:query_string) { '{ item { name address } }' }
let(:type) do
permissions = permission_collection
type_factory do |type|
- type.field :name, GraphQL::Types::String,
- null: true,
- authorize: permissions
+ type.field :address, GraphQL::Types::String, null: true, authorize: permissions
end
end
it 'returns the protected field when user has all permissions' do
permit(*permission_collection)
- expect(subject).to eq('name' => test_object.name)
+ expect(subject).to include('address' => test_object.address)
end
it 'returns nil when user only has one of the permissions' do
permit(permission_collection.first)
- expect(subject).to eq('name' => nil)
+ expect(subject).to include('address' => nil)
end
it 'returns nil when user only has none of the permissions' do
- expect(subject).to eq('name' => nil)
+ expect(subject).to include('address' => nil)
end
end
end
@@ -179,7 +176,7 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
describe 'type and field authorizations together' do
let(:authorizing_object) { anything }
let(:permission_1) { permission_collection.first }
- let(:permission_2) { permission_collection.last }
+ let(:permission_2) { permission_collection.second }
let(:type) do
type_factory do |type|
@@ -224,6 +221,55 @@ RSpec.describe 'DeclarativePolicy authorization in GraphQL ' do
include_examples 'authorization with a collection of permissions'
end
+ context 'when the resolver is a subclass of one that authorizes the object' do
+ let(:permission_object_one) { be_nil }
+ let(:permission_object_two) { be_nil }
+ let(:parent) do
+ parent = Class.new(Resolvers::BaseResolver)
+ parent.include(::Gitlab::Graphql::Authorize::AuthorizeResource)
+ parent.authorizes_object!
+ parent.authorize permission_1
+ parent
+ end
+
+ let(:resolver) do
+ simple_resolver(test_object, base_class: parent)
+ end
+
+ include_examples 'authorization with a collection of permissions'
+ end
+
+ context 'when the resolver is a subclass of one that authorizes the object, extra permission' do
+ let(:permission_object_one) { be_nil }
+ let(:permission_object_two) { be_nil }
+ let(:parent) do
+ parent = Class.new(Resolvers::BaseResolver)
+ parent.include(::Gitlab::Graphql::Authorize::AuthorizeResource)
+ parent.authorizes_object!
+ parent.authorize permission_1
+ parent
+ end
+
+ let(:resolver) do
+ resolver = simple_resolver(test_object, base_class: parent)
+ resolver.include(::Gitlab::Graphql::Authorize::AuthorizeResource)
+ resolver.authorize permission_2
+ resolver
+ end
+
+ context 'when the field does not define any permissions' do
+ let(:query_type) do
+ query_factory do |query|
+ query.field :item, type,
+ null: true,
+ resolver: resolver
+ end
+ end
+
+ include_examples 'authorization with a collection of permissions'
+ end
+ end
+
context 'when the resolver does not authorize the object, but instead calls authorized_find!' do
let(:permission_object_one) { test_object }
let(:permission_object_two) { be_nil }
diff --git a/spec/graphql/gitlab_schema_spec.rb b/spec/graphql/gitlab_schema_spec.rb
index 02c686af688..60b3edfc279 100644
--- a/spec/graphql/gitlab_schema_spec.rb
+++ b/spec/graphql/gitlab_schema_spec.rb
@@ -4,15 +4,16 @@ require 'spec_helper'
RSpec.describe GitlabSchema do
let_it_be(:connections) { GitlabSchema.connections.all_wrappers }
+ let_it_be(:tracers) { described_class.tracers }
let(:user) { build :user }
it 'uses batch loading' do
- expect(field_instrumenters).to include(BatchLoader::GraphQL)
+ expect(tracers).to include(BatchLoader::GraphQL)
end
it 'enables the generic instrumenter' do
- expect(field_instrumenters).to include(instance_of(::Gitlab::Graphql::GenericTracing))
+ expect(tracers).to include(instance_of(::Gitlab::Graphql::GenericTracing))
end
it 'has the base mutation' do
@@ -219,6 +220,8 @@ RSpec.describe GitlabSchema do
badField
veryBadField
alsoNotAGoodField
+ yetAnotherBadField
+ andYetAnother
}
}
GQL
@@ -308,8 +311,4 @@ RSpec.describe GitlabSchema do
end
end
end
-
- def field_instrumenters
- described_class.instrumenters[:field] + described_class.instrumenters[:field_after_built_ins]
- end
end
diff --git a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
index 11c0fa44110..10aed8a1f00 100644
--- a/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
+++ b/spec/graphql/mutations/boards/issues/issue_move_list_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
let_it_be(:existing_issue2) { create(:labeled_issue, project: project, labels: [testing], relative_position: 50) }
let(:current_ctx) { { current_user: user } }
- let(:params) { { board_id: global_id_of(board), project_path: project.full_path, iid: issue1.iid } }
+ let(:params) { { board_id: global_id_of(board), project_path: project.full_path, iid: issue1.iid.to_s } }
let(:move_params) do
{
from_list_id: list1.id,
@@ -67,7 +67,7 @@ RSpec.describe Mutations::Boards::Issues::IssueMoveList do
end
it 'raises an error' do
- expect { subject }.to raise_error(::GraphQL::LoadApplicationObjectFailedError)
+ expect { subject }.to raise_error(::GraphQL::CoercionError, "\"#{params[:board_id]}\" does not represent an instance of Board")
end
end
diff --git a/spec/graphql/mutations/branches/create_spec.rb b/spec/graphql/mutations/branches/create_spec.rb
index e378a8e3d41..5e9b914d87c 100644
--- a/spec/graphql/mutations/branches/create_spec.rb
+++ b/spec/graphql/mutations/branches/create_spec.rb
@@ -3,13 +3,16 @@
require 'spec_helper'
RSpec.describe Mutations::Branches::Create do
+ include GraphqlHelpers
+
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let_it_be(:project) { create(:project, :public, :repository) }
let_it_be(:user) { create(:user) }
- let_it_be(:context) do
+
+ let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: query_double(schema: nil),
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/ci/runner/update_spec.rb b/spec/graphql/mutations/ci/runner/update_spec.rb
index 75e9b57e60a..ffaa6e93d1b 100644
--- a/spec/graphql/mutations/ci/runner/update_spec.rb
+++ b/spec/graphql/mutations/ci/runner/update_spec.rb
@@ -2,11 +2,12 @@
require 'spec_helper'
-RSpec.describe Mutations::Ci::Runner::Update do
+RSpec.describe 'Mutations::Ci::Runner::Update' do
include GraphqlHelpers
let_it_be(:user) { create(:user) }
let_it_be(:runner) { create(:ci_runner, active: true, locked: false, run_untagged: true) }
+ let_it_be(:described_class) { Mutations::Ci::Runner::Update }
let(:current_ctx) { { current_user: user } }
let(:mutated_runner) { subject[:runner] }
@@ -49,6 +50,7 @@ RSpec.describe Mutations::Ci::Runner::Update do
{
id: runner.to_global_id,
description: 'updated description',
+ maintenance_note: 'updated maintenance note',
maximum_timeout: 900,
access_level: 'ref_protected',
active: false,
@@ -84,6 +86,16 @@ RSpec.describe Mutations::Ci::Runner::Update do
)
end
end
+
+ context 'with too long maintenance note' do
+ it 'returns a descriptive error' do
+ mutation_params[:maintenance_note] = '1' * 1025
+
+ expect(subject[:errors]).to contain_exactly(
+ 'Maintenance note is too long (maximum is 1024 characters)'
+ )
+ end
+ end
end
end
end
diff --git a/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb b/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
index 45d421509d0..7998be19c20 100644
--- a/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
+++ b/spec/graphql/mutations/clusters/agent_tokens/create_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Mutations::Clusters::AgentTokens::Create do
+ include GraphqlHelpers
+
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let_it_be(:cluster_agent) { create(:cluster_agent) }
@@ -10,7 +12,7 @@ RSpec.describe Mutations::Clusters::AgentTokens::Create do
let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: query_double(schema: nil), # rubocop:disable RSpec/VerifiedDoubles
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/clusters/agents/create_spec.rb b/spec/graphql/mutations/clusters/agents/create_spec.rb
index c80b6f6cdad..e2c04254ed8 100644
--- a/spec/graphql/mutations/clusters/agents/create_spec.rb
+++ b/spec/graphql/mutations/clusters/agents/create_spec.rb
@@ -3,13 +3,15 @@
require 'spec_helper'
RSpec.describe Mutations::Clusters::Agents::Create do
+ include GraphqlHelpers
+
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let(:project) { create(:project, :public, :repository) }
let(:user) { create(:user) }
let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: query_double(schema: nil), # rubocop:disable RSpec/VerifiedDoubles
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/clusters/agents/delete_spec.rb b/spec/graphql/mutations/clusters/agents/delete_spec.rb
index e0ecff5fe44..c3a2c0dcbb4 100644
--- a/spec/graphql/mutations/clusters/agents/delete_spec.rb
+++ b/spec/graphql/mutations/clusters/agents/delete_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Mutations::Clusters::Agents::Delete do
+ include GraphqlHelpers
+
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let(:cluster_agent) { create(:cluster_agent) }
@@ -10,7 +12,7 @@ RSpec.describe Mutations::Clusters::Agents::Delete do
let(:user) { create(:user) }
let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: query_double(schema: nil), # rubocop:disable RSpec/VerifiedDoubles
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/commits/create_spec.rb b/spec/graphql/mutations/commits/create_spec.rb
index 097e70bada6..9fc9c731b96 100644
--- a/spec/graphql/mutations/commits/create_spec.rb
+++ b/spec/graphql/mutations/commits/create_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Mutations::Commits::Create do
+ include GraphqlHelpers
+
subject(:mutation) { described_class.new(object: nil, context: context, field: nil) }
let_it_be(:user) { create(:user) }
@@ -10,7 +12,7 @@ RSpec.describe Mutations::Commits::Create do
let(:context) do
GraphQL::Query::Context.new(
- query: OpenStruct.new(schema: nil),
+ query: query_double(schema: nil), # rubocop:disable RSpec/VerifiedDoubles
values: { current_user: user },
object: nil
)
diff --git a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
index dafc7b4c367..f2bbf0949fb 100644
--- a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb
@@ -40,17 +40,6 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do
group.add_developer(user)
end
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(customer_relations: false)
- end
-
- it 'raises an error' do
- expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
- end
- end
-
context 'when crm_enabled is false' do
let(:group) { create(:group) }
diff --git a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
index c8206eca442..421bb4f1b06 100644
--- a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
+++ b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb
@@ -57,17 +57,6 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Update do
it 'updates the organization with correct values' do
expect(resolve_mutation[:contact]).to have_attributes(attributes)
end
-
- context 'when the feature is disabled' do
- before do
- stub_feature_flags(customer_relations: false)
- end
-
- it 'raises an error' do
- expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
- end
- end
end
end
diff --git a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
index ee78d2b16f6..ffc9632350a 100644
--- a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb
@@ -39,17 +39,6 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Create do
group.add_developer(user)
end
- context 'when the feature is disabled' do
- before do
- stub_feature_flags(customer_relations: false)
- end
-
- it 'raises an error' do
- expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
- end
- end
-
context 'when the params are invalid' do
before do
valid_params[:name] = nil
diff --git a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
index 90fd7a0a9f1..f0f37ee9c47 100644
--- a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
+++ b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb
@@ -56,17 +56,6 @@ RSpec.describe Mutations::CustomerRelations::Organizations::Update do
expect(resolve_mutation[:organization]).to have_attributes(attributes)
end
- context 'when the feature flag is disabled' do
- before do
- stub_feature_flags(customer_relations: false)
- end
-
- it 'raises an error' do
- expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
- .with_message("The resource that you are attempting to access does not exist or you don't have permission to perform this action")
- end
- end
-
context 'when the feature is disabled' do
let_it_be(:group) { create(:group) }
diff --git a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
index 63faecad5d5..ea74e427dd6 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/create_spec.rb
@@ -22,7 +22,8 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::Create do
occurred_at: args[:occurred_at].to_s,
incident: incident,
author: current_user,
- promoted_from_note: nil
+ promoted_from_note: nil,
+ editable: true
)
end
diff --git a/spec/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb b/spec/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
index 598ee496cf1..4541f8af7d3 100644
--- a/spec/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
+++ b/spec/graphql/mutations/incident_management/timeline_event/promote_from_note_spec.rb
@@ -27,7 +27,8 @@ RSpec.describe Mutations::IncidentManagement::TimelineEvent::PromoteFromNote do
occurred_at: comment.created_at.to_s,
incident: incident,
author: current_user,
- promoted_from_note: comment
+ promoted_from_note: comment,
+ editable: true
)
end
diff --git a/spec/graphql/mutations/issues/set_escalation_status_spec.rb b/spec/graphql/mutations/issues/set_escalation_status_spec.rb
index d41118b1812..f04d396efb8 100644
--- a/spec/graphql/mutations/issues/set_escalation_status_spec.rb
+++ b/spec/graphql/mutations/issues/set_escalation_status_spec.rb
@@ -50,16 +50,6 @@ RSpec.describe Mutations::Issues::SetEscalationStatus do
expect { result }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature unavailable for provided issue')
end
end
-
- context 'with feature disabled' do
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it 'raises an error' do
- expect { result }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable, 'Feature unavailable for provided issue')
- end
- end
end
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 86a6c77fa3f..a5291a00799 100644
--- a/spec/graphql/mutations/release_asset_links/create_spec.rb
+++ b/spec/graphql/mutations/release_asset_links/create_spec.rb
@@ -37,7 +37,7 @@ RSpec.describe Mutations::ReleaseAssetLinks::Create do
context 'when the user has access and no validation errors occur' do
it 'creates a new release asset link', :aggregate_failures do
- expect(subject).to eq({
+ expect(subject).to include({
link: release.reload.links.first,
errors: []
})
diff --git a/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb b/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb
index 818a7d303bd..668768189df 100644
--- a/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb
+++ b/spec/graphql/mutations/security/ci_configuration/base_security_analyzer_spec.rb
@@ -7,8 +7,10 @@ RSpec.describe Mutations::Security::CiConfiguration::BaseSecurityAnalyzer do
it 'raises a NotImplementedError error if the resolve method is called on the base class' do
user = create(:user)
+ mutation = described_class.new(context: { current_user: user }, object: nil, field: nil)
project = create(:project, :public, :repository)
project.add_developer(user)
- expect { resolve(described_class, args: { project_path: project.full_path }, ctx: { current_user: user }) }.to raise_error(NotImplementedError)
+
+ expect { mutation.resolve(project_path: project.full_path ) }.to raise_error(NotImplementedError)
end
end
diff --git a/spec/graphql/mutations/terraform/state/delete_spec.rb b/spec/graphql/mutations/terraform/state/delete_spec.rb
index 313a85a4bac..66d4b50741f 100644
--- a/spec/graphql/mutations/terraform/state/delete_spec.rb
+++ b/spec/graphql/mutations/terraform/state/delete_spec.rb
@@ -34,12 +34,12 @@ RSpec.describe Mutations::Terraform::State::Delete do
state.project.add_maintainer(user)
end
- it 'deletes the state', :aggregate_failures do
- expect do
- expect(subject).to eq(errors: [])
- end.to change { ::Terraform::State.count }.by(-1)
+ it 'schedules the state for deletion', :aggregate_failures do
+ expect_next_instance_of(Terraform::States::TriggerDestroyService, state, current_user: user) do |service|
+ expect(service).to receive(:execute).once.and_return(ServiceResponse.success)
+ end
- expect { state.reload }.to raise_error(ActiveRecord::RecordNotFound)
+ subject
end
end
diff --git a/spec/graphql/mutations/work_items/update_task_spec.rb b/spec/graphql/mutations/work_items/update_task_spec.rb
new file mode 100644
index 00000000000..cb93e97504a
--- /dev/null
+++ b/spec/graphql/mutations/work_items/update_task_spec.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::WorkItems::UpdateTask do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+ let_it_be(:referenced_work_item, refind: true) { create(:work_item, project: project, title: 'REFERENCED') }
+ let_it_be(:parent_work_item) do
+ create(:work_item, project: project, description: "- [ ] #{referenced_work_item.to_reference}+")
+ end
+
+ let(:task_params) { { title: 'UPDATED' } }
+ let(:task_input) { { id: referenced_work_item.to_global_id }.merge(task_params) }
+ let(:input) { { id: parent_work_item.to_global_id, task_data: task_input } }
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ describe '#resolve' do
+ subject(:resolve) do
+ mutation.resolve(**input)
+ end
+
+ before do
+ stub_spam_services
+ end
+
+ context 'when user has sufficient permissions' do
+ let(:current_user) { developer }
+
+ it 'expires etag cache for parent work item' do
+ allow(WorkItem).to receive(:find).and_call_original
+ allow(WorkItem).to receive(:find).with(parent_work_item.id.to_s).and_return(parent_work_item)
+
+ expect(parent_work_item).to receive(:expire_etag_cache)
+
+ resolve
+ end
+ end
+ end
+end
diff --git a/spec/graphql/mutations/work_items/update_widgets_spec.rb b/spec/graphql/mutations/work_items/update_widgets_spec.rb
new file mode 100644
index 00000000000..2e54b81b5c7
--- /dev/null
+++ b/spec/graphql/mutations/work_items/update_widgets_spec.rb
@@ -0,0 +1,58 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Mutations::WorkItems::UpdateWidgets do
+ include GraphqlHelpers
+
+ let_it_be(:project) { create(:project) }
+ let_it_be(:developer) { create(:user).tap { |user| project.add_developer(user) } }
+
+ let(:mutation) { described_class.new(object: nil, context: { current_user: current_user }, field: nil) }
+
+ describe '#resolve' do
+ before do
+ stub_spam_services
+ end
+
+ context 'when no work item matches the given id' do
+ let(:current_user) { developer }
+ let(:gid) { global_id_of(id: non_existing_record_id, model_name: WorkItem.name) }
+
+ it 'raises an error' do
+ expect { mutation.resolve(id: gid, resolve: true) }.to raise_error(
+ Gitlab::Graphql::Errors::ResourceNotAvailable,
+ Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR
+ )
+ end
+ end
+
+ context 'when user can access the requested work item', :aggregate_failures do
+ let(:current_user) { developer }
+ let(:args) { {} }
+
+ let_it_be(:work_item) { create(:work_item, project: project) }
+
+ subject { mutation.resolve(id: work_item.to_global_id, **args) }
+
+ context 'when `:work_items` is disabled for a project' do
+ let_it_be(:project2) { create(:project) }
+
+ it 'returns an error' do
+ stub_feature_flags(work_items: project2) # only enable `work_item` for project2
+
+ expect(subject[:errors]).to contain_exactly('`work_items` feature flag disabled for this project')
+ end
+ end
+
+ context 'when resolved with an input for description widget' do
+ let(:args) { { description_widget: { description: "updated description" } } }
+
+ it 'returns the updated work item' do
+ expect(subject[:work_item].description).to eq("updated description")
+ expect(subject[:errors]).to be_empty
+ end
+ end
+ end
+ end
+end
diff --git a/spec/graphql/resolvers/alert_management/alert_resolver_spec.rb b/spec/graphql/resolvers/alert_management/alert_resolver_spec.rb
index 14ebe85d80e..618735837e8 100644
--- a/spec/graphql/resolvers/alert_management/alert_resolver_spec.rb
+++ b/spec/graphql/resolvers/alert_management/alert_resolver_spec.rb
@@ -68,6 +68,6 @@ RSpec.describe Resolvers::AlertManagement::AlertResolver do
private
def resolve_alerts(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: project, args: args, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
index 392385d2a30..ab1f19abaad 100644
--- a/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_list_issues_resolver_spec.rb
@@ -128,6 +128,6 @@ RSpec.describe Resolvers::BoardListIssuesResolver do
end
def resolve_board_list_issues(args: {}, current_user: user)
- resolve(described_class, obj: list, args: args, ctx: { current_user: current_user })
+ resolve(described_class, obj: list, args: args, ctx: { current_user: current_user }, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/board_lists_resolver_spec.rb b/spec/graphql/resolvers/board_lists_resolver_spec.rb
index 7a1d8590546..c882ad7c818 100644
--- a/spec/graphql/resolvers/board_lists_resolver_spec.rb
+++ b/spec/graphql/resolvers/board_lists_resolver_spec.rb
@@ -100,6 +100,8 @@ RSpec.describe Resolvers::BoardListsResolver do
end
def resolve_board_lists(args: {}, current_user: user)
- resolve(described_class, obj: board, args: args, ctx: { current_user: current_user })
+ resolve(described_class, obj: board, args: args, ctx: { current_user: current_user },
+ arg_style: :internal
+ )
end
end
diff --git a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
index 89a2437a189..f99f48f5b07 100644
--- a/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/group_runners_resolver_spec.rb
@@ -6,7 +6,10 @@ RSpec.describe Resolvers::Ci::GroupRunnersResolver do
include GraphqlHelpers
describe '#resolve' do
- subject { resolve(described_class, obj: obj, ctx: { current_user: user }, args: args) }
+ subject do
+ resolve(described_class, obj: obj, ctx: { current_user: user }, args: args,
+ arg_style: :internal)
+ end
include_context 'runners resolver setup'
diff --git a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
index 1b69bf7f63a..6c228861ddf 100644
--- a/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/jobs_resolver_spec.rb
@@ -19,7 +19,7 @@ RSpec.describe Resolvers::Ci::JobsResolver do
describe '#resolve' do
context 'when security_report_types is empty' do
it "returns all of the pipeline's jobs" do
- jobs = resolve(described_class, obj: pipeline)
+ jobs = resolve(described_class, obj: pipeline, arg_style: :internal)
expect(jobs).to contain_exactly(
have_attributes(name: 'Normal job'),
@@ -37,7 +37,8 @@ RSpec.describe Resolvers::Ci::JobsResolver do
::Types::Security::ReportTypeEnum.values['SAST'].value,
::Types::Security::ReportTypeEnum.values['DAST'].value
]
- jobs = resolve(described_class, obj: pipeline, args: { security_report_types: report_types })
+ jobs = resolve(described_class, obj: pipeline, args: { security_report_types: report_types },
+ arg_style: :internal)
expect(jobs).to contain_exactly(
have_attributes(name: 'DAST job'),
@@ -48,7 +49,7 @@ 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)
+ jobs = resolve(described_class, obj: pipeline, arg_style: :internal)
expect(jobs).to contain_exactly(
have_attributes(tag_list: []),
have_attributes(tag_list: []),
diff --git a/spec/graphql/resolvers/ci/runners_resolver_spec.rb b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
index 9251fbf24d9..b1f5f7b3e43 100644
--- a/spec/graphql/resolvers/ci/runners_resolver_spec.rb
+++ b/spec/graphql/resolvers/ci/runners_resolver_spec.rb
@@ -9,7 +9,10 @@ RSpec.describe Resolvers::Ci::RunnersResolver do
let(:obj) { nil }
let(:args) { {} }
- subject { resolve(described_class, obj: obj, ctx: { current_user: user }, args: args) }
+ subject do
+ resolve(described_class, obj: obj, ctx: { current_user: user }, args: args,
+ arg_style: :internal)
+ end
include_context 'runners resolver setup'
diff --git a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
index 852aaf66201..892ab53a53e 100644
--- a/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
+++ b/spec/graphql/resolvers/concerns/caching_array_resolver_spec.rb
@@ -79,7 +79,7 @@ RSpec.describe ::CachingArrayResolver do
expect(User).to receive(:from_union).twice.and_call_original
results = users.in_groups_of(2, false).map do |users|
- resolve(resolver, args: { username: users.map(&:username) }, schema: schema)
+ resolve(resolver, args: { username: users.map(&:username) }, schema: schema, arg_style: :internal)
end
expect(results.flat_map(&method(:force))).to match_array(users)
@@ -208,6 +208,6 @@ RSpec.describe ::CachingArrayResolver do
args = { is_admin: admin }
opts = resolver.field_options
allow(resolver).to receive(:field_options).and_return(opts.merge(max_page_size: max_page_size))
- resolve(resolver, args: args, ctx: query_context, schema: schema)
+ resolve(resolver, args: args, ctx: query_context, schema: schema, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/concerns/resolves_groups_spec.rb b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb
index bfbbae29e92..d15c8f2ee42 100644
--- a/spec/graphql/resolvers/concerns/resolves_groups_spec.rb
+++ b/spec/graphql/resolvers/concerns/resolves_groups_spec.rb
@@ -27,11 +27,9 @@ RSpec.describe ResolvesGroups do
let_it_be(:lookahead_fields) do
<<~FIELDS
- contacts { nodes { id } }
containerRepositoriesCount
customEmoji { nodes { id } }
fullPath
- organizations { nodes { id } }
path
dependencyProxyBlobCount
dependencyProxyBlobs { nodes { fileName } }
diff --git a/spec/graphql/resolvers/container_repositories_resolver_spec.rb b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
index a17d2a7b0d5..d7aa761320f 100644
--- a/spec/graphql/resolvers/container_repositories_resolver_spec.rb
+++ b/spec/graphql/resolvers/container_repositories_resolver_spec.rb
@@ -15,7 +15,10 @@ RSpec.describe Resolvers::ContainerRepositoriesResolver do
describe '#resolve' do
let(:object) { project }
- subject { resolve(described_class, ctx: { current_user: user }, args: args, obj: object) }
+ subject do
+ resolve(described_class, ctx: { current_user: user }, args: args, obj: object,
+ arg_style: :internal)
+ end
shared_examples 'returning container repositories' do
it { is_expected.to contain_exactly(container_repositories) }
diff --git a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb
index 4e7ea253c87..9747f663759 100644
--- a/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb
+++ b/spec/graphql/resolvers/container_repository_tags_resolver_spec.rb
@@ -12,7 +12,10 @@ RSpec.describe Resolvers::ContainerRepositoryTagsResolver do
let(:args) { { sort: nil } }
describe '#resolve' do
- let(:resolver) { resolve(described_class, ctx: { current_user: user }, obj: repository, args: args) }
+ let(:resolver) do
+ resolve(described_class, ctx: { current_user: user }, obj: repository, args: args,
+ arg_style: :internal)
+ end
before do
stub_container_registry_config(enabled: true)
diff --git a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
new file mode 100644
index 00000000000..98da4aeac28
--- /dev/null
+++ b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb
@@ -0,0 +1,92 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Crm::ContactsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+
+ let_it_be(:contact_a) do
+ create(
+ :contact,
+ group: group,
+ first_name: "ABC",
+ last_name: "DEF",
+ email: "ghi@test.com",
+ description: "LMNO",
+ state: "inactive"
+ )
+ end
+
+ let_it_be(:contact_b) do
+ create(
+ :contact,
+ group: group,
+ first_name: "PQR",
+ last_name: "STU",
+ email: "vwx@test.com",
+ description: "YZ",
+ state: "active"
+ )
+ end
+
+ describe '#resolve' do
+ context 'with unauthorized user' do
+ it 'does not rise an error and returns no contacts' do
+ expect { resolve_contacts(group) }.not_to raise_error
+ expect(resolve_contacts(group)).to be_empty
+ end
+ end
+
+ context 'with authorized user' do
+ it 'does not rise an error and returns all contacts in the correct order' do
+ group.add_reporter(user)
+
+ expect { resolve_contacts(group) }.not_to raise_error
+ expect(resolve_contacts(group)).to eq([contact_a, contact_b])
+ end
+ end
+
+ context 'without parent' do
+ it 'returns no contacts' do
+ expect(resolve_contacts(nil)).to be_empty
+ end
+ end
+
+ context 'with a group parent' do
+ before do
+ group.add_developer(user)
+ end
+
+ context 'when no filter is provided' do
+ it 'returns all the contacts in the correct order' do
+ expect(resolve_contacts(group)).to eq([contact_a, contact_b])
+ end
+ end
+
+ context 'when search term is provided' do
+ it 'returns the correct contacts' do
+ expect(resolve_contacts(group, { search: "x@test.com" })).to contain_exactly(contact_b)
+ end
+ end
+
+ context 'when state is provided' do
+ it 'returns the correct contacts' do
+ expect(resolve_contacts(group, { state: :inactive })).to contain_exactly(contact_a)
+ end
+ end
+
+ context 'when ids are provided' do
+ it 'returns the correct contacts' do
+ expect(resolve_contacts(group, { ids: [contact_a.to_global_id] })).to contain_exactly(contact_a)
+ end
+ end
+ end
+ end
+
+ def resolve_contacts(parent, args = {}, context = { current_user: user })
+ resolve(described_class, obj: parent, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb
new file mode 100644
index 00000000000..323f134ffc3
--- /dev/null
+++ b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb
@@ -0,0 +1,88 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::Crm::OrganizationsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+
+ let_it_be(:organization_a) do
+ create(
+ :organization,
+ group: group,
+ name: "ABC",
+ state: "inactive"
+ )
+ end
+
+ let_it_be(:organization_b) do
+ create(
+ :organization,
+ group: group,
+ name: "DEF",
+ state: "active"
+ )
+ end
+
+ describe '#resolve' do
+ context 'with unauthorized user' do
+ it 'does not rise an error and returns no 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
+ group.add_reporter(user)
+
+ expect { resolve_organizations(group) }.not_to raise_error
+ expect(resolve_organizations(group)).to eq([organization_a, organization_b])
+ end
+ end
+
+ context 'without parent' do
+ it 'returns no organizations' do
+ expect(resolve_organizations(nil)).to be_empty
+ end
+ end
+
+ context 'with a group parent' do
+ before do
+ group.add_developer(user)
+ end
+
+ context 'when no filter is provided' do
+ it 'returns all the organizations in the correct order' do
+ expect(resolve_organizations(group)).to eq([organization_a, 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)
+ 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)
+ end
+ end
+
+ context 'when ids are provided' do
+ it 'returns the correct organizations' do
+ expect(resolve_organizations(group, {
+ ids: [organization_b.to_global_id]
+ })).to contain_exactly(organization_b)
+ end
+ end
+ end
+ end
+
+ def resolve_organizations(parent, args = {}, context = { current_user: user })
+ resolve(described_class, obj: parent, args: args, ctx: context)
+ end
+end
diff --git a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
index 8eab0222cf6..3a2ed445484 100644
--- a/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
+++ b/spec/graphql/resolvers/design_management/versions_resolver_spec.rb
@@ -90,6 +90,8 @@ RSpec.describe Resolvers::DesignManagement::VersionsResolver do
end
context 'and they do not match' do
+ subject(:result) { resolve_versions(object) }
+
let(:params) do
{
earlier_or_equal_to_sha: first_version.sha,
@@ -104,14 +106,6 @@ RSpec.describe Resolvers::DesignManagement::VersionsResolver do
end
end
end
-
- context 'by at_version in parent' do
- before do
- query_context[:at_version_argument] = first_version.to_global_id
- end
-
- it_behaves_like 'a query for all_versions up to the first_version'
- end
end
end
diff --git a/spec/graphql/resolvers/group_labels_resolver_spec.rb b/spec/graphql/resolvers/group_labels_resolver_spec.rb
index 2031e534703..71290885e6b 100644
--- a/spec/graphql/resolvers/group_labels_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_labels_resolver_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Resolvers::GroupLabelsResolver do
it 'does not raise error' do
group.add_guest(current_user)
- expect { resolve_labels(subgroup) }.not_to raise_error
+ expect(resolve_labels(subgroup)).to be_instance_of(Gitlab::Graphql::Pagination::Keyset::Connection)
end
end
diff --git a/spec/graphql/resolvers/group_milestones_resolver_spec.rb b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
index 7abc779a63c..a32a031a88f 100644
--- a/spec/graphql/resolvers/group_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_milestones_resolver_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Resolvers::GroupMilestonesResolver 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)
+ resolve(described_class, obj: group, args: args, ctx: context, arg_style: :internal)
end
let_it_be(:now) { Time.now }
@@ -126,16 +126,6 @@ RSpec.describe Resolvers::GroupMilestonesResolver do
end
end
- context 'when user cannot read milestones' do
- it 'generates an error' do
- unauthorized_user = create(:user)
-
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
- resolve_group_milestones({}, { current_user: unauthorized_user })
- end
- end
- end
-
context 'when including descendant milestones in a public group' do
let_it_be(:group) { create(:group, :public) }
diff --git a/spec/graphql/resolvers/group_packages_resolver_spec.rb b/spec/graphql/resolvers/group_packages_resolver_spec.rb
index eba3a5f2de8..c600f9c9f9a 100644
--- a/spec/graphql/resolvers/group_packages_resolver_spec.rb
+++ b/spec/graphql/resolvers/group_packages_resolver_spec.rb
@@ -2,15 +2,16 @@
require 'spec_helper'
-RSpec.describe Resolvers::GroupPackagesResolver do
+RSpec.describe 'Resolvers::GroupPackagesResolver' do
include GraphqlHelpers
+ let_it_be(:described_class) { Resolvers::GroupPackagesResolver }
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group, :public) }
let_it_be(:project) { create(:project, :public, group: group, path: 'a') }
let(:args) do
- { sort: :created_desc }
+ { sort: 'CREATED_DESC' }
end
describe '#resolve' do
@@ -26,13 +27,13 @@ RSpec.describe Resolvers::GroupPackagesResolver do
let_it_be(:package4) { create(:package, project: project2 ) }
context 'filter by package_name' do
- let(:args) { { sort: :project_path_desc } }
+ let(:args) { { sort: 'PROJECT_PATH_DESC' } }
it { is_expected.to eq([package4, package2, package3, package]) }
end
context 'filter by package_type' do
- let(:args) { { sort: :project_path_asc } }
+ let(:args) { { sort: 'PROJECT_PATH_ASC' } }
it { is_expected.to eq([package, package3, package2, package4]) }
end
diff --git a/spec/graphql/resolvers/incident_management/timeline_events_resolver_spec.rb b/spec/graphql/resolvers/incident_management/timeline_events_resolver_spec.rb
index 046cf242d56..6604141abfe 100644
--- a/spec/graphql/resolvers/incident_management/timeline_events_resolver_spec.rb
+++ b/spec/graphql/resolvers/incident_management/timeline_events_resolver_spec.rb
@@ -2,9 +2,10 @@
require 'spec_helper'
-RSpec.describe Resolvers::IncidentManagement::TimelineEventsResolver do
+RSpec.describe 'Resolvers::IncidentManagement::TimelineEventsResolver' do
include GraphqlHelpers
+ let_it_be(:described_class) { Resolvers::IncidentManagement::TimelineEventsResolver }
let_it_be(:current_user) { create(:user) }
let_it_be(:project) { create(:project) }
let_it_be(:incident) { create(:incident, project: project) }
diff --git a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
index 77f4ce4cac5..86a4154f23b 100644
--- a/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
+++ b/spec/graphql/resolvers/issue_status_counts_resolver_spec.rb
@@ -70,7 +70,7 @@ RSpec.describe Resolvers::IssueStatusCountsResolver do
end
context 'when both assignee_username and assignee_usernames are provided' do
- it 'generates a mutually exclusive filter error' do
+ it 'returns a mutually exclusive filter error' do
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, 'only one of [assigneeUsernames, assigneeUsername] arguments is allowed at the same time.') do
resolve_issue_status_counts(assignee_usernames: [current_user.username], assignee_username: current_user.username)
end
diff --git a/spec/graphql/resolvers/issues_resolver_spec.rb b/spec/graphql/resolvers/issues_resolver_spec.rb
index e6ec9d8c895..a5b5a8e4f72 100644
--- a/spec/graphql/resolvers/issues_resolver_spec.rb
+++ b/spec/graphql/resolvers/issues_resolver_spec.rb
@@ -428,6 +428,22 @@ RSpec.describe Resolvers::IssuesResolver do
end
end
+ context 'when sorting by closed at' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:closed_issue1) { create(:issue, project: project, closed_at: 3.days.from_now) }
+ let_it_be(:closed_issue2) { create(:issue, project: project, closed_at: nil) }
+ let_it_be(:closed_issue3) { create(:issue, project: project, closed_at: 2.days.ago) }
+ let_it_be(:closed_issue4) { create(:issue, project: project, closed_at: nil) }
+
+ it 'sorts issues ascending' do
+ expect(resolve_issues(sort: :closed_at_asc).to_a).to eq [closed_issue3, closed_issue1, closed_issue4, closed_issue2]
+ end
+
+ it 'sorts issues descending' do
+ expect(resolve_issues(sort: :closed_at_desc).to_a).to eq [closed_issue1, closed_issue3, closed_issue4, closed_issue2]
+ end
+ end
+
context 'when sorting by due date' do
let_it_be(:project) { create(:project, :public) }
let_it_be(:due_issue1) { create(:issue, project: project, due_date: 3.days.from_now) }
@@ -573,22 +589,6 @@ RSpec.describe Resolvers::IssuesResolver do
issues = resolve_issues(sort: :created_desc).to_a
expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident])
end
-
- context 'when incident_escalations feature flag is disabled' do
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it 'defaults ascending status sort to created_desc' do
- issues = resolve_issues(sort: :escalation_status_asc).to_a
- expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident])
- end
-
- it 'defaults descending status sort to created_desc' do
- issues = resolve_issues(sort: :escalation_status_desc).to_a
- expect(issues).to eq([resolved_incident, issue_no_status, triggered_incident])
- end
- end
end
context 'when sorting with non-stable cursors' do
@@ -701,6 +701,6 @@ RSpec.describe Resolvers::IssuesResolver do
end
def resolve_issues(args = {}, context = { current_user: current_user })
- resolve(described_class, obj: project, args: args, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/merge_requests_resolver_spec.rb b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
index e4eaeb9bc3c..ab3d7edc6bd 100644
--- a/spec/graphql/resolvers/merge_requests_resolver_spec.rb
+++ b/spec/graphql/resolvers/merge_requests_resolver_spec.rb
@@ -174,7 +174,7 @@ RSpec.describe Resolvers::MergeRequestsResolver do
context 'with draft argument' do
before do
- merge_request_4.update!(title: MergeRequest.wip_title(merge_request_4.title))
+ merge_request_4.update!(title: MergeRequest.draft_title(merge_request_4.title))
end
context 'with draft: true argument' do
@@ -411,6 +411,6 @@ RSpec.describe Resolvers::MergeRequestsResolver do
end
def resolve_mr(project, resolver: described_class, user: current_user, **args)
- resolve(resolver, obj: project, args: args, ctx: { current_user: user })
+ resolve(resolver, obj: project, args: args, ctx: { current_user: user }, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
index eb4d0ab6f37..78dd5173449 100644
--- a/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
+++ b/spec/graphql/resolvers/namespace_projects_resolver_spec.rb
@@ -152,6 +152,6 @@ RSpec.describe Resolvers::NamespaceProjectsResolver do
end
def resolve_projects(args = { include_subgroups: false, sort: nil, search: nil, ids: nil }, context = { current_user: current_user })
- resolve(described_class, obj: namespace, args: args, ctx: context)
+ resolve(described_class, obj: namespace, args: args, ctx: context, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/packages_base_resolver_spec.rb b/spec/graphql/resolvers/packages_base_resolver_spec.rb
index 8f9865c3785..7766fdd4994 100644
--- a/spec/graphql/resolvers/packages_base_resolver_spec.rb
+++ b/spec/graphql/resolvers/packages_base_resolver_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Resolvers::PackagesBaseResolver do
include GraphqlHelpers
describe '#resolve' do
- subject { resolve(described_class) }
+ subject { resolve(described_class, arg_style: :internal) }
it 'throws an error' do
expect { subject }.to raise_error(NotImplementedError)
diff --git a/spec/graphql/resolvers/project_milestones_resolver_spec.rb b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
index 2cf490c2b6a..ad1190e3df7 100644
--- a/spec/graphql/resolvers/project_milestones_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_milestones_resolver_spec.rb
@@ -2,12 +2,15 @@
require 'spec_helper'
-RSpec.describe Resolvers::ProjectMilestonesResolver do
+RSpec.describe 'Resolvers::ProjectMilestonesResolver' do
include GraphqlHelpers
describe '#resolve' do
+ let_it_be(:described_class) { Resolvers::ProjectMilestonesResolver }
let_it_be(:project) { create(:project, :private) }
let_it_be(:current_user) { create(:user) }
+ let_it_be(:now) { Time.now }
+ let_it_be(:now_date) { now.to_date }
before_all do
project.add_developer(current_user)
@@ -25,7 +28,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
it 'calls MilestonesFinder to retrieve all milestones' do
expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'all'))
+ .with(args(project_ids: project.id, state: 'all', sort: :due_date_asc))
.and_call_original
resolve_project_milestones
@@ -42,7 +45,8 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
it 'calls MilestonesFinder with correct parameters' do
expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, group_ids: contain_exactly(group, parent_group), state: 'all'))
+ .with(args(project_ids: project.id, group_ids: contain_exactly(group, parent_group),
+ state: 'all', sort: :due_date_asc))
.and_call_original
resolve_project_milestones(include_ancestors: true)
@@ -54,7 +58,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
milestone = create(:milestone, project: project)
expect(MilestonesFinder).to receive(:new)
- .with(args(ids: [milestone.id.to_s], project_ids: project.id, state: 'all'))
+ .with(args(ids: [milestone.id.to_s], project_ids: project.id, state: 'all', sort: :due_date_asc))
.and_call_original
resolve_project_milestones(ids: [milestone.to_global_id])
@@ -64,7 +68,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'by state' do
it 'calls MilestonesFinder with correct parameters' do
expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'closed'))
+ .with(args(project_ids: project.id, state: 'closed', sort: :due_date_asc))
.and_call_original
resolve_project_milestones(state: 'closed')
@@ -74,13 +78,13 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'by sort' do
it 'calls MilestonesFinder with correct parameters' do
expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'all', sort: :due_date_desc))
+ .with(args(project_ids: project.id, state: 'all', sort: :due_date_asc))
.and_call_original
- resolve_project_milestones(sort: :due_date_desc)
+ resolve_project_milestones(sort: 'DUE_DATE_ASC')
end
- %i[expired_last_due_date_asc expired_last_due_date_desc].each do |sort_by|
+ %w[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_project_milestones(sort: sort_by)
@@ -92,11 +96,12 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'by timeframe' do
context 'when start_date and end_date are present' do
it 'calls MilestonesFinder with correct parameters' do
- start_date = Time.now
- end_date = Time.now + 5.days
+ 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))
+ .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)
@@ -105,7 +110,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver 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_project_milestones(start_date: Time.now, end_date: Time.now - 2.days)
+ resolve_project_milestones(start_date: now, end_date: now - 2.days)
end
end
end
@@ -114,7 +119,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
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: Time.now)
+ resolve_project_milestones(start_date: now)
end
end
end
@@ -122,18 +127,19 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
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: Time.now)
+ resolve_project_milestones(end_date: now)
end
end
end
context 'when passing a timeframe' do
it 'calls MilestonesFinder with correct parameters' do
- start_date = Time.now
- end_date = Time.now + 5.days
+ start_date = now_date
+ end_date = now_date + 5.days
expect(MilestonesFinder).to receive(:new)
- .with(args(project_ids: project.id, state: 'all', start_date: start_date, end_date: end_date))
+ .with(args(project_ids: project.id, state: 'all',
+ sort: :due_date_asc, start_date: start_date, end_date: end_date))
.and_call_original
resolve_project_milestones(timeframe: { start: start_date, end: end_date })
@@ -144,7 +150,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'when title is present' do
it 'calls MilestonesFinder with correct parameters' do
expect(MilestonesFinder).to receive(:new)
- .with(args(title: '13.5', state: 'all', project_ids: project.id))
+ .with(args(title: '13.5', state: 'all', sort: :due_date_asc, project_ids: project.id))
.and_call_original
resolve_project_milestones(title: '13.5')
@@ -154,7 +160,7 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'when search_title is present' do
it 'calls MilestonesFinder with correct parameters' do
expect(MilestonesFinder).to receive(:new)
- .with(args(search_title: '13', state: 'all', project_ids: project.id))
+ .with(args(search_title: '13', state: 'all', sort: :due_date_asc, project_ids: project.id))
.and_call_original
resolve_project_milestones(search_title: '13')
@@ -163,24 +169,14 @@ RSpec.describe Resolvers::ProjectMilestonesResolver do
context 'when containing date is present' do
it 'calls MilestonesFinder with correct parameters' do
- t = Time.now
+ t = now
expect(MilestonesFinder).to receive(:new)
- .with(args(containing_date: t, state: 'all', project_ids: project.id))
+ .with(args(containing_date: t, state: 'all', sort: :due_date_asc, project_ids: project.id))
.and_call_original
resolve_project_milestones(containing_date: t)
end
end
-
- context 'when user cannot read milestones' do
- it 'generates an error' do
- unauthorized_user = create(:user)
-
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
- resolve_project_milestones({}, { current_user: unauthorized_user })
- end
- end
- end
end
end
diff --git a/spec/graphql/resolvers/project_packages_resolver_spec.rb b/spec/graphql/resolvers/project_packages_resolver_spec.rb
index 66a94bd42dd..c3ce30f6ef9 100644
--- a/spec/graphql/resolvers/project_packages_resolver_spec.rb
+++ b/spec/graphql/resolvers/project_packages_resolver_spec.rb
@@ -2,18 +2,22 @@
require 'spec_helper'
-RSpec.describe Resolvers::ProjectPackagesResolver do
+RSpec.describe 'Resolvers::ProjectPackagesResolver' do
include GraphqlHelpers
+ let_it_be(:described_class) { Resolvers::ProjectPackagesResolver }
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:project) { create(:project, :public) }
let(:args) do
- { sort: :created_desc }
+ { sort: 'CREATED_DESC' }
end
describe '#resolve' do
- subject { resolve(described_class, ctx: { current_user: user }, obj: project, args: args).to_a }
+ subject do
+ resolve(described_class, ctx: { current_user: user }, obj: project, args: args)
+ .to_a
+ end
it_behaves_like 'group and projects packages resolver'
end
diff --git a/spec/graphql/resolvers/releases_resolver_spec.rb b/spec/graphql/resolvers/releases_resolver_spec.rb
index 89623be891f..6ba9a6c33a1 100644
--- a/spec/graphql/resolvers/releases_resolver_spec.rb
+++ b/spec/graphql/resolvers/releases_resolver_spec.rb
@@ -87,6 +87,6 @@ RSpec.describe Resolvers::ReleasesResolver do
def resolve_releases
context = { current_user: current_user }
- resolve(described_class, obj: project, args: args, ctx: context)
+ resolve(described_class, obj: project, args: args, ctx: context, arg_style: :internal)
end
end
diff --git a/spec/graphql/resolvers/user_resolver_spec.rb b/spec/graphql/resolvers/user_resolver_spec.rb
index 446d765d3ee..d57b015b705 100644
--- a/spec/graphql/resolvers/user_resolver_spec.rb
+++ b/spec/graphql/resolvers/user_resolver_spec.rb
@@ -6,8 +6,29 @@ RSpec.describe Resolvers::UserResolver do
include GraphqlHelpers
describe '#resolve' do
+ let_it_be(:current_user) { nil }
let_it_be(:user) { create(:user) }
+ shared_examples 'queries user' do
+ context 'authenticated access' do
+ let_it_be(:current_user) { create(:user) }
+
+ it 'returns the correct user' do
+ expect(
+ resolve_user(args)
+ ).to eq(user)
+ end
+ end
+
+ context 'unauthenticated access' do
+ it 'forbids search' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_user(args)
+ end
+ end
+ end
+ end
+
context 'when neither an ID or a username is provided' do
it 'generates an ArgumentError' do
expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError) do
@@ -23,25 +44,21 @@ RSpec.describe Resolvers::UserResolver do
end
context 'by username' do
- it 'returns the correct user' do
- expect(
- resolve_user(username: user.username)
- ).to eq(user)
+ include_examples "queries user" do
+ let(:args) { { username: user.username } }
end
end
context 'by ID' do
- it 'returns the correct user' do
- expect(
- resolve_user(id: user.to_global_id)
- ).to eq(user)
+ include_examples "queries user" do
+ let(:args) { { id: user.to_global_id } }
end
end
end
private
- def resolve_user(args = {})
- sync(resolve(described_class, args: args))
+ def resolve_user(args = {}, context = { current_user: current_user })
+ sync(resolve(described_class, args: args, ctx: context))
end
end
diff --git a/spec/graphql/resolvers/users/groups_resolver_spec.rb b/spec/graphql/resolvers/users/groups_resolver_spec.rb
index 5ac7aac4898..bbe9b6371cf 100644
--- a/spec/graphql/resolvers/users/groups_resolver_spec.rb
+++ b/spec/graphql/resolvers/users/groups_resolver_spec.rb
@@ -93,6 +93,6 @@ RSpec.describe Resolvers::Users::GroupsResolver do
end
def resolve_groups(args:, current_user:, obj:)
- resolve(described_class, args: args, ctx: { current_user: current_user }, obj: obj)&.items
+ resolve(described_class, args: args, ctx: { current_user: current_user }, obj: obj, arg_style: :internal)&.items
end
end
diff --git a/spec/graphql/resolvers/users_resolver_spec.rb b/spec/graphql/resolvers/users_resolver_spec.rb
index 1ba296912a3..dda15303676 100644
--- a/spec/graphql/resolvers/users_resolver_spec.rb
+++ b/spec/graphql/resolvers/users_resolver_spec.rb
@@ -14,14 +14,6 @@ RSpec.describe Resolvers::UsersResolver do
end
describe '#resolve' do
- it 'generates an error when read_users_list is not authorized' do
- expect(Ability).to receive(:allowed?).with(current_user, :read_users_list).and_return(false)
-
- expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
- resolve_users
- end
- end
-
context 'when no arguments are passed' do
it 'returns all users' do
expect(resolve_users).to contain_exactly(user1, user2, current_user)
@@ -79,8 +71,10 @@ RSpec.describe Resolvers::UsersResolver do
end
end
- it 'allows to search by username' do
- expect(resolve_users(args: { usernames: [user1.username] })).to contain_exactly(user1)
+ it 'prohibits search by username' do
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ResourceNotAvailable) do
+ resolve_users(args: { usernames: [user1.username] })
+ end
end
end
end
diff --git a/spec/graphql/resolvers/work_items_resolver_spec.rb b/spec/graphql/resolvers/work_items_resolver_spec.rb
new file mode 100644
index 00000000000..29eac0ab46e
--- /dev/null
+++ b/spec/graphql/resolvers/work_items_resolver_spec.rb
@@ -0,0 +1,190 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Resolvers::WorkItemsResolver do
+ include GraphqlHelpers
+
+ let_it_be(:current_user) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:other_project) { create(:project, group: group) }
+
+ let_it_be(:item1) do
+ create(:work_item, project: project, state: :opened, created_at:
+ 3.hours.ago, updated_at: 3.hours.ago)
+ end
+
+ let_it_be(:item2) do
+ create(:work_item, project: project, state: :closed, title: 'foo',
+ created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at:
+ 1.hour.ago)
+ end
+
+ let_it_be(:item3) do
+ create(:work_item, project: other_project, state: :closed, title: 'foo',
+ created_at: 1.hour.ago, updated_at: 1.hour.ago, closed_at:
+ 1.hour.ago)
+ end
+
+ let_it_be(:item4) { create(:work_item) }
+
+ specify do
+ expect(described_class).to have_nullable_graphql_type(Types::WorkItemType.connection_type)
+ end
+
+ context "with a project" do
+ before_all do
+ project.add_developer(current_user)
+ project.add_reporter(reporter)
+ end
+
+ describe '#resolve' do
+ it 'finds all items' do
+ expect(resolve_items).to contain_exactly(item1, item2)
+ end
+
+ it 'filters by state' do
+ expect(resolve_items(state: 'opened')).to contain_exactly(item1)
+ expect(resolve_items(state: 'closed')).to contain_exactly(item2)
+ end
+
+ context 'when searching items' do
+ it 'returns correct items' do
+ expect(resolve_items(search: 'foo')).to contain_exactly(item2)
+ end
+
+ it 'uses project search optimization' do
+ expected_arguments = a_hash_including(
+ search: 'foo',
+ attempt_project_search_optimizations: true
+ )
+ expect(::WorkItems::WorkItemsFinder).to receive(:new).with(anything, expected_arguments).and_call_original
+
+ resolve_items(search: 'foo')
+ end
+
+ context 'with anonymous user' do
+ let_it_be(:public_project) { create(:project, :public) }
+ let_it_be(:public_item) { create(:work_item, project: public_project, title: 'Test item') }
+
+ context 'with disable_anonymous_search enabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: true)
+ end
+
+ it 'generates an error' do
+ error_message = "User must be authenticated to include the `search` argument."
+
+ expect_graphql_error_to_be_created(Gitlab::Graphql::Errors::ArgumentError, error_message) do
+ resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil })
+ end
+ end
+ end
+
+ context 'with disable_anonymous_search disabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: false)
+ end
+
+ it 'returns correct items' do
+ expect(
+ resolve(described_class, obj: public_project, args: { search: 'test' }, ctx: { current_user: nil })
+ ).to contain_exactly(public_item)
+ end
+ end
+ end
+ end
+
+ describe 'sorting' do
+ context 'when sorting by created' do
+ it 'sorts items ascending' do
+ expect(resolve_items(sort: 'created_asc').to_a).to eq [item1, item2]
+ end
+
+ it 'sorts items descending' do
+ expect(resolve_items(sort: 'created_desc').to_a).to eq [item2, item1]
+ end
+ end
+
+ context 'when sorting by title' do
+ let_it_be(:project) { create(:project, :public) }
+ let_it_be(:item1) { create(:work_item, project: project, title: 'foo') }
+ let_it_be(:item2) { create(:work_item, project: project, title: 'bar') }
+ let_it_be(:item3) { create(:work_item, project: project, title: 'baz') }
+ let_it_be(:item4) { create(:work_item, project: project, title: 'Baz 2') }
+
+ it 'sorts items ascending' do
+ expect(resolve_items(sort: :title_asc).to_a).to eq [item2, item3, item4, item1]
+ end
+
+ it 'sorts items descending' do
+ expect(resolve_items(sort: :title_desc).to_a).to eq [item1, item4, item3, item2]
+ end
+ end
+ end
+
+ it 'returns items user can see' do
+ project.add_guest(current_user)
+
+ create(:work_item, confidential: true)
+
+ expect(resolve_items).to contain_exactly(item1, item2)
+ end
+
+ it 'batches queries that only include IIDs', :request_store do
+ result = batch_sync(max_queries: 7) do
+ [item1, item2]
+ .map { |item| resolve_items(iid: item.iid.to_s) }
+ .flat_map(&:to_a)
+ end
+
+ expect(result).to contain_exactly(item1, item2)
+ end
+
+ it 'finds a specific item with iids', :request_store do
+ result = batch_sync(max_queries: 7) do
+ resolve_items(iids: [item1.iid]).to_a
+ end
+
+ expect(result).to contain_exactly(item1)
+ end
+
+ it 'finds multiple items with iids' do
+ create(:work_item, project: project, author: current_user)
+
+ expect(batch_sync { resolve_items(iids: [item1.iid, item2.iid]).to_a })
+ .to contain_exactly(item1, item2)
+ end
+
+ it 'finds only the items within the project we are looking at' do
+ another_project = create(:project)
+ iids = [item1, item2].map(&:iid)
+
+ iids.each do |iid|
+ create(:work_item, project: another_project, iid: iid)
+ end
+
+ expect(batch_sync { resolve_items(iids: iids).to_a }).to contain_exactly(item1, item2)
+ end
+ end
+ end
+
+ context "when passing a non existent, batch loaded project" do
+ let!(:project) do
+ BatchLoader::GraphQL.for("non-existent-path").batch do |_fake_paths, loader, _|
+ loader.call("non-existent-path", nil)
+ end
+ end
+
+ it "returns nil without breaking" do
+ expect(resolve_items(iids: ["don't", "break"])).to be_empty
+ end
+ end
+
+ def resolve_items(args = {}, context = { current_user: current_user })
+ resolve(described_class, obj: project, args: args, ctx: context, arg_style: :internal)
+ end
+end
diff --git a/spec/graphql/subscriptions/issuable_updated_spec.rb b/spec/graphql/subscriptions/issuable_updated_spec.rb
index 0b8fcf67513..bc640e9e3c4 100644
--- a/spec/graphql/subscriptions/issuable_updated_spec.rb
+++ b/spec/graphql/subscriptions/issuable_updated_spec.rb
@@ -52,7 +52,8 @@ RSpec.describe Subscriptions::IssuableUpdated do
let(:current_user) { unauthorized_user }
it 'unsubscribes the user' do
- expect { subject }.to throw_symbol(:graphql_subscription_unsubscribed)
+ # GraphQL::Execution::Execute::Skip is returned when unsubscribed
+ expect(subject).to be_an(GraphQL::Execution::Execute::Skip)
end
end
end
diff --git a/spec/graphql/types/base_edge_spec.rb b/spec/graphql/types/base_edge_spec.rb
index 3afb4202173..b02ccbaffef 100644
--- a/spec/graphql/types/base_edge_spec.rb
+++ b/spec/graphql/types/base_edge_spec.rb
@@ -25,7 +25,6 @@ RSpec.describe Types::BaseEdge do
Class.new(GraphQL::Schema) do
lazy_resolve ::Gitlab::Graphql::Lazy, :force
- use ::GraphQL::Pagination::Connections
use ::Gitlab::Graphql::Pagination::Connections
query(Class.new(::Types::BaseObject) do
diff --git a/spec/graphql/types/base_field_spec.rb b/spec/graphql/types/base_field_spec.rb
index 9d02f061435..439678e7e16 100644
--- a/spec/graphql/types/base_field_spec.rb
+++ b/spec/graphql/types/base_field_spec.rb
@@ -3,6 +3,92 @@
require 'spec_helper'
RSpec.describe Types::BaseField do
+ describe 'authorized?' do
+ let(:object) { double }
+ let(:current_user) { nil }
+ let(:ctx) { { current_user: current_user } }
+
+ it 'defaults to true' do
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true)
+
+ expect(field).to be_authorized(object, nil, ctx)
+ end
+
+ it 'tests the field authorization, if provided' do
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, authorize: :foo)
+
+ expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(false)
+
+ expect(field).not_to be_authorized(object, nil, ctx)
+ end
+
+ it 'tests the field authorization, if provided, when it succeeds' do
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true, authorize: :foo)
+
+ expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(true)
+
+ expect(field).to be_authorized(object, nil, ctx)
+ end
+
+ it 'only tests the resolver authorization if it authorizes_object?' do
+ resolver = Class.new
+
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true,
+ resolver_class: resolver)
+
+ expect(field).to be_authorized(object, nil, ctx)
+ end
+
+ it 'tests the resolver authorization, if provided' do
+ resolver = Class.new do
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorizes_object!
+ end
+
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true,
+ resolver_class: resolver)
+
+ expect(resolver).to receive(:authorized?).with(object, ctx).and_return(false)
+
+ expect(field).not_to be_authorized(object, nil, ctx)
+ end
+
+ it 'tests field authorization before resolver authorization, when field auth fails' do
+ resolver = Class.new do
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorizes_object!
+ end
+
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true,
+ authorize: :foo,
+ resolver_class: resolver)
+
+ expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(false)
+ expect(resolver).not_to receive(:authorized?)
+
+ expect(field).not_to be_authorized(object, nil, ctx)
+ end
+
+ it 'tests field authorization before resolver authorization, when field auth succeeds' do
+ resolver = Class.new do
+ include Gitlab::Graphql::Authorize::AuthorizeResource
+
+ authorizes_object!
+ end
+
+ field = described_class.new(name: 'test', type: GraphQL::Types::String, null: true,
+ authorize: :foo,
+ resolver_class: resolver)
+
+ expect(Ability).to receive(:allowed?).with(current_user, :foo, object).and_return(true)
+ expect(resolver).to receive(:authorized?).with(object, ctx).and_return(false)
+
+ expect(field).not_to be_authorized(object, nil, ctx)
+ end
+ end
+
context 'when considering complexity' do
let(:resolver) do
Class.new(described_class) do
diff --git a/spec/graphql/types/base_object_spec.rb b/spec/graphql/types/base_object_spec.rb
index 45dc885ecba..3c42c708187 100644
--- a/spec/graphql/types/base_object_spec.rb
+++ b/spec/graphql/types/base_object_spec.rb
@@ -137,7 +137,6 @@ RSpec.describe Types::BaseObject do
Class.new(GraphQL::Schema) do
lazy_resolve ::Gitlab::Graphql::Lazy, :force
- use ::GraphQL::Pagination::Connections
use ::Gitlab::Graphql::Pagination::Connections
query(Class.new(::Types::BaseObject) do
diff --git a/spec/graphql/types/ci/detailed_status_type_spec.rb b/spec/graphql/types/ci/detailed_status_type_spec.rb
index 5ed79b73a47..0c05227aec2 100644
--- a/spec/graphql/types/ci/detailed_status_type_spec.rb
+++ b/spec/graphql/types/ci/detailed_status_type_spec.rb
@@ -17,12 +17,10 @@ RSpec.describe Types::Ci::DetailedStatusType do
describe 'id field' do
it 'correctly renders the field' do
- parent_object = double(:parent_object, object: stage)
- parent = double(:parent, object: parent_object)
status = stage.detailed_status(stage.pipeline.user)
expected_id = "#{status.id}-#{stage.id}"
- expect(resolve_field('id', status, extras: { parent: parent })).to eq(expected_id)
+ expect(resolve_field('id', status, extras: { parent: stage }, arg_style: :internal)).to eq(expected_id)
end
end
@@ -38,7 +36,7 @@ RSpec.describe Types::Ci::DetailedStatusType do
title: status.action_title
}
- expect(resolve_field('action', status)).to eq(expected_status)
+ expect(resolve_field('action', status, arg_style: :internal)).to eq(expected_status)
end
end
end
diff --git a/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb b/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb
new file mode 100644
index 00000000000..3a90e4f1fd9
--- /dev/null
+++ b/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PipelineMergeRequestEventType'] do
+ specify { expect(described_class.graphql_name).to eq('PipelineMergeRequestEventType') }
+
+ it 'has specific values' do
+ expect(described_class.values).to match a_hash_including(
+ 'MERGED_RESULT' => have_attributes(value: :merged_result),
+ 'DETACHED' => have_attributes(value: :detached)
+ )
+ end
+end
diff --git a/spec/graphql/types/ci/pipeline_type_spec.rb b/spec/graphql/types/ci/pipeline_type_spec.rb
index 94d1b42da37..9dee834d05f 100644
--- a/spec/graphql/types/ci/pipeline_type_spec.rb
+++ b/spec/graphql/types/ci/pipeline_type_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Types::Ci::PipelineType do
coverage created_at updated_at started_at finished_at committed_at
stages user retryable cancelable jobs source_job job job_artifacts downstream
upstream path project active user_permissions warnings commit commit_path uses_needs
- test_report_summary test_suite ref ref_path warning_messages
+ test_report_summary test_suite ref ref_path warning_messages merge_request_event_type
]
if Gitlab.ee?
diff --git a/spec/graphql/types/ci/runner_type_spec.rb b/spec/graphql/types/ci/runner_type_spec.rb
index 26ac7a4da8d..4ec35db13fb 100644
--- a/spec/graphql/types/ci/runner_type_spec.rb
+++ b/spec/graphql/types/ci/runner_type_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
id description created_at contacted_at 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 groups projects jobs token_expires_at
+ maintenance_note maintenance_note_html groups projects jobs token_expires_at owner_project
]
expect(described_class).to include_graphql_fields(*expected_fields)
diff --git a/spec/graphql/types/ci/status_action_type_spec.rb b/spec/graphql/types/ci/status_action_type_spec.rb
index ab7dee3dd11..4c467bf240e 100644
--- a/spec/graphql/types/ci/status_action_type_spec.rb
+++ b/spec/graphql/types/ci/status_action_type_spec.rb
@@ -25,15 +25,9 @@ RSpec.describe Types::Ci::StatusActionType do
stage = build(:ci_stage_entity, status: :skipped)
status = stage.detailed_status(stage.pipeline.user)
- grandparent_object = double(:grandparent_object, object: stage)
- parent_object = double(:parent_object, object: status)
-
- grandparent = double(:parent, object: grandparent_object)
- parent = double(:parent, object: parent_object, parent: grandparent)
-
expected_id = "#{stage.class.name}-#{status.id}"
- expect(resolve_field('id', status, extras: { parent: parent })).to eq(expected_id)
+ expect(resolve_field('id', status, extras: { parent: status }, arg_style: :internal)).to eq(expected_id)
end
end
end
diff --git a/spec/graphql/types/issue_type_spec.rb b/spec/graphql/types/issue_type_spec.rb
index 1d4590cbb4e..e7454b85357 100644
--- a/spec/graphql/types/issue_type_spec.rb
+++ b/spec/graphql/types/issue_type_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
confidential hidden discussion_locked upvotes downvotes merge_requests_count user_notes_count user_discussions_count web_path web_url relative_position
emails_disabled subscribed time_estimate total_time_spent human_time_estimate human_total_time_spent closed_at created_at updated_at task_completion_status
design_collection alert_management_alert severity current_user_todos moved moved_to
- create_note_email timelogs project_id customer_relations_contacts escalation_status]
+ closed_as_duplicate_of create_note_email timelogs project_id customer_relations_contacts escalation_status]
fields.each do |field_name|
expect(described_class).to have_graphql_field(field_name)
@@ -291,14 +291,6 @@ RSpec.describe GitlabSchema.types['Issue'] do
let!(:escalation_status) { create(:incident_management_issuable_escalation_status, issue: issue) }
it { is_expected.to eq(escalation_status.status_name.to_s.upcase) }
-
- context 'with feature disabled' do
- before do
- stub_feature_flags(incident_escalations: false)
- end
-
- it { is_expected.to be_nil }
- end
end
end
end
diff --git a/spec/graphql/types/limited_countable_connection_type_spec.rb b/spec/graphql/types/limited_countable_connection_type_spec.rb
new file mode 100644
index 00000000000..30af26cdb83
--- /dev/null
+++ b/spec/graphql/types/limited_countable_connection_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::LimitedCountableConnectionType do
+ it 'has the expected fields' do
+ expected_fields = %i[count page_info]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/packages/cleanup/keep_duplicated_package_files_enum_spec.rb b/spec/graphql/types/packages/cleanup/keep_duplicated_package_files_enum_spec.rb
new file mode 100644
index 00000000000..d7f24a9edfd
--- /dev/null
+++ b/spec/graphql/types/packages/cleanup/keep_duplicated_package_files_enum_spec.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackagesCleanupKeepDuplicatedPackageFilesEnum'] do
+ it 'exposes all options' do
+ expect(described_class.values.keys)
+ .to contain_exactly(*Types::Packages::Cleanup::KeepDuplicatedPackageFilesEnum::OPTIONS_MAPPING.values)
+ end
+
+ it 'uses all possible options from model' do
+ all_options = Packages::Cleanup::Policy::KEEP_N_DUPLICATED_PACKAGE_FILES_VALUES
+ expect(described_class::OPTIONS_MAPPING.keys).to contain_exactly(*all_options)
+ end
+end
diff --git a/spec/graphql/types/packages/cleanup/policy_type_spec.rb b/spec/graphql/types/packages/cleanup/policy_type_spec.rb
new file mode 100644
index 00000000000..f48651ed832
--- /dev/null
+++ b/spec/graphql/types/packages/cleanup/policy_type_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['PackagesCleanupPolicy'] do
+ specify { expect(described_class.graphql_name).to eq('PackagesCleanupPolicy') }
+
+ specify do
+ expect(described_class.description)
+ .to eq('A packages cleanup policy designed to keep only packages and packages assets that matter most')
+ end
+
+ specify { expect(described_class).to require_graphql_authorizations(:admin_package) }
+
+ describe 'keep_n_duplicated_package_files' do
+ subject { described_class.fields['keepNDuplicatedPackageFiles'] }
+
+ it { is_expected.to have_non_null_graphql_type(Types::Packages::Cleanup::KeepDuplicatedPackageFilesEnum) }
+ end
+
+ describe 'next_run_at' do
+ subject { described_class.fields['nextRunAt'] }
+
+ it { is_expected.to have_nullable_graphql_type(Types::TimeType) }
+ end
+end
diff --git a/spec/graphql/types/project_type_spec.rb b/spec/graphql/types/project_type_spec.rb
index a08bd717c72..2e994bf7820 100644
--- a/spec/graphql/types/project_type_spec.rb
+++ b/spec/graphql/types/project_type_spec.rb
@@ -36,12 +36,40 @@ RSpec.describe GitlabSchema.types['Project'] do
pipeline_analytics squash_read_only sast_ci_configuration
cluster_agent cluster_agents agent_configurations
ci_template timelogs merge_commit_template squash_commit_template work_item_types
- recent_issue_boards ci_config_path_or_default
+ recent_issue_boards ci_config_path_or_default packages_cleanup_policy
]
expect(described_class).to include_graphql_fields(*expected_fields)
end
+ describe 'count' do
+ let_it_be(:user) { create(:user) }
+
+ let(:query) do
+ %(
+ query {
+ projects {
+ count
+ edges {
+ node {
+ id
+ }
+ }
+ }
+ }
+ )
+ end
+
+ subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
+
+ it 'returns valid projects count' do
+ create(:project, namespace: user.namespace)
+ create(:project, namespace: user.namespace)
+
+ expect(subject.dig('data', 'projects', 'count')).to eq(2)
+ end
+ end
+
describe 'container_registry_enabled' do
let_it_be(:project, reload: true) { create(:project, :public) }
let_it_be(:user) { create(:user) }
@@ -393,6 +421,12 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::ContainerExpirationPolicyType) }
end
+ describe 'packages cleanup policy field' do
+ subject { described_class.fields['packagesCleanupPolicy'] }
+
+ it { is_expected.to have_graphql_type(Types::Packages::Cleanup::PolicyType) }
+ end
+
describe 'terraform state field' do
subject { described_class.fields['terraformState'] }
diff --git a/spec/graphql/types/terraform/state_type_spec.rb b/spec/graphql/types/terraform/state_type_spec.rb
index 9f65bb926d7..5098adbf45c 100644
--- a/spec/graphql/types/terraform/state_type_spec.rb
+++ b/spec/graphql/types/terraform/state_type_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class).to require_graphql_authorizations(:read_terraform_state) }
describe 'fields' do
- let(:fields) { %i[id name locked_by_user locked_at latest_version created_at updated_at] }
+ let(:fields) { %i[id name locked_by_user locked_at latest_version created_at updated_at deleted_at] }
it { expect(described_class).to have_graphql_fields(fields) }
@@ -17,6 +17,7 @@ RSpec.describe GitlabSchema.types['TerraformState'] do
it { expect(described_class.fields['lockedAt'].type).not_to be_non_null }
it { expect(described_class.fields['createdAt'].type).to be_non_null }
it { expect(described_class.fields['updatedAt'].type).to be_non_null }
+ it { expect(described_class.fields['deletedAt'].type).not_to be_non_null }
it { expect(described_class.fields['latestVersion'].type).not_to be_non_null }
it { expect(described_class.fields['latestVersion'].complexity).to eq(3) }
diff --git a/spec/graphql/types/time_type_spec.rb b/spec/graphql/types/time_type_spec.rb
index 3b0d257e1d7..367a2371694 100644
--- a/spec/graphql/types/time_type_spec.rb
+++ b/spec/graphql/types/time_type_spec.rb
@@ -21,8 +21,7 @@ RSpec.describe GitlabSchema.types['Time'] do
.to raise_error(GraphQL::CoercionError)
end
- it 'rejects nil' do
- expect { described_class.coerce_isolated_input(nil) }
- .to raise_error(GraphQL::CoercionError)
+ it 'allows nil' do
+ expect(described_class.coerce_isolated_input(nil)).to be_nil
end
end
diff --git a/spec/graphql/types/todo_type_spec.rb b/spec/graphql/types/todo_type_spec.rb
index 8de63ebfda5..c7bb7c67959 100644
--- a/spec/graphql/types/todo_type_spec.rb
+++ b/spec/graphql/types/todo_type_spec.rb
@@ -4,7 +4,19 @@ require 'spec_helper'
RSpec.describe GitlabSchema.types['Todo'] do
it 'has the correct fields' do
- expected_fields = [:id, :project, :group, :author, :action, :target, :target_type, :body, :state, :created_at]
+ expected_fields = [
+ :id,
+ :project,
+ :group,
+ :author,
+ :action,
+ :target,
+ :target_type,
+ :body,
+ :state,
+ :created_at,
+ :note
+ ]
expect(described_class).to have_graphql_fields(*expected_fields)
end
diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb
index c913a4c3662..fec6a771640 100644
--- a/spec/graphql/types/user_type_spec.rb
+++ b/spec/graphql/types/user_type_spec.rb
@@ -91,8 +91,8 @@ RSpec.describe GitlabSchema.types['User'] do
context 'when requester is nil' do
let(:current_user) { nil }
- it 'returns `****`' do
- expect(user_name).to eq('****')
+ it 'returns nothing' do
+ expect(user_name).to be_nil
end
end
@@ -134,8 +134,8 @@ RSpec.describe GitlabSchema.types['User'] do
context 'when requester is nil' do
let(:current_user) { nil }
- it 'returns `****`' do
- expect(user_name).to eq('****')
+ it 'returns nothing' do
+ expect(user_name).to be_nil
end
end
diff --git a/spec/graphql/types/work_item_type_spec.rb b/spec/graphql/types/work_item_type_spec.rb
index a0480506156..7ed58786b5b 100644
--- a/spec/graphql/types/work_item_type_spec.rb
+++ b/spec/graphql/types/work_item_type_spec.rb
@@ -10,7 +10,18 @@ RSpec.describe GitlabSchema.types['WorkItem'] do
specify { expect(described_class).to expose_permissions_using(Types::PermissionTypes::WorkItem) }
it 'has specific fields' do
- fields = %i[description description_html id iid lock_version state title title_html userPermissions work_item_type]
+ fields = %i[
+ description
+ description_html
+ id
+ iid
+ lock_version
+ state title
+ title_html
+ userPermissions
+ widgets
+ work_item_type
+ ]
fields.each do |field_name|
expect(described_class).to have_graphql_fields(*fields)
diff --git a/spec/graphql/types/work_items/widget_interface_spec.rb b/spec/graphql/types/work_items/widget_interface_spec.rb
new file mode 100644
index 00000000000..ee40bcc10ca
--- /dev/null
+++ b/spec/graphql/types/work_items/widget_interface_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::WidgetInterface do
+ include GraphqlHelpers
+
+ it 'exposes the expected fields' do
+ expected_fields = %i[type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+
+ describe ".resolve_type" 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
+ end
+
+ with_them do
+ it 'knows the correct type for objects' do
+ expect(
+ described_class.resolve_type(widget_class.new(build(:work_item)), {})
+ ).to eq(widget_type_name)
+ end
+ end
+
+ it 'raises an error for an unknown type' do
+ project = build(:project)
+
+ expect { described_class.resolve_type(project, {}) }
+ .to raise_error("Unknown GraphQL type for widget #{project}")
+ end
+ end
+end
diff --git a/spec/graphql/types/work_items/widget_type_enum_spec.rb b/spec/graphql/types/work_items/widget_type_enum_spec.rb
new file mode 100644
index 00000000000..e7ac9b9c317
--- /dev/null
+++ b/spec/graphql/types/work_items/widget_type_enum_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe GitlabSchema.types['WorkItemWidgetType'] do
+ specify { expect(described_class.graphql_name).to eq('WorkItemWidgetType') }
+
+ it 'exposes all the existing widget type values' do
+ expect(described_class.values.transform_values { |v| v.value }).to include(
+ 'DESCRIPTION' => :description
+ )
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/description_type_spec.rb b/spec/graphql/types/work_items/widgets/description_type_spec.rb
new file mode 100644
index 00000000000..5ade1fe4aa2
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/description_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::DescriptionType do
+ it 'exposes the expected fields' do
+ expected_fields = %i[description description_html type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end
diff --git a/spec/graphql/types/work_items/widgets/hierarchy_type_spec.rb b/spec/graphql/types/work_items/widgets/hierarchy_type_spec.rb
new file mode 100644
index 00000000000..1722a07c5f4
--- /dev/null
+++ b/spec/graphql/types/work_items/widgets/hierarchy_type_spec.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Types::WorkItems::Widgets::HierarchyType do
+ it 'exposes the expected fields' do
+ expected_fields = %i[parent children type]
+
+ expect(described_class).to have_graphql_fields(*expected_fields)
+ end
+end