Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
951ab3a6
Commit
951ab3a6
authored
Apr 12, 2021
by
Lee Tickett
Committed by
Rémy Coutable
Apr 12, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Expose timelogs against issues and merge requests in graphql
parent
f95046ba
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
140 additions
and
79 deletions
+140
-79
app/graphql/resolvers/concerns/resolves_merge_requests.rb
app/graphql/resolvers/concerns/resolves_merge_requests.rb
+2
-1
app/graphql/resolvers/issues_resolver.rb
app/graphql/resolvers/issues_resolver.rb
+2
-1
app/graphql/types/issue_type.rb
app/graphql/types/issue_type.rb
+3
-0
app/graphql/types/merge_request_type.rb
app/graphql/types/merge_request_type.rb
+2
-0
app/models/concerns/has_timelogs_report.rb
app/models/concerns/has_timelogs_report.rb
+2
-1
changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml
.../unreleased/graphql-expose-timelogs-against-issuables.yml
+5
-0
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+3
-0
spec/factories/timelogs.rb
spec/factories/timelogs.rb
+15
-4
spec/graphql/resolvers/timelog_resolver_spec.rb
spec/graphql/resolvers/timelog_resolver_spec.rb
+32
-25
spec/graphql/types/issue_type_spec.rb
spec/graphql/types/issue_type_spec.rb
+1
-1
spec/models/concerns/has_timelogs_report_spec.rb
spec/models/concerns/has_timelogs_report_spec.rb
+3
-5
spec/models/timelog_spec.rb
spec/models/timelog_spec.rb
+6
-6
spec/requests/api/graphql/group/timelogs_spec.rb
spec/requests/api/graphql/group/timelogs_spec.rb
+9
-10
spec/requests/api/graphql/project/issues_spec.rb
spec/requests/api/graphql/project/issues_spec.rb
+49
-22
spec/requests/api/graphql/project/merge_requests_spec.rb
spec/requests/api/graphql/project/merge_requests_spec.rb
+6
-3
No files found.
app/graphql/resolvers/concerns/resolves_merge_requests.rb
View file @
951ab3a6
...
@@ -50,7 +50,8 @@ module ResolvesMergeRequests
...
@@ -50,7 +50,8 @@ module ResolvesMergeRequests
approved_by:
[
:approved_by_users
],
approved_by:
[
:approved_by_users
],
milestone:
[
:milestone
],
milestone:
[
:milestone
],
security_auto_fix:
[
:author
],
security_auto_fix:
[
:author
],
head_pipeline:
[
:merge_request_diff
,
{
head_pipeline:
[
:merge_request
]
}]
head_pipeline:
[
:merge_request_diff
,
{
head_pipeline:
[
:merge_request
]
}],
timelogs:
[
:timelogs
]
}
}
end
end
end
end
app/graphql/resolvers/issues_resolver.rb
View file @
951ab3a6
...
@@ -44,7 +44,8 @@ module Resolvers
...
@@ -44,7 +44,8 @@ module Resolvers
{
{
alert_management_alert:
[
:alert_management_alert
],
alert_management_alert:
[
:alert_management_alert
],
labels:
[
:labels
],
labels:
[
:labels
],
assignees:
[
:assignees
]
assignees:
[
:assignees
],
timelogs:
[
:timelogs
]
}
}
end
end
...
...
app/graphql/types/issue_type.rb
View file @
951ab3a6
...
@@ -124,6 +124,9 @@ module Types
...
@@ -124,6 +124,9 @@ module Types
field
:create_note_email
,
GraphQL
::
STRING_TYPE
,
null:
true
,
field
:create_note_email
,
GraphQL
::
STRING_TYPE
,
null:
true
,
description:
'User specific email address for the issue.'
description:
'User specific email address for the issue.'
field
:timelogs
,
Types
::
TimelogType
.
connection_type
,
null:
false
,
description:
'Timelogs on the issue.'
def
author
def
author
Gitlab
::
Graphql
::
Loaders
::
BatchModelLoader
.
new
(
User
,
object
.
author_id
).
find
Gitlab
::
Graphql
::
Loaders
::
BatchModelLoader
.
new
(
User
,
object
.
author_id
).
find
end
end
...
...
app/graphql/types/merge_request_type.rb
View file @
951ab3a6
...
@@ -186,6 +186,8 @@ module Types
...
@@ -186,6 +186,8 @@ module Types
description:
'Selected auto merge strategy.'
description:
'Selected auto merge strategy.'
field
:merge_user
,
Types
::
UserType
,
null:
true
,
field
:merge_user
,
Types
::
UserType
,
null:
true
,
description:
'User who merged this merge request.'
description:
'User who merged this merge request.'
field
:timelogs
,
Types
::
TimelogType
.
connection_type
,
null:
false
,
description:
'Timelogs on the merge request.'
def
approved_by
def
approved_by
object
.
approved_by_users
object
.
approved_by_users
...
...
app/models/concerns/has_timelogs_report.rb
View file @
951ab3a6
...
@@ -2,9 +2,10 @@
...
@@ -2,9 +2,10 @@
module
HasTimelogsReport
module
HasTimelogsReport
extend
ActiveSupport
::
Concern
extend
ActiveSupport
::
Concern
include
Gitlab
::
Utils
::
StrongMemoize
def
timelogs
(
start_time
,
end_time
)
def
timelogs
(
start_time
,
end_time
)
@timelogs
||=
timelogs_for
(
start_time
,
end_time
)
strong_memoize
(
:timelogs
)
{
timelogs_for
(
start_time
,
end_time
)
}
end
end
def
user_can_access_group_timelogs?
(
current_user
)
def
user_can_access_group_timelogs?
(
current_user
)
...
...
changelogs/unreleased/graphql-expose-timelogs-against-issuables.yml
0 → 100644
View file @
951ab3a6
---
title
:
Expose timelogs against issues and merge requests in GraphQL
merge_request
:
57321
author
:
Lee Tickett @leetickett
type
:
added
doc/api/graphql/reference/index.md
View file @
951ab3a6
...
@@ -2905,6 +2905,7 @@ Relationship between an epic and an issue.
...
@@ -2905,6 +2905,7 @@ Relationship between an epic and an issue.
|
`subscribed`
|
[
`Boolean!`
](
#boolean
)
| Indicates the currently logged in user is subscribed to the issue. |
|
`subscribed`
|
[
`Boolean!`
](
#boolean
)
| Indicates the currently logged in user is subscribed to the issue. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Task completion status of the issue. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Task completion status of the issue. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the issue. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the issue. |
|
`timelogs`
|
[
`TimelogConnection!`
](
#timelogconnection
)
| Timelogs on the issue. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the issue. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the issue. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the issue. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the issue. |
...
@@ -3468,6 +3469,7 @@ An edge in a connection.
...
@@ -3468,6 +3469,7 @@ An edge in a connection.
|
`subscribed`
|
[
`Boolean!`
](
#boolean
)
| Indicates the currently logged in user is subscribed to the issue. |
|
`subscribed`
|
[
`Boolean!`
](
#boolean
)
| Indicates the currently logged in user is subscribed to the issue. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Task completion status of the issue. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Task completion status of the issue. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the issue. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the issue. |
|
`timelogs`
|
[
`TimelogConnection!`
](
#timelogconnection
)
| Timelogs on the issue. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the issue. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the issue. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the issue. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the issue. |
...
@@ -3980,6 +3982,7 @@ An edge in a connection.
...
@@ -3980,6 +3982,7 @@ An edge in a connection.
|
`targetProjectId`
|
[
`Int!`
](
#int
)
| ID of the merge request target project. |
|
`targetProjectId`
|
[
`Int!`
](
#int
)
| ID of the merge request target project. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Completion status of tasks. |
|
`taskCompletionStatus`
|
[
`TaskCompletionStatus!`
](
#taskcompletionstatus
)
| Completion status of tasks. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the merge request. |
|
`timeEstimate`
|
[
`Int!`
](
#int
)
| Time estimate of the merge request. |
|
`timelogs`
|
[
`TimelogConnection!`
](
#timelogconnection
)
| Timelogs on the merge request. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the merge request. |
|
`title`
|
[
`String!`
](
#string
)
| Title of the merge request. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`titleHtml`
|
[
`String`
](
#string
)
| The GitLab Flavored Markdown rendering of
`title`
. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the merge request. |
|
`totalTimeSpent`
|
[
`Int!`
](
#int
)
| Total time reported as spent on the merge request. |
...
...
spec/factories/timelogs.rb
View file @
951ab3a6
# frozen_string_literal: true
# frozen_string_literal: true
# Read about factories at https://github.com/thoughtbot/factory_bot
FactoryBot
.
define
do
FactoryBot
.
define
do
factory
:timelog
do
factory
:timelog
do
time_spent
{
3600
}
time_spent
{
3600
}
issue
for_issue
user
{
issue
.
project
.
creator
}
factory
:issue_timelog
,
traits:
[
:for_issue
]
factory
:merge_request_timelog
,
traits:
[
:for_merge_request
]
trait
:for_issue
do
issue
user
{
issue
.
author
}
end
trait
:for_merge_request
do
merge_request
issue
{
nil
}
user
{
merge_request
.
author
}
end
end
end
end
end
spec/graphql/resolvers/timelog_resolver_spec.rb
View file @
951ab3a6
...
@@ -9,51 +9,57 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -9,51 +9,57 @@ RSpec.describe Resolvers::TimelogResolver do
expect
(
described_class
).
to
have_non_null_graphql_type
(
::
Types
::
TimelogType
.
connection_type
)
expect
(
described_class
).
to
have_non_null_graphql_type
(
::
Types
::
TimelogType
.
connection_type
)
end
end
context
"with
in
a group"
do
context
"with a group"
do
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let
(
:group
)
{
create
(
:group
)
}
let
_it_be
(
:group
)
{
create
(
:group
)
}
let
(
:project
)
{
create
(
:project
,
:public
,
group:
group
)
}
let
_it_be
(
:project
)
{
create
(
:project
,
:public
,
group:
group
)
}
before
do
before
_all
do
group
.
add_developer
(
current_user
)
group
.
add_developer
(
current_user
)
project
.
add_developer
(
current_user
)
project
.
add_developer
(
current_user
)
end
end
before
do
group
.
clear_memoization
(
:timelogs
)
end
describe
'#resolve'
do
describe
'#resolve'
do
let
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let_it_be
(
:issue
)
{
create
(
:issue
,
project:
project
)
}
let
(
:issue2
)
{
create
(
:issue
,
project:
project
)
}
let_it_be
(
:issue2
)
{
create
(
:issue
,
project:
project
)
}
let_it_be
(
:timelog1
)
{
create
(
:issue_timelog
,
issue:
issue
,
spent_at:
2
.
days
.
ago
.
beginning_of_day
)
}
let_it_be
(
:timelog2
)
{
create
(
:issue_timelog
,
issue:
issue2
,
spent_at:
2
.
days
.
ago
.
end_of_day
)
}
let_it_be
(
:timelog3
)
{
create
(
:issue_timelog
,
issue:
issue2
,
spent_at:
10
.
days
.
ago
)
}
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
end_time:
2
.
days
.
ago
.
noon
}
}
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
end_time:
2
.
days
.
ago
.
noon
}
}
let!
(
:timelog1
)
{
create
(
:timelog
,
issue:
issue
,
spent_at:
2
.
days
.
ago
.
beginning_of_day
)
}
let!
(
:timelog2
)
{
create
(
:timelog
,
issue:
issue2
,
spent_at:
2
.
days
.
ago
.
end_of_day
)
}
let!
(
:timelog3
)
{
create
(
:timelog
,
issue:
issue2
,
spent_at:
10
.
days
.
ago
)
}
it
'finds all timelogs within given dates'
do
it
'finds all timelogs within given dates'
do
timelogs
=
resolve_timelogs
(
args
)
timelogs
=
resolve_timelogs
(
**
args
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
)
end
end
it
'return nothing when user has insufficient permissions'
do
it
'return nothing when user has insufficient permissions'
do
user
=
create
(
:user
)
group
.
add_guest
(
current_user
)
group
.
add_guest
(
current_user
)
expect
(
resolve_timelogs
(
args
)).
to
be_empty
expect
(
resolve_timelogs
(
user:
user
,
**
args
)).
to
be_empty
end
end
context
'when start_time and end_date are present'
do
context
'when start_time and end_date are present'
do
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
end_date:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
end_date:
2
.
days
.
ago
}
}
it
'finds timelogs until the end of day of end_date'
do
it
'finds timelogs until the end of day of end_date'
do
timelogs
=
resolve_timelogs
(
args
)
timelogs
=
resolve_timelogs
(
**
args
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
,
timelog2
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
,
timelog2
)
end
end
end
end
context
'
finds timelogs until the time specified on end_time
'
do
context
'
when start_date and end_time are present
'
do
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
,
end_time:
2
.
days
.
ago
.
noon
}
}
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
,
end_time:
2
.
days
.
ago
.
noon
}
}
it
'finds all timelogs within start_date and end_time'
do
it
'finds all timelogs within start_date and end_time'
do
timelogs
=
resolve_timelogs
(
args
)
timelogs
=
resolve_timelogs
(
**
args
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
)
end
end
...
@@ -66,7 +72,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -66,7 +72,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{}
}
let
(
:args
)
{
{}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Start and End arguments must be present/
)
end
end
end
end
...
@@ -75,7 +81,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -75,7 +81,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
}
}
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -84,7 +90,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -84,7 +90,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
end_time:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
end_time:
2
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -93,7 +99,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -93,7 +99,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
}
}
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -102,7 +108,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -102,7 +108,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
end_date:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
end_date:
2
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -111,7 +117,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -111,7 +117,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
start_date:
6
.
days
.
ago
}
}
let
(
:args
)
{
{
start_time:
6
.
days
.
ago
,
start_date:
6
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -120,7 +126,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -120,7 +126,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
end_time:
2
.
days
.
ago
,
end_date:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
end_time:
2
.
days
.
ago
,
end_date:
2
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
.
to
raise_error
(
error_class
,
/Both Start and End arguments must be present/
)
end
end
end
end
...
@@ -129,7 +135,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -129,7 +135,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
,
end_date:
2
.
days
.
ago
,
end_time:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
start_date:
6
.
days
.
ago
,
end_date:
2
.
days
.
ago
,
end_time:
2
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Only Time or Date arguments must be present/
)
.
to
raise_error
(
error_class
,
/Only Time or Date arguments must be present/
)
end
end
end
end
...
@@ -138,7 +144,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -138,7 +144,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_time:
2
.
days
.
ago
,
end_time:
6
.
days
.
ago
}
}
let
(
:args
)
{
{
start_time:
2
.
days
.
ago
,
end_time:
6
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/Start argument must be before End argument/
)
.
to
raise_error
(
error_class
,
/Start argument must be before End argument/
)
end
end
end
end
...
@@ -147,7 +153,7 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -147,7 +153,7 @@ RSpec.describe Resolvers::TimelogResolver do
let
(
:args
)
{
{
start_time:
3
.
months
.
ago
,
end_time:
2
.
days
.
ago
}
}
let
(
:args
)
{
{
start_time:
3
.
months
.
ago
,
end_time:
2
.
days
.
ago
}
}
it
'returns correct error'
do
it
'returns correct error'
do
expect
{
resolve_timelogs
(
args
)
}
expect
{
resolve_timelogs
(
**
args
)
}
.
to
raise_error
(
error_class
,
/The time range period cannot contain more than 60 days/
)
.
to
raise_error
(
error_class
,
/The time range period cannot contain more than 60 days/
)
end
end
end
end
...
@@ -155,7 +161,8 @@ RSpec.describe Resolvers::TimelogResolver do
...
@@ -155,7 +161,8 @@ RSpec.describe Resolvers::TimelogResolver do
end
end
end
end
def
resolve_timelogs
(
args
=
{},
context
=
{
current_user:
current_user
})
def
resolve_timelogs
(
user:
current_user
,
**
args
)
context
=
{
current_user:
user
}
resolve
(
described_class
,
obj:
group
,
args:
args
,
ctx:
context
)
resolve
(
described_class
,
obj:
group
,
args:
args
,
ctx:
context
)
end
end
end
end
spec/graphql/types/issue_type_spec.rb
View file @
951ab3a6
...
@@ -18,7 +18,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
...
@@ -18,7 +18,7 @@ RSpec.describe GitlabSchema.types['Issue'] do
confidential discussion_locked upvotes downvotes user_notes_count user_discussions_count web_path web_url relative_position
confidential discussion_locked upvotes downvotes 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
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
design_collection alert_management_alert severity current_user_todos moved moved_to
create_note_email]
create_note_email
timelogs
]
fields
.
each
do
|
field_name
|
fields
.
each
do
|
field_name
|
expect
(
described_class
).
to
have_graphql_field
(
field_name
)
expect
(
described_class
).
to
have_graphql_field
(
field_name
)
...
...
spec/models/concerns/has_timelogs_report_spec.rb
View file @
951ab3a6
...
@@ -32,18 +32,16 @@ RSpec.describe HasTimelogsReport do
...
@@ -32,18 +32,16 @@ RSpec.describe HasTimelogsReport do
end
end
describe
'#user_can_access_group_timelogs?'
do
describe
'#user_can_access_group_timelogs?'
do
before
do
it
'returns true if user can access group timelogs'
do
group
.
add_developer
(
user
)
group
.
add_developer
(
user
)
end
it
'returns true if user can access group timelogs'
do
expect
(
group
).
to
be_user_can_access_group_timelogs
(
user
)
expect
(
group
.
user_can_access_group_timelogs?
(
user
)).
to
be_truthy
end
end
it
'returns false if user has insufficient permissions'
do
it
'returns false if user has insufficient permissions'
do
group
.
add_guest
(
user
)
group
.
add_guest
(
user
)
expect
(
group
.
user_can_access_group_timelogs?
(
user
)).
to
be_falsey
expect
(
group
).
not_to
be_user_can_access_group_timelogs
(
user
)
end
end
end
end
...
...
spec/models/timelog_spec.rb
View file @
951ab3a6
...
@@ -56,9 +56,9 @@ RSpec.describe Timelog do
...
@@ -56,9 +56,9 @@ RSpec.describe Timelog do
group
=
create
(
:group
)
group
=
create
(
:group
)
subgroup
=
create
(
:group
,
parent:
group
)
subgroup
=
create
(
:group
,
parent:
group
)
create
(
:
timelog
,
issue:
create
(
:issue
,
project:
create
(
:project
))
)
create
(
:
issue_timelog
)
timelog1
=
create
(
:timelog
,
issue:
create
(
:issue
,
project:
create
(
:project
,
group:
group
)))
timelog1
=
create
(
:
issue_
timelog
,
issue:
create
(
:issue
,
project:
create
(
:project
,
group:
group
)))
timelog2
=
create
(
:timelog
,
issue:
create
(
:issue
,
project:
create
(
:project
,
group:
subgroup
)))
timelog2
=
create
(
:
issue_
timelog
,
issue:
create
(
:issue
,
project:
create
(
:project
,
group:
subgroup
)))
expect
(
described_class
.
for_issues_in_group
(
group
)).
to
contain_exactly
(
timelog1
,
timelog2
)
expect
(
described_class
.
for_issues_in_group
(
group
)).
to
contain_exactly
(
timelog1
,
timelog2
)
end
end
...
@@ -66,9 +66,9 @@ RSpec.describe Timelog do
...
@@ -66,9 +66,9 @@ RSpec.describe Timelog do
describe
'between_times'
do
describe
'between_times'
do
it
'returns collection of timelogs within given times'
do
it
'returns collection of timelogs within given times'
do
create
(
:timelog
,
spent_at:
65
.
days
.
ago
)
create
(
:
issue_
timelog
,
spent_at:
65
.
days
.
ago
)
timelog1
=
create
(
:timelog
,
spent_at:
15
.
days
.
ago
)
timelog1
=
create
(
:
issue_
timelog
,
spent_at:
15
.
days
.
ago
)
timelog2
=
create
(
:timelog
,
spent_at:
5
.
days
.
ago
)
timelog2
=
create
(
:
issue_
timelog
,
spent_at:
5
.
days
.
ago
)
timelogs
=
described_class
.
between_times
(
20
.
days
.
ago
,
1
.
day
.
ago
)
timelogs
=
described_class
.
between_times
(
20
.
days
.
ago
,
1
.
day
.
ago
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
,
timelog2
)
expect
(
timelogs
).
to
contain_exactly
(
timelog1
,
timelog2
)
...
...
spec/requests/api/graphql/group/timelogs_spec.rb
View file @
951ab3a6
...
@@ -14,6 +14,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
...
@@ -14,6 +14,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
let_it_be
(
:timelog1
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-13 14:00:00'
)
}
let_it_be
(
:timelog1
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-13 14:00:00'
)
}
let_it_be
(
:timelog2
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-10 08:00:00'
)
}
let_it_be
(
:timelog2
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-10 08:00:00'
)
}
let_it_be
(
:params
)
{
{
startTime:
'2019-08-10 12:00:00'
,
endTime:
'2019-08-21 12:00:00'
}
}
let_it_be
(
:params
)
{
{
startTime:
'2019-08-10 12:00:00'
,
endTime:
'2019-08-21 12:00:00'
}
}
let
(
:timelogs_data
)
{
graphql_data
[
'group'
][
'timelogs'
][
'nodes'
]
}
let
(
:timelogs_data
)
{
graphql_data
[
'group'
][
'timelogs'
][
'nodes'
]
}
before
do
before
do
...
@@ -34,11 +35,11 @@ RSpec.describe 'Timelogs through GroupQuery' do
...
@@ -34,11 +35,11 @@ RSpec.describe 'Timelogs through GroupQuery' do
end
end
it
'contains correct data'
,
:aggregate_failures
do
it
'contains correct data'
,
:aggregate_failures
do
username
=
timelog_array
.
map
{
|
data
|
data
[
'user'
][
'username'
]
}
username
=
timelog_array
.
map
{
|
data
|
data
[
'user'
][
'username'
]
}
spent_at
=
timelog_array
.
map
{
|
data
|
data
[
'spentAt'
].
to_time
}
spent_at
=
timelog_array
.
map
{
|
data
|
data
[
'spentAt'
].
to_time
}
time_spent
=
timelog_array
.
map
{
|
data
|
data
[
'timeSpent'
]
}
time_spent
=
timelog_array
.
map
{
|
data
|
data
[
'timeSpent'
]
}
issue_title
=
timelog_array
.
map
{
|
data
|
data
[
'issue'
][
'title'
]
}
issue_title
=
timelog_array
.
map
{
|
data
|
data
[
'issue'
][
'title'
]
}
milestone_title
=
timelog_array
.
map
{
|
data
|
data
[
'issue'
][
'milestone'
][
'title'
]
}
milestone_title
=
timelog_array
.
map
{
|
data
|
data
[
'issue'
][
'milestone'
][
'title'
]
}
expect
(
username
).
to
eq
([
user
.
username
])
expect
(
username
).
to
eq
([
user
.
username
])
expect
(
spent_at
.
first
).
to
be_like_time
(
timelog1
.
spent_at
)
expect
(
spent_at
.
first
).
to
be_like_time
(
timelog1
.
spent_at
)
...
@@ -50,7 +51,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
...
@@ -50,7 +51,7 @@ RSpec.describe 'Timelogs through GroupQuery' do
context
'when arguments with no time are present'
do
context
'when arguments with no time are present'
do
let!
(
:timelog3
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-10 15:00:00'
)
}
let!
(
:timelog3
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-10 15:00:00'
)
}
let!
(
:timelog4
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-21 15:00:00'
)
}
let!
(
:timelog4
)
{
create
(
:timelog
,
issue:
issue
,
user:
user
,
spent_at:
'2019-08-21 15:00:00'
)
}
let
(
:params
)
{
{
startDate:
'2019-08-10'
,
endDate:
'2019-08-21'
}}
let
(
:params
)
{
{
startDate:
'2019-08-10'
,
endDate:
'2019-08-21'
}
}
it
'sets times as start of day and end of day'
do
it
'sets times as start of day and end of day'
do
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
...
@@ -111,12 +112,10 @@ RSpec.describe 'Timelogs through GroupQuery' do
...
@@ -111,12 +112,10 @@ RSpec.describe 'Timelogs through GroupQuery' do
}
}
NODE
NODE
graphql_query_for
(
"group"
,
{
"fullPath"
=>
group
.
full_path
},
graphql_query_for
(
[
query_graphql_field
(
:group
,
"timelogs"
,
{
full_path:
group
.
full_path
},
timelog_params
,
query_graphql_field
(
:timelogs
,
timelog_params
,
timelog_nodes
)
timelog_nodes
)]
)
)
end
end
end
end
spec/requests/api/graphql/project/issues_spec.rb
View file @
951ab3a6
...
@@ -5,14 +5,14 @@ require 'spec_helper'
...
@@ -5,14 +5,14 @@ require 'spec_helper'
RSpec
.
describe
'getting an issue list for a project'
do
RSpec
.
describe
'getting an issue list for a project'
do
include
GraphqlHelpers
include
GraphqlHelpers
let
(
:issues_data
)
{
graphql_data
[
'project'
][
'issues'
][
'edges'
]
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
,
:public
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
,
:public
)
}
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:current_user
)
{
create
(
:user
)
}
let_it_be
(
:issue_a
,
reload:
true
)
{
create
(
:issue
,
project:
project
,
discussion_locked:
true
)
}
let_it_be
(
:issue_a
,
reload:
true
)
{
create
(
:issue
,
project:
project
,
discussion_locked:
true
)
}
let_it_be
(
:issue_b
,
reload:
true
)
{
create
(
:issue
,
:with_alert
,
project:
project
)
}
let_it_be
(
:issue_b
,
reload:
true
)
{
create
(
:issue
,
:with_alert
,
project:
project
)
}
let_it_be
(
:issues
,
reload:
true
)
{
[
issue_a
,
issue_b
]
}
let_it_be
(
:issues
,
reload:
true
)
{
[
issue_a
,
issue_b
]
}
let
(
:issues_data
)
{
graphql_data
[
'project'
][
'issues'
][
'edges'
]
}
let
(
:fields
)
do
let
(
:fields
)
do
<<~
QUERY
<<~
QUERY
edges {
edges {
...
@@ -76,7 +76,7 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -76,7 +76,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
end
end
context
'no limit is provided'
do
context
'
when
no limit is provided'
do
let
(
:issue_limit
)
{
nil
}
let
(
:issue_limit
)
{
nil
}
it
'returns all issues'
do
it
'returns all issues'
do
...
@@ -143,13 +143,15 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -143,13 +143,15 @@ RSpec.describe 'getting an issue list for a project' do
let_it_be
(
:data_path
)
{
[
:project
,
:issues
]
}
let_it_be
(
:data_path
)
{
[
:project
,
:issues
]
}
def
pagination_query
(
params
)
def
pagination_query
(
params
)
graphql_query_for
(
:project
,
{
full_path:
sort_project
.
full_path
},
graphql_query_for
(
:project
,
{
full_path:
sort_project
.
full_path
},
query_graphql_field
(
:issues
,
params
,
"
#{
page_info
}
nodes { iid }"
)
query_graphql_field
(
:issues
,
params
,
"
#{
page_info
}
nodes { iid }"
)
)
)
end
end
def
pagination_results_data
(
data
)
def
pagination_results_data
(
data
)
data
.
map
{
|
issue
|
issue
.
dig
(
'iid'
)
.
to_i
}
data
.
map
{
|
issue
|
issue
[
'iid'
]
.
to_i
}
end
end
context
'when sorting by due date'
do
context
'when sorting by due date'
do
...
@@ -189,27 +191,38 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -189,27 +191,38 @@ RSpec.describe 'getting an issue list for a project' do
it_behaves_like
'sorted paginated query'
do
it_behaves_like
'sorted paginated query'
do
let
(
:sort_param
)
{
:RELATIVE_POSITION_ASC
}
let
(
:sort_param
)
{
:RELATIVE_POSITION_ASC
}
let
(
:first_param
)
{
2
}
let
(
:first_param
)
{
2
}
let
(
:expected_results
)
{
[
relative_issue5
.
iid
,
relative_issue3
.
iid
,
relative_issue1
.
iid
,
relative_issue4
.
iid
,
relative_issue2
.
iid
]
}
let
(
:expected_results
)
do
[
relative_issue5
.
iid
,
relative_issue3
.
iid
,
relative_issue1
.
iid
,
relative_issue4
.
iid
,
relative_issue2
.
iid
]
end
end
end
end
end
end
end
context
'when sorting by priority'
do
context
'when sorting by priority'
do
let_it_be
(
:sort_project
)
{
create
(
:project
,
:public
)
}
let_it_be
(
:sort_project
)
{
create
(
:project
,
:public
)
}
let_it_be
(
:early_milestone
)
{
create
(
:milestone
,
project:
sort_project
,
due_date:
10
.
days
.
from_now
)
}
let_it_be
(
:on_project
)
{
{
project:
sort_project
}
}
let_it_be
(
:late_milestone
)
{
create
(
:milestone
,
project:
sort_project
,
due_date:
30
.
days
.
from_now
)
}
let_it_be
(
:early_milestone
)
{
create
(
:milestone
,
**
on_project
,
due_date:
10
.
days
.
from_now
)
}
let_it_be
(
:priority_label1
)
{
create
(
:label
,
project:
sort_project
,
priority:
1
)
}
let_it_be
(
:late_milestone
)
{
create
(
:milestone
,
**
on_project
,
due_date:
30
.
days
.
from_now
)
}
let_it_be
(
:priority_label2
)
{
create
(
:label
,
project:
sort_project
,
priority:
5
)
}
let_it_be
(
:priority_1
)
{
create
(
:label
,
**
on_project
,
priority:
1
)
}
let_it_be
(
:priority_issue1
)
{
create
(
:issue
,
project:
sort_project
,
labels:
[
priority_label1
],
milestone:
late_milestone
)
}
let_it_be
(
:priority_2
)
{
create
(
:label
,
**
on_project
,
priority:
5
)
}
let_it_be
(
:priority_issue2
)
{
create
(
:issue
,
project:
sort_project
,
labels:
[
priority_label2
])
}
let_it_be
(
:priority_issue1
)
{
create
(
:issue
,
**
on_project
,
labels:
[
priority_1
],
milestone:
late_milestone
)
}
let_it_be
(
:priority_issue3
)
{
create
(
:issue
,
project:
sort_project
,
milestone:
early_milestone
)
}
let_it_be
(
:priority_issue2
)
{
create
(
:issue
,
**
on_project
,
labels:
[
priority_2
])
}
let_it_be
(
:priority_issue4
)
{
create
(
:issue
,
project:
sort_project
)
}
let_it_be
(
:priority_issue3
)
{
create
(
:issue
,
**
on_project
,
milestone:
early_milestone
)
}
let_it_be
(
:priority_issue4
)
{
create
(
:issue
,
**
on_project
)
}
context
'when ascending'
do
context
'when ascending'
do
it_behaves_like
'sorted paginated query'
do
it_behaves_like
'sorted paginated query'
do
let
(
:sort_param
)
{
:PRIORITY_ASC
}
let
(
:sort_param
)
{
:PRIORITY_ASC
}
let
(
:first_param
)
{
2
}
let
(
:first_param
)
{
2
}
let
(
:expected_results
)
{
[
priority_issue3
.
iid
,
priority_issue1
.
iid
,
priority_issue2
.
iid
,
priority_issue4
.
iid
]
}
let
(
:expected_results
)
do
[
priority_issue3
.
iid
,
priority_issue1
.
iid
,
priority_issue2
.
iid
,
priority_issue4
.
iid
]
end
end
end
end
end
...
@@ -217,7 +230,9 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -217,7 +230,9 @@ RSpec.describe 'getting an issue list for a project' do
it_behaves_like
'sorted paginated query'
do
it_behaves_like
'sorted paginated query'
do
let
(
:sort_param
)
{
:PRIORITY_DESC
}
let
(
:sort_param
)
{
:PRIORITY_DESC
}
let
(
:first_param
)
{
2
}
let
(
:first_param
)
{
2
}
let
(
:expected_results
)
{
[
priority_issue1
.
iid
,
priority_issue3
.
iid
,
priority_issue2
.
iid
,
priority_issue4
.
iid
]
}
let
(
:expected_results
)
do
[
priority_issue1
.
iid
,
priority_issue3
.
iid
,
priority_issue2
.
iid
,
priority_issue4
.
iid
]
end
end
end
end
end
end
end
...
@@ -275,7 +290,7 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -275,7 +290,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
end
end
context
'fetching alert management alert'
do
context
'
when
fetching alert management alert'
do
let
(
:fields
)
do
let
(
:fields
)
do
<<~
QUERY
<<~
QUERY
edges {
edges {
...
@@ -297,7 +312,7 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -297,7 +312,7 @@ RSpec.describe 'getting an issue list for a project' do
it
'avoids N+1 queries'
do
it
'avoids N+1 queries'
do
control
=
ActiveRecord
::
QueryRecorder
.
new
{
post_graphql
(
query
,
current_user:
current_user
)
}
control
=
ActiveRecord
::
QueryRecorder
.
new
{
post_graphql
(
query
,
current_user:
current_user
)
}
create
(
:alert_management_alert
,
:with_issue
,
project:
project
)
create
(
:alert_management_alert
,
:with_issue
,
project:
project
)
expect
{
post_graphql
(
query
,
current_user:
current_user
)
}.
not_to
exceed_query_limit
(
control
)
expect
{
post_graphql
(
query
,
current_user:
current_user
)
}.
not_to
exceed_query_limit
(
control
)
end
end
...
@@ -312,7 +327,7 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -312,7 +327,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
end
end
context
'fetching labels'
do
context
'
when
fetching labels'
do
let
(
:fields
)
do
let
(
:fields
)
do
<<~
QUERY
<<~
QUERY
edges {
edges {
...
@@ -362,7 +377,7 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -362,7 +377,7 @@ RSpec.describe 'getting an issue list for a project' do
end
end
end
end
context
'fetching assignees'
do
context
'
when
fetching assignees'
do
let
(
:fields
)
do
let
(
:fields
)
do
<<~
QUERY
<<~
QUERY
edges {
edges {
...
@@ -420,9 +435,10 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -420,9 +435,10 @@ RSpec.describe 'getting an issue list for a project' do
query
=
graphql_query_for
(
query
=
graphql_query_for
(
:project
,
:project
,
{
full_path:
project
.
full_path
},
{
full_path:
project
.
full_path
},
query_graphql_field
(
:issues
,
search_params
,
[
query_graphql_field
(
:issues
,
search_params
,
query_graphql_field
(
:nodes
,
nil
,
requested_fields
)
query_graphql_field
(
:nodes
,
nil
,
requested_fields
)
]
)
)
)
)
post_graphql
(
query
,
current_user:
current_user
)
post_graphql
(
query
,
current_user:
current_user
)
end
end
...
@@ -448,5 +464,16 @@ RSpec.describe 'getting an issue list for a project' do
...
@@ -448,5 +464,16 @@ RSpec.describe 'getting an issue list for a project' do
include_examples
'N+1 query check'
include_examples
'N+1 query check'
end
end
context
'when requesting `timelogs`'
do
let
(
:requested_fields
)
{
'timelogs { nodes { timeSpent } }'
}
before
do
create_list
(
:issue_timelog
,
2
,
issue:
issue_a
)
create
(
:issue_timelog
,
issue:
issue_b
)
end
include_examples
'N+1 query check'
end
end
end
end
end
spec/requests/api/graphql/project/merge_requests_spec.rb
View file @
951ab3a6
...
@@ -299,6 +299,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
...
@@ -299,6 +299,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
reviewers { nodes { username } }
reviewers { nodes { username } }
participants { nodes { username } }
participants { nodes { username } }
headPipeline { status }
headPipeline { status }
timelogs { nodes { timeSpent } }
SELECT
SELECT
end
end
...
@@ -307,7 +308,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
...
@@ -307,7 +308,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
query($first: Int) {
query($first: Int) {
project(fullPath: "
#{
project
.
full_path
}
") {
project(fullPath: "
#{
project
.
full_path
}
") {
mergeRequests(first: $first) {
mergeRequests(first: $first) {
nodes {
#{
mr_fields
}
}
nodes {
iid
#{
mr_fields
}
}
}
}
}
}
}
}
...
@@ -324,6 +325,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
...
@@ -324,6 +325,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
mr
.
assignees
<<
current_user
mr
.
assignees
<<
current_user
mr
.
reviewers
<<
create
(
:user
)
mr
.
reviewers
<<
create
(
:user
)
mr
.
reviewers
<<
current_user
mr
.
reviewers
<<
current_user
mr
.
timelogs
<<
create
(
:merge_request_timelog
,
merge_request:
mr
)
end
end
end
end
...
@@ -345,7 +347,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
...
@@ -345,7 +347,7 @@ RSpec.describe 'getting merge request listings nested in a project' do
end
end
def
user_collection
def
user_collection
{
'nodes'
=>
all
(
match
(
a_hash_including
(
'username'
=>
be_present
)))
}
{
'nodes'
=>
be_present
.
and
(
all
(
match
(
a_hash_including
(
'username'
=>
be_present
)
)))
}
end
end
it
'returns appropriate results'
do
it
'returns appropriate results'
do
...
@@ -358,7 +360,8 @@ RSpec.describe 'getting merge request listings nested in a project' do
...
@@ -358,7 +360,8 @@ RSpec.describe 'getting merge request listings nested in a project' do
'assignees'
=>
user_collection
,
'assignees'
=>
user_collection
,
'reviewers'
=>
user_collection
,
'reviewers'
=>
user_collection
,
'participants'
=>
user_collection
,
'participants'
=>
user_collection
,
'headPipeline'
=>
{
'status'
=>
be_present
}
'headPipeline'
=>
{
'status'
=>
be_present
},
'timelogs'
=>
{
'nodes'
=>
be_one
}
)))
)))
end
end
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment