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.
  • Loading branch information
brucebolt committed Dec 23, 2024
1 parent b7ffb92 commit 90f8d4d
Show file tree
Hide file tree
Showing 9 changed files with 308 additions and 1 deletion.
32 changes: 31 additions & 1 deletion app/controllers/content_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,47 @@ def set_guide_draft_access_token
end

def load_content_item
@content_item = if use_graphql?
graphql_response = Services
.publishing_api
.graphql_content_item(Graphql::NewsArticleQuery.new(content_item_path).query)

if graphql_response["schema_name"] == "news_article"
PresenterBuilder.new(
graphql_response,
content_item_path,
view_context,
).presenter
else
load_content_item_from_content_store
end
else
load_content_item_from_content_store
end
end

def load_content_item_from_content_store
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(
PresenterBuilder.new(
content_item,
content_item_path,
view_context,
).presenter
end

def use_graphql?
if params.include?(:graphql) && params[:graphql] == "true"
true
elsif params.include?(:graphql) && params[:graphql] == "false"
false
else
Features.graphql_feature_enabled?
end
end

def ordered_related_items(links)
return [] if links["ordered_related_items_overrides"].present?

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(
base_path: "#{@base_path}",
content_store: "live",
) {
... on NewsArticle {
base_path
description
details
document_type
first_published_at
links {
available_translations {
base_path
locale
}
government {
details {
current
}
title
}
organisations {
base_path
content_id
title
}
people {
base_path
content_id
title
}
taxons {
base_path
content_id
document_type
phase
title
links {
parent_taxons {
base_path
content_id
document_type
phase
title
}
}
}
topical_events {
base_path
content_id
title
}
world_locations {
base_path
content_id
title
}
}
locale
schema_name
title
}
}
}
QUERY
end
end
52 changes: 52 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 @@ -103,6 +105,56 @@ 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)
base_path = "content-item"

graphql_schema_name_fixture = fetch_graphql_fixture("news_article_schema_name")
stub_publishing_api_graphql_content_item(Graphql::SchemaNameQuery.new("/#{base_path}").query, graphql_schema_name_fixture)

graphql_fixture = fetch_graphql_fixture("news_article")
stub_publishing_api_graphql_content_item(Graphql::NewsArticleQuery.new("/#{base_path}").query, graphql_fixture)

get :show,
params: {
path: base_path,
}

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

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")
base_path = path_for(content_item)

graphql_schema_name_fixture = fetch_graphql_fixture("case_study_schema_name")
stub_publishing_api_graphql_content_item(Graphql::SchemaNameQuery.new("/#{base_path}").query, graphql_schema_name_fixture)

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

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

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

assert_response :success
end

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

Expand Down
9 changes: 9 additions & 0 deletions test/fixtures/graphql/case_study_schema_name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"data":
{
"edition":
{
"schema_name": "case_study"
}
}
}
74 changes: 74 additions & 0 deletions test/fixtures/graphql/news_article.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"data":
{
"edition":
{
"base_path": "/government/news/announcement",
"description": "Summary of the news",
"details": {
"body": "Some text",
"political": "true"
},
"document_type": "news_story",
"first_published_at": "2016-12-25T01:02:03+00:00",
"links": {
"available_translations": [
{
"base_path": "/government/news/announcement",
"locale": "en"
}
],
"government": [
{
"details": {
"current": false
},
"title": "A government"
}
],
"organisations": [
{
"base_path": "/organisation-1",
"title": "An organisation"
}
],
"people": [
{
"base_path": "/person-1",
"title": "A person"
}
],
"taxons": [
{
"base_path": "/taxon-2",
"content_id": "8fa1fa2f-bcce-4cde-98fb-308514c35c63",
"title": "Taxon 2",
"links": {
"parent_taxons": [
{
"base_path": "/taxon-1",
"content_id": "9de167ce-6c4f-40b1-a45e-e3160d75556e",
"title": "Taxon 1"
}
]
}
}
],
"topical_events": [
{
"base_path": "/topical-event-1",
"title": "A topical event"
}
],
"world_locations": [
{
"base_path": "/world-location-1",
"title": "A world location"
}
]
},
"schema_name": "news_article",
"title": "Generic news article"
}
}
}
9 changes: 9 additions & 0 deletions test/fixtures/graphql/news_article_schema_name.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"data":
{
"edition":
{
"schema_name": "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_content_item("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_content_item(type)
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
11 changes: 11 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -280,3 +280,14 @@ 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

def fetch_graphql_content_item(filename)
fetch_graphql_fixture(filename).dig("data", "edition")
end

0 comments on commit 90f8d4d

Please sign in to comment.