diff --git a/.github/actions/install_solidus/action.yml b/.github/actions/install_solidus/action.yml index c29bf6fae1a..c3a24a5fee7 100644 --- a/.github/actions/install_solidus/action.yml +++ b/.github/actions/install_solidus/action.yml @@ -57,6 +57,15 @@ runs: run: | cd $RUNNER_TEMP/my_app bundle add solidus --path "$(ruby -e"puts File.expand_path ENV['GITHUB_WORKSPACE']")" + bundle add solidus_admin --path "$(ruby -e"puts File.expand_path File.join(ENV['GITHUB_WORKSPACE'], 'admin')")" + + # The released `solidus_admin` gem ships a prebuilt `app/assets/builds/solidus_admin/tailwind.css`, + # but it's gitignored, so bundling the gem from the checkout above leaves + # `solidus_admin/application.css` unable to resolve its `require solidus_admin/tailwind.css`. + # The installer only needs the file to exist, not to be styled. + mkdir -p "$GITHUB_WORKSPACE/admin/app/assets/builds/solidus_admin" + touch "$GITHUB_WORKSPACE/admin/app/assets/builds/solidus_admin/tailwind.css" + unset RAILS_ENV # avoid doing everything on the test environment # Due to [a bug in `sprockets-rails`](https://github.com/rails/sprockets-rails/pull/546) we need to manually add diff --git a/admin/app/components/concerns/solidus_admin/slotable_default.rb b/admin/app/components/concerns/solidus_admin/slotable_default.rb deleted file mode 100644 index b7971ee6e87..00000000000 --- a/admin/app/components/concerns/solidus_admin/slotable_default.rb +++ /dev/null @@ -1,42 +0,0 @@ -# frozen_string_literal: true - -# ViewComponent v3 provided experimental functionality to define default content for slots -# https://viewcomponent.org/guide/slots.html#default_slot_name, but unfortunately -# it did not quite work: https://github.com/ViewComponent/view_component/issues/2169. -# Good news the issue has been resolved, not so good news - it's targeted to be released in v4, -# so we have to patch the functionality until we upgrade. -# The solution has been copied from here https://github.com/ViewComponent/view_component/pull/2291/files. - -require "view_component/version" -if Gem::Version.new(ViewComponent::VERSION::STRING) >= Gem::Version.new("4") - raise "The fix is included in ViewComponent v4, please remove this patch #{__FILE__}" -end - -module SolidusAdmin - module SlotableDefault - def get_slot(slot_name) - @__vc_set_slots ||= {} - content unless content_evaluated? # ensure content is loaded so slots will be defined - - # If the slot is set, return it - return @__vc_set_slots[slot_name] if @__vc_set_slots[slot_name] - - # If there is a default method for the slot, call it - if (default_method = registered_slots[slot_name][:default_method]) - renderable_value = send(default_method) - slot = ViewComponent::Slot.new(self) - - if renderable_value.respond_to?(:render_in) - slot.__vc_component_instance = renderable_value - else - slot.__vc_content = renderable_value - end - - slot - elsif self.class.registered_slots[slot_name][:collection] - # If empty slot is a collection, return an empty array - [] - end - end - end -end diff --git a/admin/app/components/solidus_admin/base_component.rb b/admin/app/components/solidus_admin/base_component.rb index 49d3f27272b..4f40cbaafce 100644 --- a/admin/app/components/solidus_admin/base_component.rb +++ b/admin/app/components/solidus_admin/base_component.rb @@ -16,6 +16,15 @@ def icon_tag(name, **attrs) render component("ui/icon").new(name:, **attrs) end + # Log missing translations instead of rendering ActionView's + # `translation_missing` span, falling back to the English translation. + def translate(key = nil, **options) + super(key, **options, raise: true) + rescue ::I18n::MissingTranslationData + missing_translation(self.class.__vc_i18n_key(key, options[:scope]), options.except(:scope)) + end + alias_method :t, :translate + def missing_translation(key, options) keys = I18n.normalize_keys(options[:locale] || I18n.locale, key, options[:scope]) @@ -28,8 +37,11 @@ def missing_translation(key, options) end end - def self.i18n_scope - @i18n_scope ||= name.underscore.tr("/", ".") + # ViewComponent assigns `virtual_path` in its `inherited` hook, which runs + # before an anonymous subclass has been given a name. Resolve it lazily so + # that translation scopes also work for dynamically built components. + def self.virtual_path + @virtual_path ||= name&.underscore end def self.stimulus_id diff --git a/admin/app/components/solidus_admin/ui/forms/address/component.rb b/admin/app/components/solidus_admin/ui/forms/address/component.rb index 92c0decc6e6..a1d1801e2c2 100644 --- a/admin/app/components/solidus_admin/ui/forms/address/component.rb +++ b/admin/app/components/solidus_admin/ui/forms/address/component.rb @@ -3,8 +3,6 @@ class SolidusAdmin::UI::Forms::Address::Component < SolidusAdmin::BaseComponent DefaultNamedFieldsetNotFound = Class.new(NameError) - include SolidusAdmin::SlotableDefault - renders_one :fieldset # @param fieldset [Symbol] use a default named fieldset, component of the same name must be defined diff --git a/admin/config/initializers/view_component.rb b/admin/config/initializers/view_component.rb index 8aa5596a4b8..4eb02b35ca5 100644 --- a/admin/config/initializers/view_component.rb +++ b/admin/config/initializers/view_component.rb @@ -1,10 +1,7 @@ # frozen_string_literal: true -Rails.application.config.view_component.capture_compatibility_patch_enabled = true - if Rails.env.development? || Rails.env.test? Rails.application.config.view_component.instrumentation_enabled = true - Rails.application.config.view_component.use_deprecated_instrumentation_name = false bold = "\e[1m" clear = "\e[0m" @@ -13,7 +10,7 @@ next unless args.last[:name]&.starts_with?("SolidusAdmin::") event = ActiveSupport::Notifications::Event.new(*args) - SolidusAdmin::BaseComponent.logger.debug \ + Rails.logger.debug \ " Rendered #{bold}#{event.payload[:name]}#{clear}" \ " (Duration: #{event.duration.round(1)}ms)" end diff --git a/admin/lib/solidus_admin/engine.rb b/admin/lib/solidus_admin/engine.rb index 013b1b02803..5181fccaee4 100644 --- a/admin/lib/solidus_admin/engine.rb +++ b/admin/lib/solidus_admin/engine.rb @@ -16,10 +16,10 @@ class Engine < ::Rails::Engine config.autoload_paths << SolidusAdmin::Engine.root.join("spec/components/previews") initializer "solidus_admin.view_component" do |app| - app.config.view_component.preview_paths << SolidusAdmin::Engine.root.join("spec/components/previews").to_s + app.config.view_component.previews.paths << SolidusAdmin::Engine.root.join("spec/components/previews").to_s app.config.to_prepare do - preview_controller_class = app.config.view_component.preview_controller.constantize + preview_controller_class = app.config.view_component.previews.controller.constantize # This is needed to make the preview controller have access to the same # set of helpers that are available to the Preview class. diff --git a/admin/lib/solidus_admin/testing_support/component_helpers.rb b/admin/lib/solidus_admin/testing_support/component_helpers.rb index f56960561dd..23d10c35942 100644 --- a/admin/lib/solidus_admin/testing_support/component_helpers.rb +++ b/admin/lib/solidus_admin/testing_support/component_helpers.rb @@ -3,6 +3,12 @@ module SolidusAdmin module TestingSupport module ComponentHelpers + # Renders components through the admin's base controller, so that the + # admin helpers and layout context are available. + def vc_test_controller_class + SolidusAdmin::BaseController + end + # Mocks a component class with the given definition. # # @param definition [Proc] the component definition diff --git a/admin/solidus_admin.gemspec b/admin/solidus_admin.gemspec index d9290e887de..db4132e7453 100644 --- a/admin/solidus_admin.gemspec +++ b/admin/solidus_admin.gemspec @@ -35,5 +35,5 @@ Gem::Specification.new do |s| s.add_dependency "solidus_core", "> 4.2" s.add_dependency "stimulus-rails", "~> 1.2" s.add_dependency "turbo-rails", "~> 2.0" - s.add_dependency "view_component", "~> 3.9" + s.add_dependency "view_component", "~> 4.0" end diff --git a/admin/spec/components/solidus_admin/base_component_spec.rb b/admin/spec/components/solidus_admin/base_component_spec.rb index 9c76df23b90..b6b5141a181 100644 --- a/admin/spec/components/solidus_admin/base_component_spec.rb +++ b/admin/spec/components/solidus_admin/base_component_spec.rb @@ -46,17 +46,33 @@ def call end describe "missing translations" do - it "logs and shows the full chain of keys" do - debug_logs = [] + let(:debug_logs) { [] } + let(:component) { mock_component { erb_template "" } } + before do allow(Rails.logger).to receive(:debug) { debug_logs << _1 } - component = mock_component { erb_template "" } render_inline(component) + end + it "logs and shows the full chain of keys" do translation = component.translate("foo.bar.baz") expect(translation).to eq("translation missing: en.foo.bar.baz") expect(debug_logs).to include(%( [Foo::Component] Missing translation: en.foo.bar.baz)) end + + it "retries in English when an explicit non-English locale is given" do + translation = component.translate("foo.bar.baz", locale: :de) + + expect(translation).to eq("translation missing: en.foo.bar.baz") + expect(debug_logs).to include( + %( [Foo::Component] Missing translation: de.foo.bar.baz), + %( [Foo::Component] Missing translation: en.foo.bar.baz) + ) + end + + it "resolves relative keys through `t` as well as `translate`" do + expect(component.t("foo.bar.baz")).to eq("translation missing: en.foo.bar.baz") + end end end diff --git a/admin/spec/spec_helper.rb b/admin/spec/spec_helper.rb index 0bd65d5102e..ecf6263ca6b 100644 --- a/admin/spec/spec_helper.rb +++ b/admin/spec/spec_helper.rb @@ -63,7 +63,6 @@ Spree::TestingSupport::FactoryBot.add_paths_and_load! # VIEW COMPONENTS -Rails.application.config.view_component.test_controller = "SolidusAdmin::BaseController" require "view_component/test_helpers" require "view_component/system_test_helpers" diff --git a/legacy_promotions/spec/rails_helper.rb b/legacy_promotions/spec/rails_helper.rb index 47c74b8b888..c598dedd02f 100644 --- a/legacy_promotions/spec/rails_helper.rb +++ b/legacy_promotions/spec/rails_helper.rb @@ -56,8 +56,8 @@ Capybara.enable_aria_label = true # VIEW COMPONENTS -Rails.application.config.view_component.test_controller = "SolidusAdmin::BaseController" require "view_component/test_helpers" +require "solidus_admin/testing_support/component_helpers" RSpec.configure do |config| config.fixture_path = File.join(__dir__, "fixtures") @@ -85,6 +85,7 @@ end config.include ViewComponent::TestHelpers, type: :component + config.include SolidusAdmin::TestingSupport::ComponentHelpers, type: :component config.include ActiveJob::TestHelper config.include SolidusAdmin::TestingSupport::FeatureHelpers, type: :feature diff --git a/promotions/lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb b/promotions/lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb index e76c10cbca4..a16b9149185 100644 --- a/promotions/lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb +++ b/promotions/lib/components/admin/solidus_promotions/promotion_categories/edit/component.rb @@ -2,7 +2,6 @@ class SolidusPromotions::PromotionCategories::Edit::Component < SolidusAdmin::BaseComponent def initialize(record) - super @promotion_category = record end diff --git a/promotions/lib/components/admin/solidus_promotions/promotion_categories/new/component.rb b/promotions/lib/components/admin/solidus_promotions/promotion_categories/new/component.rb index 7797374d04b..e61032c3dbe 100644 --- a/promotions/lib/components/admin/solidus_promotions/promotion_categories/new/component.rb +++ b/promotions/lib/components/admin/solidus_promotions/promotion_categories/new/component.rb @@ -2,7 +2,6 @@ class SolidusPromotions::PromotionCategories::New::Component < SolidusAdmin::BaseComponent def initialize(record) - super @promotion_category = record end diff --git a/storefront/template.rb b/storefront/template.rb index 7b6e07a03ce..b135037d2a9 100644 --- a/storefront/template.rb +++ b/storefront/template.rb @@ -75,7 +75,7 @@ gem "responders" gem "solidus_support", ">= 0.12.0" - gem "view_component", "~> 3.0" + gem "view_component", "~> 4.0" gem "tailwindcss-rails", "~> 3.0" gem_group :test do diff --git a/storefront/templates/spec/components/link_to_cart_component_spec.rb b/storefront/templates/spec/components/link_to_cart_component_spec.rb index 9a6d764979c..4cef893868c 100644 --- a/storefront/templates/spec/components/link_to_cart_component_spec.rb +++ b/storefront/templates/spec/components/link_to_cart_component_spec.rb @@ -1,10 +1,8 @@ require "solidus_storefront_spec_helper" RSpec.describe LinkToCartComponent, type: :component do - let(:text) { "" } - let(:link_to_cart_component) do - described_class.new(text) + described_class.new end let(:current_order) { nil }