Skip to content

Commit

Permalink
Merge pull request #3447 from alphagov/graphql-news-articles
Browse files Browse the repository at this point in the history
Render news articles using GraphQL
  • Loading branch information
brucebolt authored Dec 23, 2024
2 parents 46e18cb + 3f85edc commit 582359c
Show file tree
Hide file tree
Showing 8 changed files with 290 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
5 changes: 5 additions & 0 deletions app/lib/features.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
class Features
def self.graphql_feature_enabled?
ENV["GRAPHQL_FEATURE_FLAG"]
end
end
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
47 changes: 47 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,51 @@ 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_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::NewsArticleQuery.new("/#{base_path}").query },
times: 1

assert_not_requested :get, "#{content_store_endpoint}/content/#{base_path}"

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_fixture = fetch_graphql_fixture("news_article")
graphql_fixture["data"]["edition"]["schema_name"] = "case_study"
stub_publishing_api_graphql_content_item(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 }

assert_requested :get, "#{content_store_endpoint}/content/#{base_path}",
times: 1

assert_response :success
end

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

Expand Down
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"
}
}
}
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 582359c

Please sign in to comment.