Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add facet metadata to specialist documents #304

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 22 additions & 0 deletions 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
134 changes: 134 additions & 0 deletions app/presenters/specialist_document_presenter.rb
Expand Up @@ -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)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should include the not allowed value in the Airbrake notification for easier debugging.

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
Expand All @@ -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
61 changes: 60 additions & 1 deletion 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')

Expand Down Expand Up @@ -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"], "<a href=\"/countryside-stewardship-grants?grant_type%5B%5D=option\">Option</a>"
assert_equal component_args["other"]["Tiers or standalone items"],
["<a href=\"/countryside-stewardship-grants?tiers_or_standalone_items%5B%5D=higher-tier\">Higher Tier</a>",
"<a href=\"/countryside-stewardship-grants?tiers_or_standalone_items%5B%5D=mid-tier\">Mid Tier</a>"].join(", ")
assert_equal component_args["other"]["Land use"],
["<a href=\"/countryside-stewardship-grants?land_use%5B%5D=arable-land\">Arable land</a>",
"<a href=\"/countryside-stewardship-grants?land_use%5B%5D=wildlife-package\">Wildlife package</a>",
"<a href=\"/countryside-stewardship-grants?land_use%5B%5D=water-quality\">Water quality</a>",
"<a href=\"/countryside-stewardship-grants?land_use%5B%5D=wildlife-package\">Wildlife package</a>"].join(", ")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is wildlife package included twice?

assert_equal component_args["other"]["Funding (per unit per year)"],
"<a href=\"/countryside-stewardship-grants?funding_amount%5B%5D=more-than-500\">More than £500</a>"
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')

Expand Down