Commit ad5366da authored by Bob Van Landuyt's avatar Bob Van Landuyt

Merge branch '12577-graphql-expose-smaller-design-images' into 'master'

Expose smaller Design Management design images in GraphQL

See merge request gitlab-org/gitlab!26947
parents 60f71a33 dc587e38
......@@ -776,10 +776,15 @@ type Design implements DesignFields & Noteable {
id: ID!
"""
The URL of the image
The URL of the full-sized image
"""
image: String!
"""
The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated
"""
imageV432x230: String
"""
The issue the design belongs to
"""
......@@ -891,10 +896,15 @@ type DesignAtVersion implements DesignFields {
id: ID!
"""
The URL of the image
The URL of the full-sized image
"""
image: String!
"""
The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated
"""
imageV432x230: String
"""
The issue the design belongs to
"""
......@@ -1144,10 +1154,15 @@ interface DesignFields {
id: ID!
"""
The URL of the image
The URL of the full-sized image
"""
image: String!
"""
The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated
"""
imageV432x230: String
"""
The issue the design belongs to
"""
......
......@@ -2247,7 +2247,7 @@
},
{
"name": "image",
"description": "The URL of the image",
"description": "The URL of the full-sized image",
"args": [
],
......@@ -2263,6 +2263,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "imageV432x230",
"description": "The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issue",
"description": "The issue the design belongs to",
......@@ -2583,7 +2597,7 @@
},
{
"name": "image",
"description": "The URL of the image",
"description": "The URL of the full-sized image",
"args": [
],
......@@ -2599,6 +2613,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "imageV432x230",
"description": "The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issue",
"description": "The issue the design belongs to",
......@@ -3326,7 +3354,7 @@
},
{
"name": "image",
"description": "The URL of the image",
"description": "The URL of the full-sized image",
"args": [
],
......@@ -3342,6 +3370,20 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "imageV432x230",
"description": "The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issue",
"description": "The issue the design belongs to",
......
......@@ -170,7 +170,8 @@ A single design
| `filename` | String! | The filename of the design |
| `fullPath` | String! | The full path to the design file |
| `id` | ID! | The ID of this design |
| `image` | String! | The URL of the image |
| `image` | String! | The URL of the full-sized image |
| `imageV432x230` | String | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated |
| `issue` | Issue! | The issue the design belongs to |
| `notesCount` | Int! | The total count of user-created notes for this design |
| `project` | Project! | The project the design belongs to |
......@@ -187,7 +188,8 @@ A design pinned to a specific version. The image field reflects the design as of
| `filename` | String! | The filename of the design |
| `fullPath` | String! | The full path to the design file |
| `id` | ID! | The ID of this design |
| `image` | String! | The URL of the image |
| `image` | String! | The URL of the full-sized image |
| `imageV432x230` | String | The URL of the design resized to fit within the bounds of 432x230. This will be `null` if the image has not been generated |
| `issue` | Issue! | The issue the design belongs to |
| `notesCount` | Int! | The total count of user-created notes for this design |
| `project` | Project! | The project the design belongs to |
......
......@@ -12,7 +12,10 @@ module Types
field :issue, Types::IssueType, null: false, description: 'The issue the design belongs to'
field :filename, GraphQL::STRING_TYPE, null: false, description: 'The filename of the design'
field :full_path, GraphQL::STRING_TYPE, null: false, description: 'The full path to the design file'
field :image, GraphQL::STRING_TYPE, null: false, extras: [:parent], description: 'The URL of the image'
field :image, GraphQL::STRING_TYPE, null: false, extras: [:parent], description: 'The URL of the full-sized image'
field :image_v432x230, GraphQL::STRING_TYPE, null: true, extras: [:parent],
description: 'The URL of the design resized to fit within the bounds of 432x230. ' \
'This will be `null` if the image has not been generated'
field :diff_refs, Types::DiffRefsType,
null: false,
calls_gitaly: true,
......@@ -39,6 +42,16 @@ module Types
Gitlab::UrlBuilder.build(design, ref: sha)
end
def image_v432x230(parent:)
version = cached_stateful_version(parent)
action = design.actions.up_to_version(version).most_recent.first
# A `nil` return value indicates that the image has not been processed
return unless action.image_v432x230.file
Gitlab::UrlBuilder.build(design, ref: version.sha, size: :v432x230)
end
def event(parent:)
version = cached_stateful_version(parent)
......
---
title: Expose smaller sized Design Management design images in GraphQL
merge_request: 26947
author:
type: added
......@@ -6,24 +6,33 @@ describe 'Getting designs related to an issue' do
include GraphqlHelpers
include DesignManagementTestHelpers
let_it_be(:design) { create(:design, :with_file, versions_count: 1) }
let_it_be(:design) { create(:design, :with_smaller_image_versions, versions_count: 1) }
let_it_be(:current_user) { design.project.owner }
let(:design_query) do
<<~NODE
designs {
edges {
node {
id
filename
fullPath
event
image
imageV432x230
}
}
}
NODE
end
let(:issue) { design.issue }
let(:project) { issue.project }
let(:query) { make_query }
let(:design_collection) do
graphql_data_at(:project, :issue, :design_collection)
end
let(:design_response) do
design_collection.dig('designs', 'edges').first['node']
end
def make_query(dq = design_query)
designs_field = query_graphql_field(:design_collection, {}, dq)
......@@ -32,12 +41,8 @@ describe 'Getting designs related to an issue' do
graphql_query_for(:project, { fullPath: project.full_path }, issue_field)
end
let(:design_collection) do
graphql_data_at(:project, :issue, :design_collection)
end
let(:design_response) do
design_collection.dig('designs', 'edges').first['node']
def design_image_url(design, ref: nil, size: nil)
Gitlab::UrlBuilder.build(design, ref: ref, size: size)
end
context 'when the feature is not available' do
......@@ -64,10 +69,33 @@ describe 'Getting designs related to an issue' do
enable_design_management
end
it 'returns the design filename' do
it 'returns the design properties correctly' do
version_sha = design.versions.first.sha
post_graphql(query, current_user: current_user)
expect(design_response['filename']).to eq(design.filename)
expect(design_response).to eq(
'id' => design.to_global_id.to_s,
'event' => 'CREATION',
'fullPath' => design.full_path,
'filename' => design.filename,
'image' => design_image_url(design, ref: version_sha),
'imageV432x230' => design_image_url(design, ref: version_sha, size: :v432x230)
)
end
context 'when the v432x230-sized design image has not been processed' do
before do
allow_next_instance_of(DesignManagement::DesignV432x230Uploader) do |uploader|
allow(uploader).to receive(:file).and_return(nil)
end
end
it 'returns nil for the v432x230-sized design image' do
post_graphql(query, current_user: current_user)
expect(design_response['imageV432x230']).to be_nil
end
end
describe 'pagination' do
......@@ -152,7 +180,7 @@ describe 'Getting designs related to an issue' do
describe 'viewing a design board at a particular version' do
let_it_be(:issue) { design.issue }
let_it_be(:second_design) { create(:design, :with_file, issue: issue, versions_count: 1) }
let_it_be(:second_design, reload: true) { create(:design, :with_smaller_image_versions, issue: issue, versions_count: 1) }
let_it_be(:deleted_design) { create(:design, :with_versions, issue: issue, deleted: true, versions_count: 1) }
let(:all_versions) { issue.design_versions.ordered.reverse }
let(:design_query) do
......@@ -162,6 +190,7 @@ describe 'Getting designs related to an issue' do
node {
id
image
imageV432x230
event
versions {
edges {
......@@ -179,10 +208,6 @@ describe 'Getting designs related to an issue' do
design_collection['designs']['edges']
end
def image_url(design, sha = nil)
Gitlab::UrlBuilder.build(design, ref: sha)
end
def global_id(object)
object.to_global_id.to_s
end
......@@ -214,9 +239,15 @@ describe 'Getting designs related to an issue' do
)
end
it 'returns the correct version of the design image' do
it 'returns the correct full-sized design image' do
expect(design_nodes).to contain_exactly(
a_hash_including('image' => design_image_url(design, ref: version.sha))
)
end
it 'returns the correct v432x230-sized design image' do
expect(design_nodes).to contain_exactly(
a_hash_including('image' => image_url(design, version.sha))
a_hash_including('imageV432x230' => design_image_url(design, ref: version.sha, size: :v432x230))
)
end
......@@ -247,10 +278,17 @@ describe 'Getting designs related to an issue' do
)
end
it 'returns the correct versions of the design images' do
it 'returns the correct full-sized design images' do
expect(design_nodes).to contain_exactly(
a_hash_including('image' => image_url(design, version.sha)),
a_hash_including('image' => image_url(second_design, version.sha))
a_hash_including('image' => design_image_url(design, ref: version.sha)),
a_hash_including('image' => design_image_url(second_design, ref: version.sha))
)
end
it 'returns the correct v432x230-sized design images' do
expect(design_nodes).to contain_exactly(
a_hash_including('imageV432x230' => design_image_url(design, ref: version.sha, size: :v432x230)),
a_hash_including('imageV432x230' => design_image_url(second_design, ref: version.sha, size: :v432x230))
)
end
......@@ -271,10 +309,11 @@ describe 'Getting designs related to an issue' do
context 'viewing the last version, when one design was deleted and one was updated' do
let(:version) { all_versions.last }
let!(:second_design_update) do
create(:design_action, :with_image_v432x230, design: second_design, version: version, event: 'modification')
end
before do
second_design.actions.create!(version: version, event: 'modification')
post_graphql(query, current_user: current_user)
end
......@@ -289,10 +328,17 @@ describe 'Getting designs related to an issue' do
)
end
it 'returns the correct versions of the design images' do
it 'returns the correct full-sized design images' do
expect(design_nodes).to contain_exactly(
a_hash_including('image' => design_image_url(design, ref: version.sha)),
a_hash_including('image' => design_image_url(second_design, ref: version.sha))
)
end
it 'returns the correct v432x230-sized design images' do
expect(design_nodes).to contain_exactly(
a_hash_including('image' => image_url(design, version.sha)),
a_hash_including('image' => image_url(second_design, version.sha))
a_hash_including('imageV432x230' => design_image_url(design, ref: version.sha, size: :v432x230)),
a_hash_including('imageV432x230' => design_image_url(second_design, ref: version.sha, size: :v432x230))
)
end
......
......@@ -16,6 +16,7 @@ RSpec.shared_examples 'a GraphQL type with design fields' do
filename
full_path
image
image_v432x230
diff_refs
event
notes_count
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment