debian-mirror-gitlab/spec/requests/api/graphql/work_item_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

339 lines
9.9 KiB
Ruby
Raw Normal View History

2022-05-07 20:08:51 +05:30
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'Query.work_item(id)' do
include GraphqlHelpers
let_it_be(:developer) { create(:user) }
2022-07-23 23:45:48 +05:30
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, :private) }
2022-08-27 11:52:29 +05:30
let_it_be(:work_item) do
create(
:work_item,
project: project,
description: '- List item',
start_date: Date.today,
2022-10-11 01:57:18 +05:30
due_date: 1.week.from_now,
created_at: 1.week.ago,
last_edited_at: 1.day.ago,
last_edited_by: guest
2022-08-27 11:52:29 +05:30
)
end
2022-07-23 23:45:48 +05:30
let_it_be(:child_item1) { create(:work_item, :task, project: project) }
let_it_be(:child_item2) { create(:work_item, :task, confidential: true, project: project) }
let_it_be(:child_link1) { create(:parent_link, work_item_parent: work_item, work_item: child_item1) }
let_it_be(:child_link2) { create(:parent_link, work_item_parent: work_item, work_item: child_item2) }
2022-05-07 20:08:51 +05:30
let(:current_user) { developer }
let(:work_item_data) { graphql_data['workItem'] }
2022-08-27 11:52:29 +05:30
let(:work_item_fields) { all_graphql_fields_for('WorkItem', max_depth: 2) }
2022-05-07 20:08:51 +05:30
let(:global_id) { work_item.to_gid.to_s }
let(:query) do
graphql_query_for('workItem', { 'id' => global_id }, work_item_fields)
end
context 'when the user can read the work item' do
before do
2022-07-23 23:45:48 +05:30
project.add_developer(developer)
project.add_guest(guest)
2022-05-07 20:08:51 +05:30
post_graphql(query, current_user: current_user)
end
it_behaves_like 'a working graphql query'
it 'returns all fields' do
expect(work_item_data).to include(
'description' => work_item.description,
'id' => work_item.to_gid.to_s,
'iid' => work_item.iid.to_s,
'lockVersion' => work_item.lock_version,
'state' => "OPEN",
'title' => work_item.title,
2022-08-27 11:52:29 +05:30
'confidential' => work_item.confidential,
2022-07-16 23:28:13 +05:30
'workItemType' => hash_including('id' => work_item.work_item_type.to_gid.to_s),
2022-08-27 11:52:29 +05:30
'userPermissions' => { 'readWorkItem' => true, 'updateWorkItem' => true, 'deleteWorkItem' => false },
'project' => hash_including('id' => project.to_gid.to_s, 'fullPath' => project.full_path)
2022-05-07 20:08:51 +05:30
)
end
2022-07-23 23:45:48 +05:30
context 'when querying widgets' do
describe 'description widget' do
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
... on WorkItemWidgetDescription {
description
descriptionHtml
2022-10-11 01:57:18 +05:30
edited
lastEditedBy {
webPath
username
}
lastEditedAt
2022-07-23 23:45:48 +05:30
}
}
GRAPHQL
end
it 'returns widget information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
2022-08-13 15:12:31 +05:30
'widgets' => include(
2022-07-23 23:45:48 +05:30
hash_including(
'type' => 'DESCRIPTION',
'description' => work_item.description,
2022-10-11 01:57:18 +05:30
'descriptionHtml' => ::MarkupHelper.markdown_field(work_item, :description, {}),
'edited' => true,
'lastEditedAt' => work_item.last_edited_at.iso8601,
'lastEditedBy' => {
'webPath' => "/#{guest.full_path}",
'username' => guest.username
}
2022-07-23 23:45:48 +05:30
)
2022-08-13 15:12:31 +05:30
)
2022-07-23 23:45:48 +05:30
)
end
end
describe 'hierarchy widget' do
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
... on WorkItemWidgetHierarchy {
parent {
id
}
children {
nodes {
id
}
}
}
}
GRAPHQL
end
it 'returns widget information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
2022-08-13 15:12:31 +05:30
'widgets' => include(
2022-07-23 23:45:48 +05:30
hash_including(
'type' => 'HIERARCHY',
'parent' => nil,
2022-11-25 23:54:43 +05:30
'children' => { 'nodes' => match_array(
[
hash_including('id' => child_link1.work_item.to_gid.to_s),
hash_including('id' => child_link2.work_item.to_gid.to_s)
]) }
2022-07-23 23:45:48 +05:30
)
2022-08-13 15:12:31 +05:30
)
2022-07-23 23:45:48 +05:30
)
end
it 'avoids N+1 queries' do
post_graphql(query, current_user: current_user) # warm up
control_count = ActiveRecord::QueryRecorder.new(skip_cached: false) do
post_graphql(query, current_user: current_user)
end
create_list(:parent_link, 3, work_item_parent: work_item)
expect do
post_graphql(query, current_user: current_user)
end.not_to exceed_all_query_limit(control_count)
end
context 'when user is guest' do
let(:current_user) { guest }
it 'filters out not accessible children or parent' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
2022-08-13 15:12:31 +05:30
'widgets' => include(
2022-07-23 23:45:48 +05:30
hash_including(
'type' => 'HIERARCHY',
'parent' => nil,
2022-11-25 23:54:43 +05:30
'children' => { 'nodes' => match_array(
[
hash_including('id' => child_link1.work_item.to_gid.to_s)
]) }
2022-07-23 23:45:48 +05:30
)
2022-08-13 15:12:31 +05:30
)
2022-07-23 23:45:48 +05:30
)
end
end
context 'when requesting child item' do
let_it_be(:work_item) { create(:work_item, :task, project: project, description: '- List item') }
let_it_be(:parent_link) { create(:parent_link, work_item: work_item) }
it 'returns parent information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
2022-08-13 15:12:31 +05:30
'widgets' => include(
2022-07-23 23:45:48 +05:30
hash_including(
'type' => 'HIERARCHY',
'parent' => hash_including('id' => parent_link.work_item_parent.to_gid.to_s),
'children' => { 'nodes' => match_array([]) }
)
2022-08-13 15:12:31 +05:30
)
2022-07-23 23:45:48 +05:30
)
end
end
end
2022-08-13 15:12:31 +05:30
2022-08-27 11:52:29 +05:30
describe 'assignees widget' do
let(:assignees) { create_list(:user, 2) }
let(:work_item) { create(:work_item, project: project, assignees: assignees) }
2022-08-13 15:12:31 +05:30
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
2022-08-27 11:52:29 +05:30
... on WorkItemWidgetAssignees {
allowsMultipleAssignees
canInviteMembers
assignees {
nodes {
id
username
}
}
2022-08-13 15:12:31 +05:30
}
}
GRAPHQL
end
it 'returns widget information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
'widgets' => include(
hash_including(
2022-08-27 11:52:29 +05:30
'type' => 'ASSIGNEES',
'allowsMultipleAssignees' => boolean,
'canInviteMembers' => boolean,
'assignees' => {
'nodes' => match_array(
assignees.map { |a| { 'id' => a.to_gid.to_s, 'username' => a.username } }
)
}
2022-08-13 15:12:31 +05:30
)
)
)
end
end
2022-08-27 11:52:29 +05:30
describe 'labels widget' do
let(:labels) { create_list(:label, 2, project: project) }
let(:work_item) { create(:work_item, project: project, labels: labels) }
2022-08-13 15:12:31 +05:30
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
2022-08-27 11:52:29 +05:30
... on WorkItemWidgetLabels {
labels {
2022-08-13 15:12:31 +05:30
nodes {
id
2022-08-27 11:52:29 +05:30
title
2022-08-13 15:12:31 +05:30
}
}
}
}
GRAPHQL
end
it 'returns widget information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
'widgets' => include(
hash_including(
2022-08-27 11:52:29 +05:30
'type' => 'LABELS',
'labels' => {
2022-08-13 15:12:31 +05:30
'nodes' => match_array(
2022-08-27 11:52:29 +05:30
labels.map { |a| { 'id' => a.to_gid.to_s, 'title' => a.title } }
2022-08-13 15:12:31 +05:30
)
}
)
)
)
end
end
2022-08-27 11:52:29 +05:30
describe 'start and due date widget' do
let(:work_item_fields) do
<<~GRAPHQL
id
widgets {
type
... on WorkItemWidgetStartAndDueDate {
startDate
dueDate
}
}
GRAPHQL
end
it 'returns widget information' do
expect(work_item_data).to include(
'id' => work_item.to_gid.to_s,
'widgets' => include(
hash_including(
'type' => 'START_AND_DUE_DATE',
'startDate' => work_item.start_date.to_s,
'dueDate' => work_item.due_date.to_s
)
)
)
end
end
2022-07-23 23:45:48 +05:30
end
2022-05-07 20:08:51 +05:30
context 'when an Issue Global ID is provided' do
let(:global_id) { Issue.find(work_item.id).to_gid.to_s }
it 'allows an Issue GID as input' do
expect(work_item_data).to include('id' => work_item.to_gid.to_s)
end
end
end
context 'when the user can not read the work item' do
let(:current_user) { create(:user) }
before do
post_graphql(query)
end
it 'returns an access error' do
expect(work_item_data).to be_nil
expect(graphql_errors).to contain_exactly(
hash_including('message' => ::Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
)
end
end
context 'when the work_items feature flag is disabled' do
before do
stub_feature_flags(work_items: false)
end
it 'returns nil' do
post_graphql(query)
expect(work_item_data).to be_nil
end
end
end