Add latest changes from gitlab-org/gitlab@15-4-stable-ee
This commit is contained in:
parent
ef309cf146
commit
6dce4e9bb1
|
|
@ -102,7 +102,8 @@
|
|||
"Epic",
|
||||
"EpicIssue",
|
||||
"Issue",
|
||||
"MergeRequest"
|
||||
"MergeRequest",
|
||||
"WorkItem"
|
||||
],
|
||||
"User": [
|
||||
"MergeRequestAssignee",
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ module Resolvers
|
|||
|
||||
def preloads
|
||||
{
|
||||
last_edited_by: :last_edited_by
|
||||
last_edited_by: :last_edited_by,
|
||||
web_url: { project: { namespace: :route } }
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ module Types
|
|||
class TodoTargetEnum < BaseEnum
|
||||
value 'COMMIT', value: 'Commit', description: 'Commit.'
|
||||
value 'ISSUE', value: 'Issue', description: 'Issue.'
|
||||
value 'WORKITEM', value: 'WorkItem', description: 'Work item.'
|
||||
value 'MERGEREQUEST', value: 'MergeRequest', description: 'Merge request.'
|
||||
value 'DESIGN', value: 'DesignManagement::Design', description: 'Design.'
|
||||
value 'ALERT', value: 'AlertManagement::Alert', description: 'Alert.'
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ module Types
|
|||
|
||||
def self.resolve_type(object, context)
|
||||
case object
|
||||
when WorkItem
|
||||
Types::WorkItemType
|
||||
when Issue
|
||||
Types::IssueType
|
||||
when MergeRequest
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ module Types
|
|||
class WorkItemType < BaseObject
|
||||
graphql_name 'WorkItem'
|
||||
|
||||
implements(Types::TodoableInterface)
|
||||
|
||||
authorize :read_work_item
|
||||
|
||||
field :closed_at, Types::TimeType, null: true,
|
||||
|
|
@ -42,5 +44,9 @@ module Types
|
|||
markdown_field :description_html, null: true
|
||||
|
||||
expose_permissions Types::PermissionTypes::WorkItem
|
||||
|
||||
def web_url
|
||||
Gitlab::UrlBuilder.build(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19338,6 +19338,7 @@ Represents vulnerability letter grades with associated projects.
|
|||
| <a id="workitemtitlehtml"></a>`titleHtml` | [`String`](#string) | The GitLab Flavored Markdown rendering of `title`. |
|
||||
| <a id="workitemupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the work item was last updated. |
|
||||
| <a id="workitemuserpermissions"></a>`userPermissions` | [`WorkItemPermissions!`](#workitempermissions) | Permissions for the current user on the resource. |
|
||||
| <a id="workitemweburl"></a>`webUrl` | [`String`](#string) | URL of this object. |
|
||||
| <a id="workitemwidgets"></a>`widgets` | [`[WorkItemWidget!]`](#workitemwidget) | Collection of widgets that belong to the work item. |
|
||||
| <a id="workitemworkitemtype"></a>`workItemType` | [`WorkItemType!`](#workitemtype) | Type assigned to the work item. |
|
||||
|
||||
|
|
@ -21167,6 +21168,7 @@ Category of error.
|
|||
| <a id="todotargetenumepic"></a>`EPIC` | An Epic. |
|
||||
| <a id="todotargetenumissue"></a>`ISSUE` | Issue. |
|
||||
| <a id="todotargetenummergerequest"></a>`MERGEREQUEST` | Merge request. |
|
||||
| <a id="todotargetenumworkitem"></a>`WORKITEM` | Work item. |
|
||||
|
||||
### `TrainingUrlRequestStatus`
|
||||
|
||||
|
|
@ -22457,6 +22459,7 @@ Implementations:
|
|||
- [`EpicIssue`](#epicissue)
|
||||
- [`Issue`](#issue)
|
||||
- [`MergeRequest`](#mergerequest)
|
||||
- [`WorkItem`](#workitem)
|
||||
|
||||
##### Fields
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module API
|
||||
module Entities
|
||||
class WorkItem < Issue
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -26,6 +26,7 @@ RSpec.describe GitlabSchema.types['WorkItem'] do
|
|||
created_at
|
||||
updated_at
|
||||
closed_at
|
||||
web_url
|
||||
]
|
||||
|
||||
expect(described_class).to have_graphql_fields(*fields)
|
||||
|
|
|
|||
|
|
@ -11,23 +11,31 @@ RSpec.describe 'Todo Query' do
|
|||
|
||||
let_it_be(:todo_owner) { create(:user) }
|
||||
|
||||
let_it_be(:todo) { create(:todo, user: todo_owner, target: project) }
|
||||
let_it_be(:todo) { create(:todo, user: todo_owner, target: issue) }
|
||||
|
||||
let(:todo_subject) { todo }
|
||||
let(:fields) do
|
||||
<<~GRAPHQL
|
||||
id
|
||||
targetType
|
||||
target {
|
||||
webUrl
|
||||
... on WorkItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
GRAPHQL
|
||||
end
|
||||
|
||||
let(:query) do
|
||||
graphql_query_for(:todo, { id: todo_subject.to_global_id.to_s }, fields)
|
||||
end
|
||||
|
||||
before do
|
||||
project.add_developer(todo_owner)
|
||||
end
|
||||
|
||||
let(:fields) do
|
||||
<<~GRAPHQL
|
||||
id
|
||||
GRAPHQL
|
||||
end
|
||||
|
||||
let(:query) do
|
||||
graphql_query_for(:todo, { id: todo.to_global_id.to_s }, fields)
|
||||
end
|
||||
|
||||
subject do
|
||||
subject(:graphql_response) do
|
||||
result = GitlabSchema.execute(query, context: { current_user: current_user }).to_h
|
||||
graphql_dig_at(result, :data, :todo)
|
||||
end
|
||||
|
|
@ -35,7 +43,23 @@ RSpec.describe 'Todo Query' do
|
|||
context 'when requesting user is todo owner' do
|
||||
let(:current_user) { todo_owner }
|
||||
|
||||
it { is_expected.to include('id' => todo.to_global_id.to_s) }
|
||||
it { is_expected.to include('id' => todo_subject.to_global_id.to_s) }
|
||||
|
||||
context 'when todo target is WorkItem' do
|
||||
let(:work_item) { create(:work_item, :task, project: project) }
|
||||
let(:todo_subject) { create(:todo, user: todo_owner, target: work_item, target_type: WorkItem.name) }
|
||||
|
||||
it 'works with a WorkItem target' do
|
||||
expect(graphql_response).to include(
|
||||
'id' => todo_subject.to_gid.to_s,
|
||||
'targetType' => 'WORKITEM',
|
||||
'target' => {
|
||||
'id' => work_item.to_gid.to_s,
|
||||
'webUrl' => Gitlab::UrlBuilder.build(work_item)
|
||||
}
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when requesting user is not todo owner' do
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ RSpec.describe API::Todos do
|
|||
let_it_be(:author_2) { create(:user) }
|
||||
let_it_be(:john_doe) { create(:user, username: 'john_doe') }
|
||||
let_it_be(:issue) { create(:issue, project: project_1) }
|
||||
let_it_be(:work_item) { create(:work_item, :task, project: project_1) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project_1) }
|
||||
let_it_be(:alert) { create(:alert_management_alert, project: project_1) }
|
||||
let_it_be(:alert_todo) { create(:todo, project: project_1, author: john_doe, user: john_doe, target: alert) }
|
||||
|
|
@ -20,6 +21,7 @@ RSpec.describe API::Todos do
|
|||
let_it_be(:pending_2) { create(:todo, project: project_2, author: author_2, user: john_doe, target: issue) }
|
||||
let_it_be(:pending_3) { create(:on_commit_todo, project: project_1, author: author_2, user: john_doe) }
|
||||
let_it_be(:pending_4) { create(:on_commit_todo, project: project_1, author: author_2, user: john_doe, commit_id: 'invalid_id') }
|
||||
let_it_be(:pending_5) { create(:todo, :mentioned, project: project_1, author: author_1, user: john_doe, target: work_item, target_type: WorkItem.name) }
|
||||
let_it_be(:done) { create(:todo, :done, project: project_1, author: author_1, user: john_doe, target: issue) }
|
||||
let_it_be(:award_emoji_1) { create(:award_emoji, awardable: merge_request, user: author_1, name: 'thumbsup') }
|
||||
let_it_be(:award_emoji_2) { create(:award_emoji, awardable: pending_1.target, user: author_1, name: 'thumbsup') }
|
||||
|
|
@ -69,38 +71,62 @@ RSpec.describe API::Todos do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(5)
|
||||
expect(json_response[0]['id']).to eq(pending_3.id)
|
||||
expect(json_response[0]['project']).to be_a Hash
|
||||
expect(json_response[0]['author']).to be_a Hash
|
||||
expect(json_response[0]['target_type']).to be_present
|
||||
expect(json_response[0]['target']).to be_a Hash
|
||||
expect(json_response[0]['target_url']).to be_present
|
||||
expect(json_response[0]['body']).to be_present
|
||||
expect(json_response[0]['state']).to eq('pending')
|
||||
expect(json_response[0]['action_name']).to eq('assigned')
|
||||
expect(json_response[0]['created_at']).to be_present
|
||||
expect(json_response[0]['target_type']).to eq('Commit')
|
||||
expect(json_response.length).to eq(6)
|
||||
|
||||
expect(json_response[1]['target_type']).to eq('Issue')
|
||||
expect(json_response[1]['target']['upvotes']).to eq(1)
|
||||
expect(json_response[1]['target']['downvotes']).to eq(1)
|
||||
expect(json_response[1]['target']['merge_requests_count']).to eq(0)
|
||||
expect(json_response[0]).to include(
|
||||
'id' => pending_5.id,
|
||||
'target_type' => 'WorkItem',
|
||||
'target' => hash_including('type' => 'TASK')
|
||||
)
|
||||
|
||||
expect(json_response[2]['target_type']).to eq('Issue')
|
||||
expect(json_response[2]['target']['upvotes']).to eq(1)
|
||||
expect(json_response[2]['target']['downvotes']).to eq(1)
|
||||
expect(json_response[2]['target']['merge_requests_count']).to eq(0)
|
||||
expect(json_response[1]).to include(
|
||||
'id' => pending_3.id,
|
||||
'project' => instance_of(Hash),
|
||||
'author' => instance_of(Hash),
|
||||
'target' => instance_of(Hash),
|
||||
'state' => 'pending',
|
||||
'action_name' => 'assigned',
|
||||
'target_type' => 'Commit',
|
||||
'target_url' => be_present,
|
||||
'body' => be_present,
|
||||
'created_at' => be_present
|
||||
)
|
||||
|
||||
expect(json_response[2]).to include(
|
||||
'target_type' => 'Issue',
|
||||
'target' => hash_including(
|
||||
'upvotes' => 1,
|
||||
'downvotes' => 1,
|
||||
'merge_requests_count' => 0
|
||||
)
|
||||
)
|
||||
|
||||
expect(json_response[3]).to include(
|
||||
'target_type' => 'Issue',
|
||||
'target' => hash_including(
|
||||
'upvotes' => 1,
|
||||
'downvotes' => 1,
|
||||
'merge_requests_count' => 0
|
||||
)
|
||||
)
|
||||
|
||||
expect(json_response[3]['target_type']).to eq('MergeRequest')
|
||||
# Only issues get a merge request count at the moment
|
||||
expect(json_response[3]['target']['merge_requests_count']).to be_nil
|
||||
expect(json_response[3]['target']['upvotes']).to eq(1)
|
||||
expect(json_response[3]['target']['downvotes']).to eq(0)
|
||||
expect(json_response[4].dig('target', 'merge_requests_count')).to be_nil
|
||||
expect(json_response[4]).to include(
|
||||
'target_type' => 'MergeRequest',
|
||||
'target' => hash_including(
|
||||
'upvotes' => 1,
|
||||
'downvotes' => 0
|
||||
)
|
||||
)
|
||||
|
||||
expect(json_response[4]['target_type']).to eq('AlertManagement::Alert')
|
||||
expect(json_response[4]['target']['iid']).to eq(alert.iid)
|
||||
expect(json_response[4]['target']['title']).to eq(alert.title)
|
||||
expect(json_response[5]).to include(
|
||||
'target_type' => 'AlertManagement::Alert',
|
||||
'target' => hash_including(
|
||||
'iid' => alert.iid,
|
||||
'title' => alert.title
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
context "when current user does not have access to one of the TODO's target" do
|
||||
|
|
@ -111,7 +137,7 @@ RSpec.describe API::Todos do
|
|||
|
||||
get api('/todos', john_doe)
|
||||
|
||||
expect(json_response.count).to eq(5)
|
||||
expect(json_response.count).to eq(6)
|
||||
expect(json_response.map { |t| t['id'] }).not_to include(no_access_todo.id, pending_4.id)
|
||||
end
|
||||
end
|
||||
|
|
@ -169,7 +195,7 @@ RSpec.describe API::Todos do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(4)
|
||||
expect(json_response.length).to eq(5)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -180,7 +206,7 @@ RSpec.describe API::Todos do
|
|||
expect(response).to have_gitlab_http_status(:ok)
|
||||
expect(response).to include_pagination_headers
|
||||
expect(json_response).to be_an Array
|
||||
expect(json_response.length).to eq(1)
|
||||
expect(json_response.length).to eq(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -189,6 +215,10 @@ RSpec.describe API::Todos do
|
|||
create_issue_todo_for(john_doe)
|
||||
create(:todo, project: project_1, author: author_2, user: john_doe, target: merge_request)
|
||||
|
||||
# Destroying to preserve behavior prior to fixing todo's target as WorkItem
|
||||
# TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/375293 remove when N + 1 are fixed
|
||||
pending_5.destroy!
|
||||
|
||||
get api('/todos', john_doe)
|
||||
|
||||
control1 = ActiveRecord::QueryRecorder.new { get api('/todos', john_doe) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue