Skip to content

Commit

Permalink
Use GraphQL for rendering news articles
Browse files Browse the repository at this point in the history
This retrieves the content from Publishing API, instead of Content
Store, using a GraphQL query.

Note this has been done in the way that reduces the number of changes
needed in this application. As a result, we have introduced a small
"hack" to return the data in `GdsApi::Response` format but with this app
rewriting the hash keys to make them all underscore based.
  • Loading branch information
brucebolt committed Dec 3, 2024
1 parent 5c17431 commit 43a748e
Show file tree
Hide file tree
Showing 7 changed files with 272 additions and 7 deletions.
40 changes: 33 additions & 7 deletions app/controllers/content_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,42 @@ def set_guide_draft_access_token
@content_item.draft_access_token = params[:token]
end

class GdsApi::Response
def update_response_body
updated_response = JSON.parse(@http_response.body).dig("data", "edition").deep_transform_keys(&:underscore)
@http_response = RestClient::Response.create(
updated_response.to_json,
@http_response.net_http_res,
@http_response.request,
)
end
end

def load_content_item
## TODO: how do we know this is a news article without content store telling us first??
content_item = Services.content_store.content_item(content_item_path)

content_item["links"]["ordered_related_items"] = ordered_related_items(content_item["links"]) if content_item["links"]

@content_item = PresenterBuilder.new(
content_item,
content_item_path,
view_context,
).presenter
@content_item = if content_item["schema_name"] == "news_article" && (Features.graphql_feature_enabled? || params.include?(:graphql))
graphql_response = Services
.publishing_api
.graphql_query(Graphql::NewsArticleQuery.new(content_item_path).query)

graphql_response.update_response_body

PresenterBuilder.new(
graphql_response,
content_item_path,
view_context,
).presenter
else
content_item["links"]["ordered_related_items"] = ordered_related_items(content_item["links"]) if content_item["links"]

PresenterBuilder.new(
content_item,
content_item_path,
view_context,
).presenter
end
end

def ordered_related_items(links)
Expand Down
75 changes: 75 additions & 0 deletions app/queries/graphql/news_article_query.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
class Graphql::NewsArticleQuery
def initialize(base_path)
@base_path = base_path
end

def query
<<-QUERY
{
edition(
basePath: "#{@base_path}",
contentStore: "live",
) {
... on NewsArticle {
basePath
description
details
documentType
firstPublishedAt
links {
availableTranslations {
basePath
locale
}
government {
details {
current
}
title
}
organisations {
basePath
contentId
title
}
people {
basePath
contentId
title
}
taxons {
basePath
contentId
documentType
phase
title
links {
parentTaxons {
basePath
contentId
documentType
phase
title
}
}
}
topicalEvents {
basePath
contentId
title
}
worldLocations {
basePath
contentId
title
}
}
locale
schemaName
title
}
}
}
QUERY
end
end
38 changes: 38 additions & 0 deletions test/controllers/content_items_controller_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
require "test_helper"
require "gds_api/test_helpers/publishing_api"

class ContentItemsControllerTest < ActionController::TestCase
include GdsApi::TestHelpers::ContentStore
include GdsApi::TestHelpers::PublishingApi
include GovukAbTesting::MinitestHelpers

test "routing handles paths with no format or locale" do
Expand Down Expand Up @@ -124,6 +126,42 @@ class ContentItemsControllerTest < ActionController::TestCase
assert_response :not_acceptable
end

test "with the GraphQL feature flag enabled gets item from GraphQL if it is a news article" do
Features.stubs(:graphql_feature_enabled?).returns(true)

content_item = content_store_has_schema_example("news_article", "news_article")
base_path = content_item["base_path"]

graphql_fixture = fetch_graphql_fixture("news_article")
stub_publishing_api_graphql_query(Graphql::NewsArticleQuery.new(base_path).query, graphql_fixture)

get :show,
params: {
path: path_for(content_item),
}

