diff --git a/.ruby-version b/.ruby-version index 49cdd668e..ef538c281 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.7.6 +3.1.2 diff --git a/Dockerfile b/Dockerfile index 33788b286..b83d092a0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ -ARG base_image=ghcr.io/alphagov/govuk-ruby-base:2.7.6 -ARG builder_image=ghcr.io/alphagov/govuk-ruby-builder:2.7.6 +ARG base_image=ghcr.io/alphagov/govuk-ruby-base:3.1.2 +ARG builder_image=ghcr.io/alphagov/govuk-ruby-builder:3.1.2 FROM $builder_image AS builder diff --git a/Gemfile b/Gemfile index 1b95cce60..0fd167df6 100644 --- a/Gemfile +++ b/Gemfile @@ -13,6 +13,7 @@ gem "plek" gem "rack_strip_client_ip" gem "rails-controller-testing" gem "rails-i18n" +gem "rss" gem "sassc-rails" gem "slimmer" gem "sprockets-rails" diff --git a/Gemfile.lock b/Gemfile.lock index a0f8807c2..941440b3d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -285,6 +285,8 @@ GEM netrc (~> 0.8) rexml (3.2.5) rouge (4.0.0) + rss (0.2.9) + rexml rubocop (1.35.0) json (~> 2.3) parallel (~> 1.10) @@ -412,6 +414,7 @@ DEPENDENCIES rails-controller-testing rails-i18n rails_translation_manager + rss rubocop-govuk sassc-rails simplecov @@ -422,4 +425,4 @@ DEPENDENCIES webmock BUNDLED WITH - 2.1.4 + 2.3.22 diff --git a/app/presenters/contact_presenter.rb b/app/presenters/contact_presenter.rb index 17c0d26c1..31c4f109d 100644 --- a/app/presenters/contact_presenter.rb +++ b/app/presenters/contact_presenter.rb @@ -118,7 +118,7 @@ def phone_numbers_in_group(group) def v_card_part(v_card_class, value) { - v_card_class: v_card_class, + v_card_class:, value: value.try(:strip).try(:html_safe), } end diff --git a/app/presenters/content_item/corporate_information_groups.rb b/app/presenters/content_item/corporate_information_groups.rb index 951d9bbf4..9c7204de9 100644 --- a/app/presenters/content_item/corporate_information_groups.rb +++ b/app/presenters/content_item/corporate_information_groups.rb @@ -44,7 +44,7 @@ def further_information_link(type) def further_information_about(type) link = further_information_link(type) - I18n.t("corporate_information_page.#{type}_html", link: link) if link + I18n.t("corporate_information_page.#{type}_html", link:) if link end def corporate_information_heading diff --git a/app/presenters/content_item/manual.rb b/app/presenters/content_item/manual.rb index 1963c660c..b2a92cf89 100644 --- a/app/presenters/content_item/manual.rb +++ b/app/presenters/content_item/manual.rb @@ -8,9 +8,9 @@ def page_title title += " - " if title.present? if hmrc? - I18n.t("manuals.hmrc_title", title: title) + I18n.t("manuals.hmrc_title", title:) else - I18n.t("manuals.title", title: title) + I18n.t("manuals.title", title:) end end alias_method :manual_page_title, :page_title @@ -29,7 +29,7 @@ def body def manual_metadata { - from: from, + from:, first_published: published, other: other_metadata, inverse: true, diff --git a/app/presenters/content_item/metadata.rb b/app/presenters/content_item/metadata.rb index 635d1885f..dfb1c2a07 100644 --- a/app/presenters/content_item/metadata.rb +++ b/app/presenters/content_item/metadata.rb @@ -5,11 +5,11 @@ module Metadata def metadata { - from: from, + from:, first_published: published, last_updated: updated, see_updates_link: true, - part_of: part_of, + part_of:, direction: text_direction, other: {}, } @@ -21,7 +21,7 @@ def important_metadata def publisher_metadata { - from: from, + from:, first_published: published, last_updated: updated, see_updates_link: true, diff --git a/app/presenters/content_item/title_and_context.rb b/app/presenters/content_item/title_and_context.rb index 44f17a4bc..d217ed0c1 100644 --- a/app/presenters/content_item/title_and_context.rb +++ b/app/presenters/content_item/title_and_context.rb @@ -2,7 +2,7 @@ module ContentItem module TitleAndContext def title_and_context { - title: title, + title:, context: I18n.t("content_item.schema_name.#{document_type}", count: 1), context_locale: view_context.t_locale_fallback("content_item.schema_name.#{document_type}", count: 1), average_title_length: "long", diff --git a/app/presenters/content_item/withdrawable.rb b/app/presenters/content_item/withdrawable.rb index c0733e09d..f032db485 100644 --- a/app/presenters/content_item/withdrawable.rb +++ b/app/presenters/content_item/withdrawable.rb @@ -41,7 +41,7 @@ def withdrawal_notice_time end def english_display_date(timestamp, format = "%-d %B %Y") - I18n.l(Time.zone.parse(timestamp), format: format, locale: :en) if timestamp + I18n.l(Time.zone.parse(timestamp), format:, locale: :en) if timestamp end end end diff --git a/app/presenters/content_item_presenter.rb b/app/presenters/content_item_presenter.rb index 024a996fd..c4e7e3396 100644 --- a/app/presenters/content_item_presenter.rb +++ b/app/presenters/content_item_presenter.rb @@ -111,7 +111,7 @@ def voting_is_open? end def display_date(timestamp, format = "%-d %B %Y") - I18n.l(Time.zone.parse(timestamp), format: format, locale: "en") if timestamp + I18n.l(Time.zone.parse(timestamp), format:, locale: "en") if timestamp end def sorted_locales(translations) @@ -135,6 +135,6 @@ def text_direction end def native_language_name_for(locale) - I18n.t("language_names.#{locale}", locale: locale) + I18n.t("language_names.#{locale}", locale:) end end diff --git a/app/presenters/travel_advice_presenter.rb b/app/presenters/travel_advice_presenter.rb index 719003603..da47c9eac 100644 --- a/app/presenters/travel_advice_presenter.rb +++ b/app/presenters/travel_advice_presenter.rb @@ -23,7 +23,7 @@ def metadata other["Latest update"] = view_context.simple_format(latest_update, { class: "metadata__update" }, wrapper_tag: "span") if latest_update.present? { - other: other, + other:, } end diff --git a/test/component_test_helper.rb b/test/component_test_helper.rb index 9ade067de..457c3d30f 100644 --- a/test/component_test_helper.rb +++ b/test/component_test_helper.rb @@ -8,6 +8,6 @@ def component_name end def render_component(locals) - render partial: "components/#{component_name}", locals: locals + render partial: "components/#{component_name}", locals: end end diff --git a/test/controllers/content_items_controller_test.rb b/test/controllers/content_items_controller_test.rb index dfb26a396..69993e8cc 100644 --- a/test/controllers/content_items_controller_test.rb +++ b/test/controllers/content_items_controller_test.rb @@ -255,9 +255,9 @@ class ContentItemsControllerTest < ActionController::TestCase test "renders translated content items in their locale" do content_item = content_store_has_schema_example("case_study", "translated") locale = content_item["locale"] - translated_schema_name = I18n.t("content_item.schema_name.case_study", count: 1, locale: locale) + translated_schema_name = I18n.t("content_item.schema_name.case_study", count: 1, locale:) - get :show, params: { path: path_for(content_item, locale), locale: locale } + get :show, params: { path: path_for(content_item, locale), locale: } assert_response :success assert_select "title", %r{#{translated_schema_name}} @@ -296,7 +296,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_content_store_does_not_have_item("/#{path}") - get :show, params: { path: path } + get :show, params: { path: } assert_response :not_found end @@ -305,7 +305,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_content_store_does_not_have_item("/#{path}") - get :show, params: { path: path } + get :show, params: { path: } assert_response :not_found end @@ -317,7 +317,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_content_store_has_item("/#{path}", content_item) - get :show, params: { path: path } + get :show, params: { path: } assert_response :not_found end @@ -326,7 +326,7 @@ class ContentItemsControllerTest < ActionController::TestCase url = "#{content_store_endpoint}/content/#{path}" stub_request(:get, url).to_return(status: 403, headers: {}) - get :show, params: { path: path } + get :show, params: { path: } assert_response :forbidden end diff --git a/test/controllers/get_involved_controller_test.rb b/test/controllers/get_involved_controller_test.rb index 9144ec461..8d707b3b7 100644 --- a/test/controllers/get_involved_controller_test.rb +++ b/test/controllers/get_involved_controller_test.rb @@ -62,7 +62,7 @@ def setup title = "Next closing consultation on time zones" stub_search_query(query: hash_including(filter_content_store_document_type: "open_consultation", filter_end_date: "from: #{Time.zone.now.to_date}"), - response: { "results" => [consultation_result(title: title)] }) + response: { "results" => [consultation_result(title:)] }) get :show assert_select ".gem-c-inset-text", /#{title}/ @@ -72,7 +72,7 @@ def setup test "showing recently opened consultations" do title = "Open consultation on time zones" stub_search_query(query: hash_including(filter_content_store_document_type: "open_consultation"), - response: { "results" => [consultation_result(title: title)] }) + response: { "results" => [consultation_result(title:)] }) get :show assert response.body.include?(title) @@ -81,7 +81,7 @@ def setup test "showing recent consultation outcomes" do title = "Consultation outcome on time zones" stub_search_query(query: hash_including(filter_content_store_document_type: "consultation_outcome"), - response: { "results" => [consultation_result(title: title)] }) + response: { "results" => [consultation_result(title:)] }) get :show assert response.body.include?(title) @@ -97,7 +97,7 @@ def setup def stub_search_query(query:, response:) stub_request(:get, /\A#{Plek.new.find('search')}\/search.json/) - .with(query: query) + .with(query:) .to_return(body: response.to_json) end diff --git a/test/controllers/service_sign_in_content_item_controller_test.rb b/test/controllers/service_sign_in_content_item_controller_test.rb index 7f8a2ea0e..5f649697f 100644 --- a/test/controllers/service_sign_in_content_item_controller_test.rb +++ b/test/controllers/service_sign_in_content_item_controller_test.rb @@ -35,7 +35,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - get :show, params: { path: path } + get :show, params: { path: } assert_template :service_sign_in end @@ -46,14 +46,14 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - get :show, params: { path: path } + get :show, params: { path: } assert_template :service_sign_in end test "raises a 404 for a content item which isn't a service_sign_in page" do path = "this/is/not/a/sign/in/page" - post :service_sign_in_options, params: { path: path } + post :service_sign_in_options, params: { path: } assert_response :not_found end @@ -67,7 +67,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - post :service_sign_in_options, params: { path: path, option: value } + post :service_sign_in_options, params: { path:, option: value } assert_response :redirect assert_redirected_to link @@ -79,7 +79,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - post :service_sign_in_options, params: { path: path } + post :service_sign_in_options, params: { path: } assert_not_nil @controller.instance_variable_get(:@error) assert_template :service_sign_in @@ -93,7 +93,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - post :service_sign_in_options, params: { path: path, option: option } + post :service_sign_in_options, params: { path:, option: } assert_not_nil @controller.instance_variable_get(:@error) assert_template :service_sign_in @@ -112,7 +112,7 @@ class ContentItemsControllerTest < ActionController::TestCase stub_request(:get, %r{#{path}}).to_return(status: 200, body: content_item.to_json, headers: {}) - post :service_sign_in_options, params: { path: path, _ga: "1.1111111.1111111.111111111", option: value } + post :service_sign_in_options, params: { path:, _ga: "1.1111111.1111111.111111111", option: value } assert_response :redirect assert_redirected_to "https://www.horse.service.gov.uk/account?horse=brown&_ga=1.1111111.1111111.111111111" diff --git a/test/controllers/step_navigation_controller_test.rb b/test/controllers/step_navigation_controller_test.rb index 2a821ee48..9ab5cbbe1 100644 --- a/test/controllers/step_navigation_controller_test.rb +++ b/test/controllers/step_navigation_controller_test.rb @@ -13,7 +13,7 @@ class ContentItemsControllerTest < ActionController::TestCase @controller.stubs(:page_in_scope?).returns(false) - get :show, params: { path: path } + get :show, params: { path: } assert_response 200 assert response.body.include?("Learn to drive a car: step by step") @@ -28,7 +28,7 @@ class ContentItemsControllerTest < ActionController::TestCase @controller.stubs(:page_in_scope?).returns(false) - get :show, params: { path: path } + get :show, params: { path: } assert_response 200 assert_not response.body.include?("Learn to drive a car: step by step") diff --git a/test/integration/specialist_document_test.rb b/test/integration/specialist_document_test.rb index cab3b6938..3b2bd5edd 100644 --- a/test/integration/specialist_document_test.rb +++ b/test/integration/specialist_document_test.rb @@ -139,7 +139,7 @@ def assert_nested_content_item(heading) if heading_level < 4 assert page.has_css?(selector), "Failed to find an element matching: #{selector}" - assert page.has_css?(selector, text: text), "Failed to find an element matching #{selector} with text: #{text}" + assert page.has_css?(selector, text:), "Failed to find an element matching #{selector} with text: #{text}" else assert_not page.has_css?(selector), "Found a nested heading too deep, there should be no element matching: #{selector}" end diff --git a/test/support/govuk_content_schema_examples.rb b/test/support/govuk_content_schema_examples.rb index 8e823ed26..ba8808216 100644 --- a/test/support/govuk_content_schema_examples.rb +++ b/test/support/govuk_content_schema_examples.rb @@ -26,7 +26,7 @@ def content_store_has_schema_example(schema_name, example_name) end def govuk_content_schema_example(schema_name, example_name) - GovukSchemas::Example.find(schema_name, example_name: example_name) + GovukSchemas::Example.find(schema_name, example_name:) end module ClassMethods diff --git a/test/test_helper.rb b/test/test_helper.rb index 88c81cb77..ffa1c2f85 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -76,7 +76,7 @@ def assert_has_contents_list(contents) selector = "a[href=\"##{heading[:id]}\"]" text = heading.fetch(:text) assert page.has_css?(selector), "Failed to find an element matching: #{selector}" - assert page.has_css?(selector, text: text), "Failed to find an element matching #{selector} with text: #{text}" + assert page.has_css?(selector, text:), "Failed to find an element matching #{selector} with text: #{text}" end end end @@ -105,7 +105,7 @@ def assert_has_metadata(any_args, extra_metadata_classes: nil) value = { value => nil } if value.is_a?(String) value.each do |text, href| if href - assert page.has_link?(text, href: href), "Metadata text '#{text} with link of #{href}' not found" + assert page.has_link?(text, href:), "Metadata text '#{text} with link of #{href}' not found" else assert page.has_text?(text), "Metadata value '#{text}' not found" end @@ -120,9 +120,9 @@ def assert_has_metadata_local(metadata, term_selector, definition_selector) "Metadata term '#{key}' not found" value = { value => nil } if value.is_a?(String) value.each do |text, href| - within(definition_selector, text: text) do + within(definition_selector, text:) do if href - assert page.has_link?(text, href: href), "Metadata link '#{text}' not found" + assert page.has_link?(text, href:), "Metadata link '#{text}' not found" else assert page.has_text?(text), "Metadata value '#{text}' not found" end @@ -156,7 +156,7 @@ def assert_has_devolved_nations_component(text, nations = nil) end def assert_footer_has_published_dates(first_published = nil, last_updated = nil, history_link: false) - assert_has_published_dates(first_published, last_updated, history_link: history_link) + assert_has_published_dates(first_published, last_updated, history_link:) end def setup_and_visit_content_item(name, parameter_string = "")