Skip to content

Commit 27584d7

Browse files
committed
DGUK-290 Fix flaky tests
Run markdown render in spec/rails_helper. This is because feature tests require the app/views/generated views to exist. Refactor markdown to be more resilliant to failures Add tests
1 parent 4f25ed1 commit 27584d7

19 files changed

Lines changed: 488 additions & 245 deletions

File tree

app/services/dgu/collections_service.rb

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
module Dgu
22
class CollectionsService
3-
COLLECTIONS_LOCATION = Rails.configuration.x.generated_collections_location
4-
COLLECTION_PAGES = Rails.configuration.x.collection_pages.deep_dup
5-
63
attr_reader :collection, :page_name, :collection_pages
74

85
def initialize(collection, page_name = nil)
@@ -11,7 +8,7 @@ def initialize(collection, page_name = nil)
118
end
129

1310
@collection = collection
14-
@collection_pages = COLLECTION_PAGES[collection].map do |collection_page|
11+
@collection_pages = collections_config[collection].map do |collection_page|
1512
{
1613
url: "/collections/#{@collection}/#{collection_page[:slug]}",
1714
slug: collection_page[:slug],
@@ -34,18 +31,6 @@ def image_path
3431
"v2/collections/badge-#{collection}.png"
3532
end
3633

37-
def collections_slugs
38-
Dir.entries(Rails.root.join(COLLECTIONS_LOCATION)).sort
39-
.reject { |files|
40-
[".", ".."].include?(files)
41-
}.map do |collection|
42-
Struct.new(:slug, :title).new(
43-
collection,
44-
collection.gsub("-", " ").humanize,
45-
)
46-
end
47-
end
48-
4934
def view_template_path
5035
"generated/collections/#{collection}/#{page}"
5136
end
@@ -72,8 +57,22 @@ def title
7257

7358
private
7459

60+
def collections_config
61+
Rails.configuration.x.collection_pages
62+
end
63+
64+
def collections_slugs
65+
Dir.children(Rails.root.join(collections_location)).sort
66+
.map do |collection|
67+
Struct.new(:slug, :title).new(
68+
collection,
69+
collection.gsub("-", " ").humanize,
70+
)
71+
end
72+
end
73+
7574
def pages
76-
Dir.entries(Rails.root.join(COLLECTIONS_LOCATION, @collection)).sort
75+
Dir.entries(Rails.root.join(collections_location, @collection)).sort
7776
.reject { |entry|
7877
[".", ".."].include?(entry)
7978
}
@@ -85,15 +84,19 @@ def pages
8584
def page?(page = nil)
8685
return true if page.blank?
8786

88-
Rails.root.join(COLLECTIONS_LOCATION, @collection, "#{page}.html.erb").exist?
87+
Rails.root.join(collections_location, @collection, "#{page}.html.erb").exist?
8988
end
9089

9190
def collection?(collection)
92-
Rails.root.join(COLLECTIONS_LOCATION, collection).exist?
91+
Rails.root.join(collections_location, collection).exist?
9392
end
9493

9594
def current_page_index
9695
@collection_pages.index { |page| page[:slug] == @page_name }
9796
end
97+
98+
def collections_location
99+
Rails.configuration.x.generated_collections_location
100+
end
98101
end
99102
end
Lines changed: 53 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,74 @@
11
require Rails.root.join("app/services/dgu/markdown")
22

3-
def format_date(date_str)
4-
Date.iso8601(date_str).strftime("%-d/%-m/%Y")
5-
rescue ArgumentError, TypeError
6-
nil
3+
def format_date(date)
4+
return nil if date.blank?
5+
6+
Date.iso8601(date).strftime("%-d/%-m/%Y")
7+
end
8+
9+
def process_visualisation_data(chart_json)
10+
return chart_json unless chart_json["visualisation_type"] == "line"
11+
12+
point_shapes = %w[circle triangle rect rectRot]
13+
14+
chart_json["series"].each do |series|
15+
data_size = series["data"].keys.size
16+
next if data_size.zero?
17+
18+
series["dataset"] = {
19+
pointRadius: Array.new(data_size - 1, 0) << 4,
20+
pointStyle: Array.new(data_size, point_shapes.pop || "circle"),
21+
}
22+
end
23+
24+
chart_json
725
end
826

927
namespace :markdown do
1028
desc "Convert markdown to static html pages"
1129
task render: :environment do
12-
markdown_input = Rails.configuration.x.markdown_collections_location_glob
30+
markdown_input_glob = Rails.configuration.x.markdown_collections_location_glob
1331
markdown_output_dir = Rails.configuration.x.markdown_collections_output_location
1432
visualisations_data_location = Rails.configuration.x.visualisations_data_location
1533

16-
input_root = Pathname.new(Rails.root.join(markdown_input.split("*").first)).cleanpath
17-
markdowns = Dir.glob(Rails.root.join(markdown_input))
18-
34+
input_root = Pathname.new(Rails.root.join(markdown_input_glob.split("*").first)).cleanpath
1935
output_directory = Rails.root.join(markdown_output_dir)
36+
2037
FileUtils.mkdir_p(output_directory)
2138

39+
markdowns = Dir.glob(Rails.root.join(markdown_input_glob))
40+
2241
if markdowns.empty?
23-
puts("No markdown files were found")
42+
puts("No markdown files were found at #{markdown_input_glob}")
43+
next
2444
end
2545

2646
markdowns.each do |markdown_file|
2747
parsed_markdown = FrontMatterParser::Parser.parse_file(markdown_file)
2848
front_matter = parsed_markdown.front_matter
49+
50+
if front_matter["status"] != "for-publication"
51+
puts("Skipping markdown file #{markdown_file} as 'status' is missing or not 'for-publication'")
52+
next
53+
end
54+
2955
content = parsed_markdown.content
3056
html_body = Dgu::Markdown.render(content)
3157

3258
if html_body.strip.empty?
33-
puts("Skipping markdown file #{markdown_file} no body content present")
59+
puts("Skipping markdown file #{markdown_file} - no body content present")
3460
next
3561
end
3662

37-
if front_matter["visualisation-data"]
38-
chart_data = File.read(Rails.root.join("#{visualisations_data_location}/#{front_matter['visualisation-data']}")) if front_matter["visualisation-data"]
39-
chart_json = JSON.parse(chart_data)
40-
41-
if chart_json["visualisation_type"] == "line"
42-
point_shapes = %w[circle triangle rect rectRot]
63+
chart_json = nil
64+
if front_matter["visualisation-data"].present?
65+
chart_path = Rails.root.join(visualisations_data_location, front_matter["visualisation-data"])
4366

44-
chart_json["series"].map! do |series|
45-
series["dataset"] = {
46-
pointRadius: Array.new(series["data"].keys.size - 1, 0) << 4,
47-
pointStyle: Array.new(series["data"].keys.size, point_shapes.pop || "circle"),
48-
}
49-
series
50-
end
67+
if File.exist?(chart_path)
68+
chart_data = File.read(chart_path)
69+
chart_json = process_visualisation_data(JSON.parse(chart_data))
70+
else
71+
puts("Warning: Visualisation data not found for #{markdown_file} - #{chart_path}")
5172
end
5273
end
5374

@@ -67,20 +88,18 @@ namespace :markdown do
6788
contact: front_matter["contact"],
6889
body: html_body.html_safe,
6990
collection_topic_path: collection_topic_path,
70-
chart_data: chart_json || nil,
91+
chart_data: chart_json,
7192
}
7293

