diff --git a/app/models/benchmarking_ab_test_request.rb b/app/models/benchmarking_ab_test_request.rb
new file mode 100644
index 000000000..58d3c147e
--- /dev/null
+++ b/app/models/benchmarking_ab_test_request.rb
@@ -0,0 +1,22 @@
+class BenchmarkingAbTestRequest
+ attr_accessor :requested_variant
+
+ delegate :analytics_meta_tag, to: :requested_variant
+
+ def initialize(request)
+ dimension = Rails.application.config.benchmarking_ab_test_dimension
+ ab_test = GovukAbTesting::AbTest.new(
+ "Benchmarking",
+ dimension: dimension
+ )
+ @requested_variant = ab_test.requested_variant(request.headers)
+ end
+
+ def in_benchmarking?
+ requested_variant.variant_b?
+ end
+
+ def set_response_vary_header(response)
+ requested_variant.configure_response(response)
+ end
+end
diff --git a/app/presenters/specialist_document_presenter.rb b/app/presenters/specialist_document_presenter.rb
index feaa9f0d2..6c13c6c9b 100644
--- a/app/presenters/specialist_document_presenter.rb
+++ b/app/presenters/specialist_document_presenter.rb
@@ -15,8 +15,132 @@ def title_and_context
end
end
+ def metadata
+ super.tap do |m|
+ facets_with_values.each do |facet|
+ m[:other][facet['name']] = join_facets(facet)
+ end
+ end
+ end
+
+ def document_footer
+ super.tap do |m|
+ m[:other_dates] = {}
+ facets_with_values.each do |facet|
+ type = facet['type'] == 'date' ? :other_dates : :other
+ m[type][facet['name']] = join_facets(facet)
+ end
+ end
+ end
+
+ def breadcrumbs
+ return [] unless finder
+
+ [
+ {
+ title: "Home",
+ url: "/",
+ },
+ {
+ title: finder['title'],
+ url: finder['base_path'],
+ }
+ ]
+ end
+
private
+ def join_facets(facet)
+ facet['values'].join(', ')
+ end
+
+ def finder
+ first_finder = content_item.dig("links", "finder", 0)
+ Airbrake.notify("Finder not found",
+ error_message:
+ "All specialist documents should have at least one finder"
+ ) if first_finder.nil?
+ first_finder
+ end
+
+ def facets
+ return nil unless finder
+ finder.dig('details', 'facets')
+ end
+
+ def facet_values
+ # Metadata is a required field
+ content_item["details"]["metadata"]
+ end
+
+ def facets_with_values
+ return [] unless facets && facet_values.any?
+ only_facets_with_values = facets.select { |f| facet_values[f['key']] }
+
+ only_facets_with_values.map do |facet|
+ facet_key = facet['key']
+ # Cast all values into an array
+ values = [facet_values[facet_key]].flatten
+
+ facet['values'] = case facet['type']
+ when 'date'
+ friendly_facet_date(values)
+ when 'text'
+ friendly_facet_text(facet, values)
+ else
+ values
+ end
+
+ facet
+ end
+ end
+
+ def friendly_facet_date(dates)
+ dates.map { |date| display_date(date) }
+ end
+
+ def friendly_facet_text(facet, values)
+ if facet['allowed_values'] && facet['allowed_values'].any?
+ check_allowed_values(facet, values)
+ facet_blocks(facet, values)
+ else
+ values
+ end
+ end
+
+ def check_allowed_values(facet, values)
+ allowed_values = facet['allowed_values'].map { |av| av["value"] }
+ not_allowed = "facet value not in list of allowed values"
+
+ values.each do |v|
+ Airbrake.notify(not_allowed) unless allowed_values.include?(v)
+ end
+ end
+
+ # the facet value comes back bare, and without a label
+ # so we use the value in the url, and cross reference
+ # the allowed_values to get the label ##funky
+ def facet_blocks(facet, values)
+ values.map do |value|
+ values_with_label = facet["allowed_values"]
+ allowed_value = values_with_label.select { |av|
+ av["value"] == value
+ }.first
+ facet_block(facet, allowed_value)
+ end
+ end
+
+ def facet_block(facet, allowed_value)
+ return allowed_value['label'] unless facet['filterable']
+ facet_link(allowed_value['label'], allowed_value['value'], facet['key'])
+ end
+
+ def facet_link(label, value, key)
+ finder_base_path = finder['base_path']
+ link_to(label, "#{finder_base_path}?#{key}%5B%5D=#{value}")
+ end
+
+
# first_published_at does not have reliable data
# at time of writing dates could be after public_updated_at
# details.first_public_at is not provided
@@ -27,4 +151,14 @@ def first_public_at
changes = reverse_chronological_change_history
changes.any? ? changes.last[:timestamp] : nil
end
+
+ # specialist document change history can have a modified date that is
+ # slightly different to the public_updated_at, eg milliseconds different
+ # this means the direct comparison in updatable gives a false positive
+ # Use change_history as specialist-frontend did
+ #
+ # Can be removed when first_published_at is reliable
+ def any_updates?
+ change_history.size > 1
+ end
end
diff --git a/test/integration/specialist_document_test.rb b/test/integration/specialist_document_test.rb
index bb48f43cd..346fee9eb 100644
--- a/test/integration/specialist_document_test.rb
+++ b/test/integration/specialist_document_test.rb
@@ -1,6 +1,13 @@
require 'test_helper'
class SpecialistDocumentTest < ActionDispatch::IntegrationTest
+ test "random but valid items do not error" do
+ setup_and_visit_random_content_item(document_type: 'aaib_report')
+ setup_and_visit_random_content_item(document_type: 'raib_report')
+ setup_and_visit_random_content_item(document_type: 'tax_tribunal_decision')
+ setup_and_visit_random_content_item(document_type: 'cma_case')
+ end
+
test "renders title, description and body" do
setup_and_visit_content_item('aaib-reports')
@@ -33,13 +40,65 @@ class SpecialistDocumentTest < ActionDispatch::IntegrationTest
within shared_component_selector("document_footer") do
component_args = JSON.parse(page.text)
history = component_args.fetch("history")
-
assert_equal history.first["note"], @content_item["details"]["change_history"].last["note"]
assert_equal history.last["note"], @content_item["details"]["change_history"].first["note"]
assert_equal history.size, @content_item["details"]["change_history"].size
end
end
+ test "renders text facets correctly" do
+ setup_and_visit_content_item('countryside-stewardship-grants')
+
+ def test_meta(component)
+ within shared_component_selector(component) do
+ component_args = JSON.parse(page.text)
+ assert_equal component_args["other"]["Grant type"], "Option"
+ assert_equal component_args["other"]["Tiers or standalone items"],
+ ["Higher Tier",
+ "Mid Tier"].join(", ")
+ assert_equal component_args["other"]["Land use"],
+ ["Arable land",
+ "Wildlife package",
+ "Water quality",
+ "Wildlife package"].join(", ")
+ assert_equal component_args["other"]["Funding (per unit per year)"],
+ "More than £500"
+ end
+ end
+ test_meta("document_footer")
+ test_meta("metadata")
+ end
+
+ test "renders date facets correctly" do
+ setup_and_visit_content_item('drug-device-alerts')
+
+ within shared_component_selector("document_footer") do
+ component_args = JSON.parse(page.text)
+ assert_equal component_args["other_dates"]["Issued"], "6 July 2015"
+ end
+
+ within shared_component_selector("metadata") do
+ component_args = JSON.parse(page.text)
+ assert_equal component_args["other"]["Issued"], "6 July 2015"
+ end
+ end
+
+
+ test "renders when no facet or finder" do
+ setup_and_visit_content_item('business-finance-support-scheme')
+ assert_has_component_metadata_pair("first_published", "9 July 2015")
+
+ within shared_component_selector("document_footer") do
+ component_args = JSON.parse(page.text)
+ assert_equal component_args["other_dates"], {}
+ end
+
+ within shared_component_selector("metadata") do
+ component_args = JSON.parse(page.text)
+ assert_equal component_args["other"], {}
+ end
+ end
+
test "renders a contents list" do
setup_and_visit_content_item('aaib-reports')
diff --git a/test/presenters/specialist_document_presenter_test.rb b/test/presenters/specialist_document_presenter_test.rb
index a861c398a..20926d6f0 100644
--- a/test/presenters/specialist_document_presenter_test.rb
+++ b/test/presenters/specialist_document_presenter_test.rb
@@ -26,6 +26,31 @@ class PresentedSpecialistDocument < SpecialistDocumentTestCase
assert presented_item('aaib-reports').is_a?(ContentsList)
end
+ test 'presents updates based on change history' do
+ example = schema_item('aaib-reports')
+ example["details"]["change_history"] = [
+ {
+ "note" => "First published",
+ "public_timestamp" => "2003-03-03"
+ }
+ ]
+
+ refute present_example(example).updated
+
+ example["details"]["change_history"] = [
+ {
+ "note" => "First published",
+ "public_timestamp" => "2003-03-03"
+ },
+ {
+ "note" => "Modified since first published",
+ "public_timestamp" => "2013-04-05"
+ }
+ ]
+
+ assert present_example(example).updated
+ end
+
test 'presents the published date using the oldest date in the change history' do
example = schema_item('aaib-reports')
example["first_published_at"] = "2001-01-01"
@@ -58,4 +83,144 @@ class PresentedSpecialistDocument < SpecialistDocumentTestCase
assert_equal title_component_params, presented_item('aaib-reports').title_and_context
end
end
+
+ class PresentedSpecialistDocumentWithFinderFacets < SpecialistDocumentTestCase
+ def example_with_finder_facets(facets = [], values = {})
+ example = schema_item('aaib-reports')
+ example_finder = {
+ "base_path" => "/finder-base-path",
+ "title" => "Finder title",
+ "details" => {
+ "document_noun" => "case",
+ "filter" => {
+ "document_type" => "cma_case"
+ },
+ "format_name" => "Competition and Markets Authority case",
+ "facets" => facets,
+ },
+ }
+
+ example['details']['metadata'] = values
+ example['links']['finder'] = [example_finder]
+ example
+ end
+
+ def example_facet(overrides = {})
+ {
+ "name" => "Facet name",
+ "key" => "facet-key",
+ "type" => "text",
+ "filterable" => false
+ }.merge(overrides)
+ end
+
+ test 'includes non-filterable facet as text in metadata and document footer' do
+ values = { "facet-key" => "document-value" }
+ example = example_with_finder_facets([example_facet], values)
+
+ presented = present_example(example)
+ assert_equal "document-value", presented.metadata[:other]["Facet name"]
+ assert_equal "document-value", presented.document_footer[:other]["Facet name"]
+ end
+
+ test 'includes friendly label for facet value in metadata and document footer' do
+ overrides = {
+ "allowed_values" => [
+ {
+ "label" => "Document value from label",
+ "value" => "document-value"
+ }
+ ]
+ }
+
+ values = { "facet-key" => "document-value" }
+ example = example_with_finder_facets([example_facet(overrides)], values)
+
+ presented = present_example(example)
+ assert_equal "Document value from label", presented.metadata[:other]["Facet name"]
+ assert_equal "Document value from label", presented.document_footer[:other]["Facet name"]
+ end
+
+ test 'handles multiple values for facets' do
+ overrides = {
+ "allowed_values" => [
+ {
+ "label" => "One",
+ "value" => "one"
+ },
+ {
+ "label" => "Two",
+ "value" => "two"
+ }
+ ]
+ }
+
+ values = { "facet-key" => %w{one two} }
+ example = example_with_finder_facets([example_facet(overrides)], values)
+
+ presented = present_example(example)
+ assert_equal "One, Two", presented.metadata[:other]["Facet name"]
+ assert_equal "One, Two", presented.document_footer[:other]["Facet name"]
+ end
+
+ test 'creates links for filterable friendly values' do
+ overrides = {
+ "filterable" => true,
+ "allowed_values" => [
+ {
+ "label" => "Something",
+ "value" => "something"
+ }
+ ]
+ }
+
+ values = { "facet-key" => "something" }
+ example = example_with_finder_facets([example_facet(overrides)], values)
+
+ presented = present_example(example)
+ expected_link = "Something"
+ assert_equal expected_link, presented.metadata[:other]["Facet name"]
+ assert_equal expected_link, presented.document_footer[:other]["Facet name"]
+ end
+
+ test 'includes friendly dates for date facets in metadata' do
+ overrides = { "type" => "date" }
+ values = { "facet-key" => "2010-01-01" }
+ example = example_with_finder_facets([example_facet(overrides)], values)
+
+ presented_metadata = present_example(example).metadata[:other]
+ assert_equal "1 January 2010", presented_metadata["Facet name"]
+ end
+
+ test 'includes friendly dates in other_dates for date facets in document footer' do
+ overrides = { "type" => "date" }
+ values = { "facet-key" => "2010-01-01" }
+ example = example_with_finder_facets([example_facet(overrides)], values)
+
+ presented_metadata = present_example(example).document_footer[:other_dates]
+ assert_equal "1 January 2010", presented_metadata["Facet name"]
+ end
+
+ test 'breadcrumbs' do
+ assert_equal [
+ {
+ title: "Home",
+ url: "/"
+ },
+ {
+ title: "Finder title",
+ url: "/finder-base-path"
+ }
+ ], present_example(example_with_finder_facets).breadcrumbs
+ end
+
+ test 'no breadcrumbs render with no finder' do
+ example = schema_item('aaib-reports')
+ example['links']['finder'] = []
+ assert_equal [], present_example(example).breadcrumbs
+
+ example['links'].delete('finder')
+ assert_equal [], present_example(example).breadcrumbs
+ end
+ end
end