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
4c78cc58
Commit
4c78cc58
authored
Jan 20, 2021
by
Alex Kalderimis
Committed by
Peter Leitzen
Jan 20, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use GlobalID types in discussions
This uses the GlobalIDType for discussions
parent
0df9f800
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
119 additions
and
20 deletions
+119
-20
app/graphql/types/notes/discussion_type.rb
app/graphql/types/notes/discussion_type.rb
+7
-5
app/graphql/types/notes/note_type.rb
app/graphql/types/notes/note_type.rb
+1
-1
doc/api/graphql/reference/gitlab_schema.graphql
doc/api/graphql/reference/gitlab_schema.graphql
+3
-3
doc/api/graphql/reference/gitlab_schema.json
doc/api/graphql/reference/gitlab_schema.json
+3
-3
doc/api/graphql/reference/index.md
doc/api/graphql/reference/index.md
+3
-3
lib/gitlab/global_id.rb
lib/gitlab/global_id.rb
+2
-2
spec/requests/api/graphql/issue/issue_spec.rb
spec/requests/api/graphql/issue/issue_spec.rb
+14
-0
spec/requests/api/graphql/project/issue/designs/notes_spec.rb
.../requests/api/graphql/project/issue/designs/notes_spec.rb
+18
-1
spec/support/helpers/graphql_helpers.rb
spec/support/helpers/graphql_helpers.rb
+6
-2
spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb
...examples/requests/api/graphql/noteable_shared_examples.rb
+62
-0
No files found.
app/graphql/types/notes/discussion_type.rb
View file @
4c78cc58
...
@@ -3,24 +3,26 @@
...
@@ -3,24 +3,26 @@
module
Types
module
Types
module
Notes
module
Notes
class
DiscussionType
<
BaseObject
class
DiscussionType
<
BaseObject
DiscussionID
=
::
Types
::
GlobalIDType
[
::
Discussion
]
graphql_name
'Discussion'
graphql_name
'Discussion'
authorize
:read_note
authorize
:read_note
implements
(
Types
::
ResolvableInterface
)
implements
(
Types
::
ResolvableInterface
)
field
:id
,
GraphQL
::
ID_TYPE
,
null:
false
,
field
:id
,
DiscussionID
,
null:
false
,
description:
"ID of this discussion"
description:
"ID of this discussion"
field
:reply_id
,
GraphQL
::
ID_TYPE
,
null:
false
,
field
:reply_id
,
DiscussionID
,
null:
false
,
description:
'ID used to reply to this discussion'
description:
'ID used to reply to this discussion'
field
:created_at
,
Types
::
TimeType
,
null:
false
,
field
:created_at
,
Types
::
TimeType
,
null:
false
,
description:
"Timestamp of the discussion's creation"
description:
"Timestamp of the discussion's creation"
field
:notes
,
Types
::
Notes
::
NoteType
.
connection_type
,
null:
false
,
field
:notes
,
Types
::
Notes
::
NoteType
.
connection_type
,
null:
false
,
description:
'All notes in the discussion'
description:
'All notes in the discussion'
#
The gem we use to generate Global IDs is hard-coded to work with
#
DiscussionID.coerce_result is suitable here, but will always mark this
#
`id` properties. To generate a GID for the `reply_id` property,
#
as being a 'Discussion'. Using `GlobalId.build` guarantees that we get
#
we must use the ::Gitlab::GlobalId module
.
#
the correct class, and that it matches `id`
.
def
reply_id
def
reply_id
::
Gitlab
::
GlobalId
.
build
(
object
,
id:
object
.
reply_id
)
::
Gitlab
::
GlobalId
.
build
(
object
,
id:
object
.
reply_id
)
end
end
...
...
app/graphql/types/notes/note_type.rb
View file @
4c78cc58
...
@@ -11,7 +11,7 @@ module Types
...
@@ -11,7 +11,7 @@ module Types
implements
(
Types
::
ResolvableInterface
)
implements
(
Types
::
ResolvableInterface
)
field
:id
,
GraphQL
::
ID_TYPE
,
null:
false
,
field
:id
,
::
Types
::
GlobalIDType
[
::
Note
]
,
null:
false
,
description:
'ID of the note'
description:
'ID of the note'
field
:project
,
Types
::
ProjectType
,
field
:project
,
Types
::
ProjectType
,
...
...
doc/api/graphql/reference/gitlab_schema.graphql
View file @
4c78cc58
...
@@ -7878,7 +7878,7 @@ type Discussion implements ResolvableInterface {
...
@@ -7878,7 +7878,7 @@ type Discussion implements ResolvableInterface {
"""
"""
ID
of
this
discussion
ID
of
this
discussion
"""
"""
id
:
ID
!
id
:
Discussion
ID
!
"""
"""
All
notes
in
the
discussion
All
notes
in
the
discussion
...
@@ -7908,7 +7908,7 @@ type Discussion implements ResolvableInterface {
...
@@ -7908,7 +7908,7 @@ type Discussion implements ResolvableInterface {
"""
"""
ID
used
to
reply
to
this
discussion
ID
used
to
reply
to
this
discussion
"""
"""
replyId
:
ID
!
replyId
:
Discussion
ID
!
"""
"""
Indicates
if
the
object
can
be
resolved
Indicates
if
the
object
can
be
resolved
...
@@ -16154,7 +16154,7 @@ type Note implements ResolvableInterface {
...
@@ -16154,7 +16154,7 @@ type Note implements ResolvableInterface {
"""
"""
ID
of
the
note
ID
of
the
note
"""
"""
id
:
ID
!
id
:
Note
ID
!
"""
"""
The
position
of
this
note
on
a
diff
The
position
of
this
note
on
a
diff
...
...
doc/api/graphql/reference/gitlab_schema.json
View file @
4c78cc58
...
@@ -21766,7 +21766,7 @@
...
@@ -21766,7 +21766,7 @@
"name": null,
"name": null,
"ofType": {
"ofType": {
"kind": "SCALAR",
"kind": "SCALAR",
"name": "ID",
"name": "
Discussion
ID",
"ofType": null
"ofType": null
}
}
},
},
...
@@ -21841,7 +21841,7 @@
...
@@ -21841,7 +21841,7 @@
"name": null,
"name": null,
"ofType": {
"ofType": {
"kind": "SCALAR",
"kind": "SCALAR",
"name": "ID",
"name": "
Discussion
ID",
"ofType": null
"ofType": null
}
}
},
},
...
@@ -47730,7 +47730,7 @@
...
@@ -47730,7 +47730,7 @@
"name": null,
"name": null,
"ofType": {
"ofType": {
"kind": "SCALAR",
"kind": "SCALAR",
"name": "ID",
"name": "
Note
ID",
"ofType": null
"ofType": null
}
}
},
},
doc/api/graphql/reference/index.md
View file @
4c78cc58
...
@@ -1301,9 +1301,9 @@ Aggregated summary of changes.
...
@@ -1301,9 +1301,9 @@ Aggregated summary of changes.
| Field | Type | Description |
| Field | Type | Description |
| ----- | ---- | ----------- |
| ----- | ---- | ----------- |
|
`createdAt`
| Time! | Timestamp of the discussion's creation |
|
`createdAt`
| Time! | Timestamp of the discussion's creation |
|
`id`
| ID! | ID of this discussion |
|
`id`
|
Discussion
ID! | ID of this discussion |
|
`notes`
| NoteConnection! | All notes in the discussion |
|
`notes`
| NoteConnection! | All notes in the discussion |
|
`replyId`
| ID! | ID used to reply to this discussion |
|
`replyId`
|
Discussion
ID! | ID used to reply to this discussion |
|
`resolvable`
| Boolean! | Indicates if the object can be resolved |
|
`resolvable`
| Boolean! | Indicates if the object can be resolved |
|
`resolved`
| Boolean! | Indicates if the object is resolved |
|
`resolved`
| Boolean! | Indicates if the object is resolved |
|
`resolvedAt`
| Time | Timestamp of when the object was resolved |
|
`resolvedAt`
| Time | Timestamp of when the object was resolved |
...
@@ -2429,7 +2429,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
...
@@ -2429,7 +2429,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily.
|
`confidential`
| Boolean | Indicates if this note is confidential |
|
`confidential`
| Boolean | Indicates if this note is confidential |
|
`createdAt`
| Time! | Timestamp of the note creation |
|
`createdAt`
| Time! | Timestamp of the note creation |
|
`discussion`
| Discussion | The discussion this note is a part of |
|
`discussion`
| Discussion | The discussion this note is a part of |
|
`id`
| ID! | ID of the note |
|
`id`
|
Note
ID! | ID of the note |
|
`position`
| DiffPosition | The position of this note on a diff |
|
`position`
| DiffPosition | The position of this note on a diff |
|
`project`
| Project | Project associated with the note |
|
`project`
| Project | Project associated with the note |
|
`resolvable`
| Boolean! | Indicates if the object can be resolved |
|
`resolvable`
| Boolean! | Indicates if the object can be resolved |
...
...
lib/gitlab/global_id.rb
View file @
4c78cc58
...
@@ -19,8 +19,8 @@ module Gitlab
...
@@ -19,8 +19,8 @@ module Gitlab
value
value
when
URI
::
GID
when
URI
::
GID
GlobalID
.
new
(
value
)
GlobalID
.
new
(
value
)
when
Integer
when
Integer
,
String
raise
CoerceError
,
'Cannot coerce Integer'
unless
model_name
.
present?
raise
CoerceError
,
"Cannot coerce
#{
value
.
class
}
"
unless
model_name
.
present?
GlobalID
.
new
(
::
Gitlab
::
GlobalId
.
build
(
model_name:
model_name
,
id:
value
))
GlobalID
.
new
(
::
Gitlab
::
GlobalId
.
build
(
model_name:
model_name
,
id:
value
))
else
else
...
...
spec/requests/api/graphql/issue/issue_spec.rb
View file @
4c78cc58
...
@@ -24,6 +24,20 @@ RSpec.describe 'Query.issue(id)' do
...
@@ -24,6 +24,20 @@ RSpec.describe 'Query.issue(id)' do
end
end
end
end
it_behaves_like
'a noteable graphql type we can query'
do
let
(
:noteable
)
{
issue
}
let
(
:project
)
{
issue
.
project
}
let
(
:path_to_noteable
)
{
[
:issue
]
}
before
do
project
.
add_guest
(
current_user
)
end
def
query
(
fields
)
graphql_query_for
(
'issue'
,
issue_params
,
fields
)
end
end
context
'when the user does not have access to the issue'
do
context
'when the user does not have access to the issue'
do
it
'returns nil'
do
it
'returns nil'
do
project
.
project_feature
.
update!
(
issues_access_level:
ProjectFeature
::
PRIVATE
)
project
.
project_feature
.
update!
(
issues_access_level:
ProjectFeature
::
PRIVATE
)
...
...
spec/requests/api/graphql/project/issue/designs/notes_spec.rb
View file @
4c78cc58
...
@@ -22,6 +22,23 @@ RSpec.describe 'Getting designs related to an issue' do
...
@@ -22,6 +22,23 @@ RSpec.describe 'Getting designs related to an issue' do
end
end
end
end
it_behaves_like
'a noteable graphql type we can query'
do
let
(
:noteable
)
{
design
}
let
(
:note_factory
)
{
:diff_note_on_design
}
let
(
:discussion_factory
)
{
:diff_note_on_design
}
let
(
:path_to_noteable
)
{
[
:issue
,
:design_collection
,
:designs
,
:nodes
,
0
]
}
before
do
project
.
add_developer
(
current_user
)
end
def
query
(
fields
)
graphql_query_for
(
:issue
,
{
id:
global_id_of
(
issue
)
},
<<~
FIELDS
)
designCollection { designs { nodes {
#{
fields
}
} } }
FIELDS
end
end
it
'is not too deep for anonymous users'
do
it
'is not too deep for anonymous users'
do
note_fields
=
<<~
FIELDS
note_fields
=
<<~
FIELDS
id
id
...
@@ -37,7 +54,7 @@ RSpec.describe 'Getting designs related to an issue' do
...
@@ -37,7 +54,7 @@ RSpec.describe 'Getting designs related to an issue' do
expect
(
note_data
[
'id'
]).
to
eq
(
note
.
to_global_id
.
to_s
)
expect
(
note_data
[
'id'
]).
to
eq
(
note
.
to_global_id
.
to_s
)
end
end
def
query
(
note_fields
=
all_graphql_fields_for
(
Note
))
def
query
(
note_fields
=
all_graphql_fields_for
(
Note
,
max_depth:
1
))
design_node
=
<<~
NODE
design_node
=
<<~
NODE
designs {
designs {
nodes {
nodes {
...
...
spec/support/helpers/graphql_helpers.rb
View file @
4c78cc58
...
@@ -510,8 +510,12 @@ module GraphqlHelpers
...
@@ -510,8 +510,12 @@ module GraphqlHelpers
end
end
end
end
def
global_id_of
(
model
)
def
global_id_of
(
model
,
id:
nil
,
model_name:
nil
)
model
.
to_global_id
.
to_s
if
id
||
model_name
::
Gitlab
::
GlobalId
.
build
(
model
,
id:
id
,
model_name:
model_name
).
to_s
else
model
.
to_global_id
.
to_s
end
end
end
def
missing_required_argument
(
path
,
argument
)
def
missing_required_argument
(
path
,
argument
)
...
...
spec/support/shared_examples/requests/api/graphql/noteable_shared_examples.rb
0 → 100644
View file @
4c78cc58
# frozen_string_literal: true
# Requires `query(fields)`, `path_to_noteable`, `project`, and `noteable` bindings
RSpec
.
shared_examples
'a noteable graphql type we can query'
do
let
(
:note_factory
)
{
:note
}
let
(
:discussion_factory
)
{
:discussion_note
}
describe
'.discussions'
do
let
(
:fields
)
do
"discussions { nodes {
#{
all_graphql_fields_for
(
'Discussion'
)
}
} }"
end
def
expected
noteable
.
discussions
.
map
do
|
discussion
|
include
(
'id'
=>
global_id_of
(
discussion
),
'replyId'
=>
global_id_of
(
discussion
,
id:
discussion
.
reply_id
),
'createdAt'
=>
discussion
.
created_at
.
iso8601
,
'notes'
=>
include
(
'nodes'
=>
have_attributes
(
size:
discussion
.
notes
.
size
)
)
)
end
end
it
'can fetch discussions'
do
create
(
discussion_factory
,
project:
project
,
noteable:
noteable
)
post_graphql
(
query
(
fields
),
current_user:
current_user
)
expect
(
graphql_data_at
(
*
path_to_noteable
,
:discussions
,
:nodes
))
.
to
match_array
(
expected
)
end
end
describe
'.notes'
do
let
(
:fields
)
do
"notes { nodes {
#{
all_graphql_fields_for
(
'Note'
,
max_depth:
2
)
}
} }"
end
def
expected
noteable
.
notes
.
map
do
|
note
|
include
(
'id'
=>
global_id_of
(
note
),
'project'
=>
include
(
'id'
=>
global_id_of
(
project
)),
'author'
=>
include
(
'id'
=>
global_id_of
(
note
.
author
)),
'createdAt'
=>
note
.
created_at
.
iso8601
,
'body'
=>
eq
(
note
.
note
)
)
end
end
it
'can fetch notes'
do
create
(
note_factory
,
project:
project
,
noteable:
noteable
)
post_graphql
(
query
(
fields
),
current_user:
current_user
)
expect
(
graphql_data_at
(
*
path_to_noteable
,
:notes
,
:nodes
))
.
to
match_array
(
expected
)
end
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