assert_requested :post, "#{PUBLISHING_API_ENDPOINT}/graphql",
body: { query: Graphql::NewsArticleQuery.new(base_path).query },
times: 1

assert_response :success
end

test "with the GraphQL feature flag enabled does not get item from GraphQL if it is not a news article" do
Features.stubs(:graphql_feature_enabled?).returns(true)

content_item = content_store_has_schema_example("case_study", "case_study")

get :show,
params: {
path: path_for(content_item),
}

assert_not_requested :post, "#{PUBLISHING_API_ENDPOINT}/graphql"

assert_response :success
end

test "gets item from content store" do
content_item = content_store_has_schema_example("case_study", "case_study")

Expand Down
72 changes: 72 additions & 0 deletions test/fixtures/graphql/news_article.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"data": {
"edition": {
"basePath": "/government/news/announcement",
"description": "Summary of the news",
"details": {
"body": "Some text",
"political": "true"
},
"documentType": "news_story",
"firstPublishedAt": "2016-12-25T01:02:03+00:00",
"links": {
"availableTranslations": [
{
"basePath": "/government/news/announcement",
"locale": "en"
}
],
"government": [
{
"details": {
"current": false
},
"title": "A government"
}
],
"organisations": [
{
"basePath": "/organisation-1",
"title": "An organisation"
}
],
"people": [
{
"basePath": "/person-1",
"title": "A person"
}
],
"taxons": [
{
"basePath": "/taxon-1",
"contentId": "8fa1fa2f-bcce-4cde-98fb-308514c35c63",
"title": "Taxon 1",
"links": {
"parentTaxons": [
{
"basePath": "/taxon-2",
"contentId": "9de167ce-6c4f-40b1-a45e-e3160d75556e",
"title": "Taxon 2"
}
]
}
}
],
"topicalEvents": [
{
"basePath": "/topical-event-1",
"title": "A topical event"
}
],
"worldLocations": [
{
"basePath": "/world-location-1",
"title": "A world location"
}
]
},
"schemaName": "news_article",
"title": "Generic news article"
}
}
}
14 changes: 14 additions & 0 deletions test/presenter_test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,17 @@ def schema_item(type = schema_name, schema = schema_name)
govuk_content_schema_example(schema, type)
end
end

class GraphqlPresenterTestCase < PresenterTestCase
def create_presenter(presenter_class,
content_item: fetch_graphql_fixture("news_article"),
requested_path: "/test-content-item",
view_context: ApplicationController.new.view_context)
presenter_class.new(content_item, requested_path, view_context)
end

def presented_item(type = schema_name, overrides = {})
example = fetch_graphql_fixture(type).dig("data", "edition").deep_transform_keys(&:underscore)
present_example(example.merge(overrides))
end
end
33 changes: 33 additions & 0 deletions test/presenters/news_article_graphql_presenter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require "presenter_test_helper"

class NewsArticleGraphqlPresenterTest
class NewsArticleGraphqlPresenterTestCase < GraphqlPresenterTestCase
attr_accessor :example_schema_name

def schema_name
"news_article"
end
end

class PresentedNewsArticleGraphqlTest < NewsArticleGraphqlPresenterTestCase
test "presents a description" do
assert_equal "Summary of the news", presented_item.description
end

test "presents a body" do
assert_equal "Some text", presented_item.body
end

test "presents a readable first published date" do
assert_equal "25 December 2016", presented_item.published
end

test "presents the locale" do
assert_equal "en", presented_item.locale
end

test "presents historically political" do
assert presented_item.historically_political?
end
end
end
7 changes: 7 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,10 @@ def single_page_notification_button_ga4_tracking(index_link, section)
}
end
end

def fetch_graphql_fixture(filename)
json = File.read(
Rails.root.join("test", "fixtures", "graphql", "#{filename}.json"),
)
JSON.parse(json)
end

0 comments on commit 43a748e

Please sign in to comment.