diff --git a/app/presenters/content_item_presenter.rb b/app/presenters/content_item_presenter.rb index 6b32ba825..6f5adf6c5 100644 --- a/app/presenters/content_item_presenter.rb +++ b/app/presenters/content_item_presenter.rb @@ -5,6 +5,7 @@ class ContentItemPresenter attr_reader :content_item, :requested_content_item_path, :base_path, + :slug, :title, :description, :schema_name, @@ -21,6 +22,7 @@ def initialize(content_item, requested_content_item_path = nil) @content_item = content_item @requested_content_item_path = requested_content_item_path @base_path = content_item["base_path"] + @slug = @base_path.delete_prefix("/") if @base_path @title = content_item["title"] @description = content_item["description"] @schema_name = content_item["schema_name"] diff --git a/app/presenters/machine_readable/yaml_faq_page_schema_presenter.rb b/app/presenters/machine_readable/yaml_faq_page_schema_presenter.rb new file mode 100644 index 000000000..52e70ceb6 --- /dev/null +++ b/app/presenters/machine_readable/yaml_faq_page_schema_presenter.rb @@ -0,0 +1,69 @@ +module MachineReadable + class YamlFaqPageSchemaPresenter + attr_reader :content_item, :config_file + + def self.configured?(content_item) + File.exist?(config_path(content_item)) + end + + def self.config_path(content_item) + CONFIG_PATH.join(content_item.slug + ".yml").to_s + end + + def initialize(content_item) + @content_item = content_item + @config_file = YAML.load_file(YamlFaqPageSchemaPresenter.config_path(content_item)) + end + + def structured_data + # http://schema.org/FAQPage + { + "@context" => "http://schema.org", + "@type" => "FAQPage", + "headline" => config_file["title"], + "description" => config_file["preamble"], + "publisher" => { + "@type" => "Organization", + "name" => "GOV.UK", + "url" => "https://www.gov.uk", + "logo" => { + "@type" => "ImageObject", + "url" => logo_url, + }, + }, + } + .merge(main_entity) + end + + private + + CONFIG_PATH = Rails.root.join("config/machine_readable/").freeze + + def main_entity + { + "mainEntity" => questions_and_answers, + } + end + + def questions_and_answers + config_file["faqs"].each_with_index.map do |faq| + { + "@type" => "Question", + "name" => faq["question"], + "acceptedAnswer" => { + "@type" => "Answer", + "text" => faq["answer"], + }, + } + end + end + + def logo_url + image_url("govuk_publishing_components/govuk-logo.png") + end + + def image_url(image_file) + ActionController::Base.helpers.asset_url(image_file, type: :image) + end + end +end diff --git a/app/views/content_items/guide_single.html.erb b/app/views/content_items/guide_single.html.erb index e0030c800..248981f47 100644 --- a/app/views/content_items/guide_single.html.erb +++ b/app/views/content_items/guide_single.html.erb @@ -6,9 +6,11 @@ ) %> <% end %> +<% if MachineReadable::YamlFaqPageSchemaPresenter.configured?(@content_item) %> +<% end %> <% content_for :simple_header, true %> diff --git a/config/machine_readable/voting-in-the-uk.yml b/config/machine_readable/voting-in-the-uk.yml new file mode 100644 index 000000000..f53b49af7 --- /dev/null +++ b/config/machine_readable/voting-in-the-uk.yml @@ -0,0 +1,84 @@ +title: "How to vote" +preamble: > +
You need to register to vote before you can vote in UK elections or referendums.
+If you’re eligible, you can vote in person on the day of the election at a named polling station. You can also apply for a postal or proxy vote instead.
+ +faqs: + - question: Ways of voting + answer: > +You can vote:
+You cannot vote online in any elections.
+ + - question: Eligibility to vote + answer: > +You can vote when you’re:
+You vote in person at a polling station (usually in a public building, such as a school or local hall).
+You’ll be sent a poll card just before an election telling you when to vote and at which polling station. You can only vote at the polling station location on your card.
+If you have not received a poll card but think you should, contact your local Electoral Registration Office.
+You can still vote if you’ve lost your card.
+ + - question: When you can vote + answer: > +Polling stations are open from 7am to 10pm on the day of the election (‘polling day’).
+ + - question: ID you need to bring + answer: > +If you live in England, Wales or Scotland you do not need to bring any identification to vote.
+You will need to show photo ID to vote in Northern Ireland (your passport, driving licence, Electoral Identity Card or certain kinds of Translink Smartpass).
+ + - question: Voting by post + answer: > +You must apply for a postal vote if you want to vote by post, for example if:
+You do not need to give a reason unless you’re voting in Northern Ireland.
+ + - question: Voting by proxy + answer: > +If you’re unable to vote in person you can ask someone to vote on your behalf. This is called a proxy vote.
+You can only apply for a proxy vote under certain circumstances, including:
+Apply for a proxy vote using a paper form. You need to send it to your local Electoral Registration Office.
+Usually, you need to apply for a proxy vote at least 6 working days before election day if you want to vote in England, Scotland or Wales.
+There’s a different form to apply to vote by proxy in Northern Ireland. Apply at least 14 working days before election day.
+ + - question: Voting from abroad + answer: > +If you’re abroad on election day you need to make arrangements in advance. Apply to vote by proxy if the election is less than 2 weeks away and you have not made the arrangements yet.
+How you vote when you’re abroad depends on:
+You can vote by post or proxy if you’ll be abroad temporarily on election day, for example on holiday or a work trip.
+You can arrange:
+Your postal ballot will be sent to the address you’ve chosen no earlier than 16 days before the election. You need to return your ballot before 10pm on polling day.
+There’s a different process to apply to vote by post or proxy if you live in Northern Ireland and will be abroad temporarily on election day.
+If you vote by post you must return your ballot before going abroad (you cannot post it from outside the UK).
diff --git a/test/integration/guide_test.rb b/test/integration/guide_test.rb index d59ac5f32..61596ac0b 100644 --- a/test/integration/guide_test.rb +++ b/test/integration/guide_test.rb @@ -112,6 +112,38 @@ class GuideTest < ActionDispatch::IntegrationTest assert_nil faq_schema end + # The schema config is in /config/machine_readable/voting-in-the-uk.yml + test "voting in the UK guide shows hard coded FAQ schema" do + setup_and_visit_voting_guide + + faq_schema = find_structured_data(page, "FAQPage") + q_and_as = faq_schema["mainEntity"] + + assert_equal faq_schema["@type"], "FAQPage" + assert_equal faq_schema["headline"], "How to vote" + assert_equal faq_schema["description"], "You need to register to vote before you can vote in UK elections or referendums.
If you’re eligible, you can vote in person on the day of the election at a named polling station. You can also apply for a postal or proxy vote instead.
\n" + + assert_equal 8, q_and_as.count + end + + test "voting in the UK guide shows all chapters on a single page" do + content_item = setup_and_visit_voting_guide + part_titles = content_item["details"]["parts"].map { |part| part["title"] } + + part_titles.each do |part_title| + assert page.has_css? "h1", text: part_title + end + end + + def setup_and_visit_voting_guide + @content_item = get_content_example("guide").tap do |item| + item["base_path"] = "/voting-in-the-uk" + item["content_id"] = "9315bc67-33e7-42e9-8dea-e022f56dabfa" + content_store_has_item(item["base_path"], item.to_json) + visit_with_cachebust(item["base_path"]) + end + end + def setup_and_visit_part_in_guide @content_item = get_content_example("guide").tap do |item| chapter_path = "#{item['base_path']}/key-stage-1-and-2"