73-
if front_matter["status"].nil? || front_matter["status"] != "for-publication"
74-
puts("Skipping markdown file #{markdown_file} as 'status' is missing or not 'for-publication' ")
75-
next
76-
end
77-
7894
path = Pathname.new(markdown_file)
7995
relative_path = path.relative_path_from(input_root).sub_ext(".html.erb")
80-
output_path = output_directory / relative_path
96+
output_path = output_directory.join(relative_path)
97+
8198
FileUtils.mkdir_p(output_path.dirname)
8299

83-
puts("Render #{path.basename} to => #{output_path}")
100+
unless Rails.env.test?
101+
puts("Rendering #{path.basename} to => #{output_path}")
102+
end
84103

85104
html = ApplicationController.renderer.render(
86105
partial: "v2/collection/content",
@@ -90,9 +109,10 @@ namespace :markdown do
90109

91110
File.write(output_path, html)
92111
rescue StandardError => e
93-
puts("error processing #{markdown_file}")
94-
puts e
112+
puts("Error processing #{markdown_file}: #{e.message}")
113+
puts(e.backtrace.first(3).join("\n"))
95114
end
115+
96116
puts("Completed rendering markdown to html files")
97117
end
98118
end

spec/features/v2/charts_spec.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
require "rails_helper"
22

33
RSpec.describe "Charts", type: :system, js: true do
4+
# Setup and teardown for generated views is handled globally in rails_helper.rb
5+
46
scenario "I can see a single series line chart on a collection page" do
57
given_i_visit_a_collection_page_with_a_single_series_line_chart
68
then_i_should_see_a_line_chart_with_expected_data

spec/features/v2/collections_spec.rb

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,7 @@
11
require "rails_helper"
22

33
RSpec.feature "collections", type: :feature do
4-
before(:all) do
5-
Rake.application.rake_require("tasks/markdown_to_static_html")
6-
Rake::Task.define_task(:environment)
7-
Rake::Task["markdown:render"].invoke
8-
end
9-
10-
after(:all) do
11-
output_directory = Rails.configuration.x.markdown_collections_output_location
12-
FileUtils.rm_rf(output_directory)
13-
end
4+
# Setup and teardown for generated views is handled globally in rails_helper.rb
145

156
scenario "I visit a collection page" do
167
given_i_am_on_a_collection_page
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Page One</h1>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Page Two</h1>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
<h1 class="govuk-heading-l datagovuk-heading-l">Inflation</h1>
3+
4+
<section class="govuk-section datagovuk-section">
5+
<p class="govuk-body-m datagovuk-body">Explore various datasets about inflation and price indices published by the Office for National Statistics (ONS). You can download the data as a PNG, CSV or XLS file.</p>
6+
<p class="govuk-body-m datagovuk-body">Inflation refers to the rate at which the general level of prices for goods and services rises, while a price index measures the average change in prices over time. Measures of inflation and prices include consumer price inflation, producer price inflation and the House Price Index. </p>
7+
</section>
8+
9+
<section class="datagovuk-headline govuk-section datagovuk-section govuk-!-margin-top-8">
10+
11+
<h2 class="govuk-heading-m datagovuk-heading-m">Consumer Prices Index including owner occupiers&#39; housing costs - annual rate</h2>
12+
13+
<div class="govuk-grid-row line-chart">
14+
<div id="chart-1" style="height: 300px; width: 100%; text-align: center; color: #999; line-height: 300px; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">Loading...</div>
15+
<script nonce="/AwItmjN1ASeMELmxl4cAaPb9pr+EwWXcijfVmLjsmU=">
16+
(function() {
17+
if (document.documentElement.hasAttribute("data-turbolinks-preview")) return;
18+
if (document.documentElement.hasAttribute("data-turbo-preview")) return;
19+
20+
var createChart = function() { new Chartkick["LineChart"]("chart-1", [{"name":"Rate","color":"#000000","data":{"1989":5.7,"1990":8.0,"1991":7.5,"1992":4.6,"1993":2.6,"1994":2.2,"1995":2.7,"1996":2.9,"1997":2.2,"1998":1.8,"1999":1.7,"2000":1.2,"2001":1.6,"2002":1.5,"2003":1.4,"2004":1.4,"2005":2.1,"2006":2.5,"2007":2.4,"2008":3.5,"2009":2.0,"2010":2.5,"2011":3.8,"2012":2.6,"2013":2.3,"2014":1.5,"2015":0.4,"2016":1.0,"2017":2.6,"2018":2.3,"2019":1.7,"2020":1.0,"2021":2.5,"2022":7.9,"2023":6.8,"2024":3.3,"2025":3.9},"dataset":{"pointRadius":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],"pointStyle":["rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot"]}}], {"suffix":"%","round":2,"points":true,"dataset":{"empty":"No data available","tension":0.5,"pointRadius":0,"pointHoverRadius":10},"library":{"plugins":{"datalabels":{"display":false},"legend":{"display":false,"labels":{"color":"#5D5D5D","font":{"size":20,"family":"Inter, sans-serif","weight":"bold"},"padding":30,"usePointStyle":true}},"tooltip":{"bodyFont":{"size":20,"family":"Inter, sans-serif","weight":"bold"},"titleFont":{"size":20,"family":"Inter, sans-serif","weight":"bold"}}},"responsive":true,"layout":{"padding":{"top":20,"bottom":20,"left":20,"right":20}},"scales":{"y":{"min":0,"grid":{"display":true},"border":{"dash":[5,5]},"ticks":{"stepSize":2,"maxTicksLimit":10,"autoSkip":false,"font":{"size":20}}},"x":{"border":{"display":true},"ticks":{"font":{"size":20}}}}},"legend":"bottom"}); };
21+
if ("Chartkick" in window) {
22+
createChart();
23+
} else {
24+
window.addEventListener("chartkick:load", createChart, true);
25+
}
26+
})();
27+
</script>
28+
29+
</div>
30+
31+
32+
<p class="govuk-body datagovuk-body govuk-!-margin-top-4">
33+
<a href="/collections/business-and-economy/inflation/charts/inflation-1989-2025.csv" class="govuk-link datagovuk-link">Download the chart data</a>
34+
</p>
35+
</section>
36+
37+
<div class="govuk-inset-text datagovuk-feedback-inset-text">
38+
<p class="govuk-body datagovuk-body">
39+
Is this data useful?
40+
<a href="https://forms.office.com/e/9V26PNFQaR" class="govuk-link datagovuk-link">Give us feedback</a>
41+
</p>
42+
</div>
43+
44+
45+
46+
<section class="datagovuk-link datagovuk-section" aria-label="Get the data links">
47+
<section class="datagovuk-section">
48+
<h3 class="govuk-heading-m datagovuk-heading-m">Get the data</h3>
49+
<a role="button" class="govuk-button datagovuk-button" rel="nofollow" href="https://www.ons.gov.uk/economy/inflationandpriceindices">Inflation and price indices <span class="datagovuk-right-arrow">&#8594;</span></a>
50+
</section>
51+
<section class="datagovuk-section">
52+
<p class="govuk-body datagovuk-body datagovuk-!-colour-grey">The page was last updated 25/3/2026</p>
53+
</section>
54+
</section>
55+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
2+
<h1 class="govuk-heading-l datagovuk-heading-l">UK trade</h1>
3+
4+
<section class="govuk-section datagovuk-section">
5+
<p class="govuk-body-m datagovuk-body">Explore statistics that set out the UK’s economic relationship with other countries and illustrate the UK’s bilateral trade on top exports and imports for goods and services. In addition, the UK trade summary statistics depict foreign direct investment (FDI), regional trade statistics, and the UK’s position in global trade and investment rankings. </p>
6+
<p class="govuk-body-m datagovuk-body">You can download more detailed data in ODS format. The data is provided by the Department for Business and Trade.</p>
7+
</section>
8+
9+
<section class="datagovuk-headline govuk-section datagovuk-section govuk-!-margin-top-8">
10+
11+
<h2 class="govuk-heading-m datagovuk-heading-m">Total UK exports and imports in goods and services 2010 to 2025</h2>
12+
13+
<div class="govuk-grid-row line-chart">
14+
<div id="chart-1" style="height: 300px; width: 100%; text-align: center; color: #999; line-height: 300px; font-size: 14px; font-family: 'Lucida Grande', 'Lucida Sans Unicode', Verdana, Arial, Helvetica, sans-serif;">Loading...</div>
15+
<script nonce="4VBZSs68OtXOwcNU1lUED7Y0uhycACWjlb+rG3D91Qg=">
16+
(function() {
17+
if (document.documentElement.hasAttribute("data-turbolinks-preview")) return;
18+
if (document.documentElement.hasAttribute("data-turbo-preview")) return;
19+
20+
var createChart = function() { new Chartkick["LineChart"]("chart-1", [{"name":"Value of exports in £ billions","color":"#C27A9A","data":{"2010":464.495,"2011":522.107,"2012":525.113,"2013":540.436,"2014":534.994,"2015":537.513,"2016":582.613,"2017":649.59,"2018":691.74,"2019":718.759,"2020":636.325,"2021":680.291,"2022":879.121,"2023":878.278,"2024":897.916,"2025":925.541},"dataset":{"pointRadius":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],"pointStyle":["rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot","rectRot"]}},{"name":"Value of imports in £ billions","color":"#00890B","data":{"2010":489.677,"2011":535.37,"2012":541.81,"2013":563.771,"2014":567.939,"2015":563.867,"2016":617.023,"2017":675.643,"2018":717.814,"2019":745.746,"2020":620.657,"2021":679.352,"2022":906.868,"2023":910.419,"2024":919.505,"2025":971.472},"dataset":{"pointRadius":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4],"pointStyle":["rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect","rect"]}}], {"suffix":"bn","round":2,"points":true,"dataset":{"empty":"No data available","tension":0.5,"pointRadius":0,"pointHoverRadius":10},"library":{"plugins":{"datalabels":{"display":false},"legend":{"display":true,"labels":{"color":"#5D5D5D","font":{"size":20,"family":"Inter, sans-serif","weight":"bold"},"padding":30,"usePointStyle":true}},"tooltip":{"bodyFont":{"size":20,"family":"Inter, sans-serif","weight":"bold"},"titleFont":{"size":20,"family":"Inter, sans-serif","weight":"bold"}}},"responsive":true,"layout":{"padding":{"top":20,"bottom":20,"left":20,"right":20}},"scales":{"y":{"min":100,"grid":{"display":true},"border":{"dash":[5,5]},"ticks":{"stepSize":0,"maxTicksLimit":10,"autoSkip":false,"font":{"size":20}}},"x":{"border":{"display":true},"ticks":{"font":{"size":20}}}}},"legend":"bottom"}); };
21+
if ("Chartkick" in window) {
22+
createChart();
23+
} else {
24+
window.addEventListener("chartkick:load", createChart, true);
25+
}
26+
})();
27+
</script>
28+
29+
</div>
30+
31+
32+
<p class="govuk-body datagovuk-body govuk-!-margin-top-4">
33+
<a href="/collections/business-and-economy/uk-trade/charts/total-uk-imports-exports" class="govuk-link datagovuk-link">Download the chart data</a>
34+
</p>
35+
</section>
36+
37+
<div class="govuk-inset-text datagovuk-feedback-inset-text">
38+
<p class="govuk-body datagovuk-body">
39+
Is this data useful?
40+
<a href="https://forms.office.com/e/9V26PNFQaR" class="govuk-link datagovuk-link">Give us feedback</a>
41+
</p>
42+
</div>
43+
44+
45+
46+
<section class="datagovuk-link datagovuk-section" aria-label="Get the data links">
47+
<section class="datagovuk-section">
48+
<h3 class="govuk-heading-m datagovuk-heading-m">Get the data</h3>
49+
<a role="button" class="govuk-button datagovuk-button" rel="nofollow" href="https://www.gov.uk/government/statistics/uk-trade-in-numbers/uk-trade-in-numbers-web-version">UK trade statistics <span class="datagovuk-right-arrow">&#8594;</span></a>
50+
</section>
51+
<section class="datagovuk-section">
52+
<p class="govuk-body datagovuk-body datagovuk-!-colour-grey">The page was last updated 24/3/2026</p>
53+
</section>
54+
</section>
55+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Page One</h1>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<h1>Page Two</h1>

0 commit comments

Comments
 (0)