view_component 2.74.1 → 2.82.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of view_component might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 64dcea99274ed75352d28004634307fa7db193aa5bf8bf57dd0c9d5c5c241308
4
- data.tar.gz: c097b1034bc3df6216117fc0b32df26a8b02c0922c7e7399b254a6606aa46c31
3
+ metadata.gz: 9bb20706245c43b9c5fa4d11087a2e98332bda53d659f7065874a3c0b8545547
4
+ data.tar.gz: 13821a1e91da8a8dce8270962b99aa3b84fddb9731f99c2e2acfd143ad017836
5
5
  SHA512:
6
- metadata.gz: efe5f3a05e157482eec4426ae05eef96345da9aa3ae0865c2ce7bc1755e08ae07405ee648923fe84165eca989a87b53f015012f13002202e809c12819c552a5b
7
- data.tar.gz: 7b8bb21b81a1da222b47dd8c8c12cf2c0f7f5e2bd1e74d80ebfc8bf7e1cbe5c54eeab46c80395d3c8bb28809caac8be07ce833e1530af3b982d153d44398fba2
6
+ metadata.gz: 5b0ebf7ac54fc2c82374b29f9cceadfe55af73516ad2e4c65dad69cd65a7c63de3e00ef9cdba8b359c1061309f9a0d2f90344374feec2b37211fbfb36282c96b
7
+ data.tar.gz: 48e156dcc5fa1ac9a6cff64e4cb585d528103452938a515d1e3598b505b03188e89362c393c86c0a05437f9a8c28f22e937e3d706f3da17ae03a7c1371728505
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ViewComponentsSystemTestController < ActionController::Base # :nodoc:
4
+ def system_test_entrypoint
5
+ render file: "./tmp/view_components/#{params.permit(:file)[:file]}"
6
+ end
7
+ end
data/docs/CHANGELOG.md CHANGED
@@ -10,6 +10,124 @@ nav_order: 5
10
10
 
11
11
  ## main
12
12
 
13
+ ## 2.82.0
14
+
15
+ * Revert "Avoid loading ActionView::Base during initialization (#1528)"
16
+
17
+ *Jon Rohan*
18
+
19
+ * Fix tests using `with_rendered_component_path` with custom layouts.
20
+
21
+ *Ian Hollander*
22
+
23
+ ## 2.81.0
24
+
25
+ * Adjust the way response objects are set on the preview controller to work around a recent change in Rails main.
26
+
27
+ *Cameron Dutro*
28
+
29
+ * Fix typo in "Generate a Stimulus controller" documentation.
30
+
31
+ *Ben Trewern*
32
+
33
+ * Modify the `render_in_view_context` test helper to forward its args to the block.
34
+
35
+ *Cameron Dutro*
36
+
37
+ ## 2.80.0
38
+
39
+ * Move system test endpoint out of the unrelated previews controller.
40
+
41
+ *Edwin Mak*
42
+
43
+ * Display Ruby 2.7 deprecation notice only once, when starting the application.
44
+
45
+ *Henrik Hauge Bjørnskov*
46
+
47
+ * Require Rails 5.2+ in gemspec and update documentation.
48
+
49
+ *Drew Bragg*
50
+
51
+ * Add documentation for using `with_rendered_component_path` with RSpec.
52
+
53
+ *Edwin Mak*
54
+
55
+ ## 2.79.0
56
+
57
+ * Add ability to pass explicit `preview_path` to preview generator.
58
+
59
+ *Erinna Chen*
60
+
61
+ * Add `with_rendered_component_path` helper for writing component system tests.
62
+
63
+ *Edwin Mak*
64
+
65
+ * Include gem name and deprecation horizon in every deprecation message.
66
+
67
+ *Jan Klimo*
68
+
69
+ ## 2.78.0
70
+
71
+ * Support variants with dots in their names.
72
+
73
+ *Javi Martín*
74
+
75
+ ## 2.77.0
76
+
77
+ * Support variants with dashes in their names.
78
+
79
+ *Javi Martín*
80
+
81
+ ## 2.76.0
82
+
83
+ * `Component.with_collection` supports components that accept splatted keyword arguments.
84
+
85
+ *Zee Spencer*
86
+
87
+ * Remove `config.view_component.use_consistent_rendering_lifecycle` since it is no longer planned for 3.0.
88
+
89
+ *Blake Williams*
90
+
91
+ * Prevent polymorphic slots from calculating `content` when setting a slot.
92
+
93
+ *Blake Williams*
94
+
95
+ * Add ability to pass in the preview class to `render_preview`.
96
+
97
+ *Jon Rohan*
98
+
99
+ * Fix issue causing PVC tests to fail in CI.
100
+
101
+ *Cameron Dutro*
102
+
103
+ * Fix YARD docs build task.
104
+
105
+ *Hans Lemuet*
106
+
107
+ * Add Startup Jobs to list of companies using ViewComponent.
108
+
109
+ *Marc Köhlbrugge*
110
+
111
+ * Run PVC's accessibility tests in a single process to avoid resource contention in CI.
112
+
113
+ *Cameron Dutro*
114
+
115
+ ## 2.75.0
116
+
117
+ * Avoid loading ActionView::Base during Rails initialization.
118
+
119
+ *Jonathan del Strother*
120
+
121
+ <!-- vale off -->
122
+ * Mention lambda slots rendering returned values lazily in the guide.
123
+
124
+ *Graham Rogers*
125
+ <!-- vale on -->
126
+
127
+ * Add "ViewComponent In The Wild" articles to resources.
128
+
129
+ *Alexander Baygeldin*
130
+
13
131
  ## 2.74.1
14
132
 
15
133
  * Add more users of ViewComponent to docs.
@@ -273,7 +391,7 @@ nav_order: 5
273
391
 
274
392
  * Revert `Expose Capybara DSL methods directly inside tests.` This change unintentionally broke other Capybara methods and thus introduced a regression. We aren't confident that we can fail forward so we have decided to revert this change.
275
393
 
276
- *Joel Hawksley*, *Blake Williams*
394
+ *Joel Hawksley, Blake Williams*
277
395
 
278
396
  * Revert change making content evaluation consistent.
279
397
 
@@ -356,7 +474,7 @@ nav_order: 5
356
474
 
357
475
  * Add @boardfish and @spone as maintainers.
358
476
 
359
- *Joel Hawksley*, *Cameron Dutro*, *Blake Williams*
477
+ *Joel Hawksley, Cameron Dutro, Blake Williams*
360
478
 
361
479
  * Re-compile updated, inherited templates when class caching is disabled.
362
480
 
@@ -416,13 +534,13 @@ nav_order: 5
416
534
 
417
535
  * Restore removed `rendered_component`, marking it for deprecation in v3.0.0.
418
536
 
419
- *Tyson Gach*, *Richard Macklin*, *Joel Hawksley*
537
+ *Tyson Gach, Richard Macklin, Joel Hawksley*
420
538
 
421
539
  ## 2.56.1
422
540
 
423
541
  * Rename private accessor `rendered_component` to `rendered_content`.
424
542
 
425
- *Yoshiyuki Hirano*, *Simon Dawson*
543
+ *Yoshiyuki Hirano, Simon Dawson*
426
544
 
427
545
  ## 2.56.0
428
546
 
@@ -513,7 +631,7 @@ nav_order: 5
513
631
 
514
632
  * Skip Rails 5.2 in local test environment if using incompatible Ruby version.
515
633
 
516
- *Cameron Dutro*, *Blake Williams*, *Joel Hawksley*
634
+ *Cameron Dutro, Blake Williams, Joel Hawksley*
517
635
 
518
636
  * Improve landing page documentation.
519
637
 
@@ -539,7 +657,7 @@ nav_order: 5
539
657
 
540
658
  * Add the option to use a "global" output buffer so `form_for` and friends can be used with view components.
541
659
 
542
- *Cameron Dutro*, *Blake Williams*
660
+ *Cameron Dutro, Blake Williams*
543
661
 
544
662
  * Fix fragment caching in partials when global output buffer is enabled.
545
663
  * Fix template inheritance when eager loading is disabled.
@@ -676,7 +794,7 @@ nav_order: 5
676
794
 
677
795
  * Add generators to support `tailwindcss-rails`.
678
796
 
679
- *Dino Maric*, *Hans Lemuet*
797
+ *Dino Maric, Hans Lemuet*
680
798
 
681
799
  * Add a namespaced component example to docs.
682
800
 
@@ -857,7 +975,7 @@ nav_order: 5
857
975
 
858
976
  * Rename internal accessor to use private naming.
859
977
 
860
- *Joel Hawksley*, *Blake Williams*, *Cameron Dutro*
978
+ *Joel Hawksley, Blake Williams, Cameron Dutro*
861
979
 
862
980
  * Add Github repo link to docs website header.
863
981
 
@@ -925,7 +1043,7 @@ nav_order: 5
925
1043
 
926
1044
  * Add support for `image_path` helper in previews.
927
1045
 
928
- *Tobias Ahlin*, *Joel Hawksley*
1046
+ *Tobias Ahlin, Joel Hawksley*
929
1047
 
930
1048
  * Add section to docs listing users of ViewComponent. Please submit a PR to add your team to the list!
931
1049
 
@@ -963,7 +1081,7 @@ nav_order: 5
963
1081
 
964
1082
  * Fix bug where `helpers` would instantiate and use a new `view_context` in each component.
965
1083
 
966
- *Blake Williams*, *Ian C. Anderson*
1084
+ *Blake Williams, Ian C. Anderson*
967
1085
 
968
1086
  * Implement polymorphic slots as experimental feature. See the Slots documentation to learn more.
969
1087
 
@@ -990,7 +1108,7 @@ nav_order: 5
990
1108
 
991
1109
  * Fix bug where `with_collection_parameter` didn't inherit from parent component.
992
1110
 
993
- *Will Drexler*, *Christian Campoli*
1111
+ *Will Drexler, Christian Campoli*
994
1112
 
995
1113
  * Allow query parameters in `with_request_url` test helper.
996
1114
 
@@ -1030,7 +1148,7 @@ nav_order: 5
1030
1148
 
1031
1149
  * Clarify documentation of `with_variant` as an override of Action Pack.
1032
1150
 
1033
- *Blake Williams*, *Cameron Dutro*, *Joel Hawksley*
1151
+ *Blake Williams, Cameron Dutro, Joel Hawksley*
1034
1152
 
1035
1153
  * Update docs page to be called Javascript and CSS, rename Building ViewComponents to Guide.
1036
1154
 
@@ -1055,7 +1173,7 @@ nav_order: 5
1055
1173
 
1056
1174
  * Clarify slots example in docs to reduce naming confusion.
1057
1175
 
1058
- *Joel Hawksley*, *Blake Williams*
1176
+ *Joel Hawksley, Blake Williams*
1059
1177
 
1060
1178
  * Fix error in documentation for `render_many` passthrough slots.
1061
1179
 
@@ -1517,7 +1635,7 @@ _Note: This release includes an underlying change to Slots that may affect incor
1517
1635
 
1518
1636
  * Add support for templates as ViewComponent::Preview examples.
1519
1637
 
1520
- *Juan Manuel Ramallo
1638
+ *Juan Manuel Ramallo*
1521
1639
 
1522
1640
  ## 2.14.1
1523
1641
 
@@ -1894,11 +2012,11 @@ _Note: This release includes an underlying change to Slots that may affect incor
1894
2012
 
1895
2013
  *Rainer Borene*
1896
2014
 
2015
+ <!-- vale off -->
1897
2016
  * Fix edge case issue with extracting variants from less conventional source_locations.
1898
2017
 
1899
- <!-- vale proselint.GenderBias = NO -->
1900
2018
  *Ryan Workman*
1901
- <!-- vale proselint.GenderBias = YES -->
2019
+ <!-- vale on -->
1902
2020
 
1903
2021
  ## v1.6.0
1904
2022
 
@@ -1916,7 +2034,7 @@ _Note: This release includes an underlying change to Slots that may affect incor
1916
2034
 
1917
2035
  * Template-less variants fall back to default template.
1918
2036
 
1919
- *Asger Behncke Jacobsen*, *Cesario Uy*
2037
+ *Asger Behncke Jacobsen, Cesario Uy*
1920
2038
 
1921
2039
  * Generated tests use new naming convention.
1922
2040
 
@@ -1932,11 +2050,11 @@ _Note: This release includes an underlying change to Slots that may affect incor
1932
2050
 
1933
2051
  ## v1.5.3
1934
2052
 
2053
+ <!-- vale off -->
1935
2054
  * Add support for RSpec to generators.
1936
2055
 
1937
- <!-- vale proselint.GenderBias = NO -->
1938
2056
  *Dylan Clark, Ryan Workman*
1939
- <!-- vale proselint.GenderBias = YES -->
2057
+ <!-- vale on -->
1940
2058
 
1941
2059
  * Require controllers as part of setting autoload paths.
1942
2060
 
@@ -1958,11 +2076,11 @@ _Note: This release includes an underlying change to Slots that may affect incor
1958
2076
 
1959
2077
  Note: `actionview-component` is now loaded by requiring `actionview/component`, not `actionview/component/base`.
1960
2078
 
2079
+ <!-- vale off -->
1961
2080
  * Fix issue with generating component method signatures.
1962
2081
 
1963
- <!-- vale proselint.GenderBias = NO -->
1964
2082
  *Ryan Workman, Dylan Clark*
1965
- <!-- vale proselint.GenderBias = YES -->
2083
+ <!-- vale off -->
1966
2084
 
1967
2085
  * Create component generator.
1968
2086
 
@@ -4,15 +4,22 @@ module Preview
4
4
  module Generators
5
5
  class ComponentGenerator < ::Rails::Generators::NamedBase
6
6
  source_root File.expand_path("templates", __dir__)
7
+ class_option :preview_path, type: :string, desc: "Path for previews, required when multiple preview paths are configured", default: ViewComponent::Base.config.generate.preview_path
7
8
 
8
9
  argument :attributes, type: :array, default: [], banner: "attribute"
9
10
  check_class_collision suffix: "ComponentPreview"
10
11
 
11
12
  def create_preview_file
12
13
  preview_paths = ViewComponent::Base.config.preview_paths
13
- return if preview_paths.count > 1
14
+ optional_path = options[:preview_path]
15
+ return if preview_paths.count > 1 && optional_path.blank?
16
+
17
+ path_prefix = if optional_path.present?
18
+ optional_path
19
+ else
20
+ preview_paths.one? ? preview_paths.first : "test/components/previews"
21
+ end
14
22
 
15
- path_prefix = preview_paths.one? ? preview_paths.first : "test/components/previews"
16
23
  template "component_preview.rb", File.join(path_prefix, class_path, "#{file_name}_component_preview.rb")
17
24
  end
18
25
 
@@ -19,9 +19,16 @@ module ViewComponent
19
19
  class << self
20
20
  delegate(*ViewComponent::Config.defaults.keys, to: :config)
21
21
 
22
+ # Returns the current config.
23
+ #
24
+ # @return [ViewComponent::Config]
22
25
  def config
23
26
  @config ||= ViewComponent::Config.defaults
24
27
  end
28
+
29
+ # Replaces the entire config. You shouldn't need to use this directly
30
+ # unless you're building a `ViewComponent::Config` elsewhere.
31
+ attr_writer :config
25
32
  end
26
33
 
27
34
  include ViewComponent::ContentAreas
@@ -123,11 +130,6 @@ module ViewComponent
123
130
  before_render
124
131
 
125
132
  if render?
126
- # Ensure `content` is evaluated before rendering the template, this is
127
- # needed so slots and other side-effects are performed before the
128
- # component template is evaluated.
129
- content if self.class.use_consistent_rendering_lifecycle
130
-
131
133
  render_template_for(@__vc_variant).to_s + output_postamble
132
134
  else
133
135
  ""
@@ -333,18 +335,6 @@ module ViewComponent
333
335
  # Defaults to `nil`. If this is falsy, `app/components` is used.
334
336
  #
335
337
 
336
- # Evaluate `#content` before `#call` to ensure side-effects are present
337
- # during component renders. This will be the default behavior in a future
338
- # release.
339
- #
340
- # ```ruby
341
- # config.view_component.use_consistent_rendering_lifecycle = true
342
- # ```
343
- #
344
- # Defaults to `false`
345
- #
346
- mattr_accessor :use_consistent_rendering_lifecycle, instance_writer: false, default: false
347
-
348
338
  # Parent class for generated components
349
339
  #
350
340
  # ```ruby
@@ -412,7 +402,7 @@ module ViewComponent
412
402
  # Find sidecar files for the given extensions.
413
403
  #
414
404
  # The provided array of extensions is expected to contain
415
- # strings starting without the "dot", example: `["erb", "haml"]`.
405
+ # strings starting without the dot, example: `["erb", "haml"]`.
416
406
  #
417
407
  # For example, one might collect sidecar CSS files that need to be compiled.
418
408
  # @param extensions [Array<String>] Extensions of which to return matching sidecar files.
@@ -590,7 +580,7 @@ module ViewComponent
590
580
  parameter = validate_default ? collection_parameter : provided_collection_parameter
591
581
 
592
582
  return unless parameter
593
- return if initialize_parameter_names.include?(parameter)
583
+ return if initialize_parameter_names.include?(parameter) || splatted_keyword_argument_present?
594
584
 
595
585
  # If Ruby can't parse the component class, then the initalize
596
586
  # parameters will be empty and ViewComponent will not be able to render
@@ -646,6 +636,11 @@ module ViewComponent
646
636
 
647
637
  private
648
638
 
639
+ def splatted_keyword_argument_present?
640
+ initialize_parameters.flatten.include?(:keyrest) &&
641
+ !initialize_parameters.include?([:keyrest, :**]) # Un-named splatted keyword args don't count!
642
+ end
643
+
649
644
  def initialize_parameter_names
650
645
  return attribute_names.map(&:to_sym) if respond_to?(:attribute_names)
651
646
 
@@ -30,10 +30,6 @@ module ViewComponent
30
30
  return if compiled? && !force
31
31
  return if component_class == ViewComponent::Base
32
32
 
33
- if RUBY_VERSION < "2.7.0"
34
- ViewComponent::Deprecation.warn("Support for Ruby versions < 2.7.0 will be removed in v3.0.0.")
35
- end
36
-
37
33
  component_class.superclass.compile(raise_errors: raise_errors) if should_compile_superclass?
38
34
  subclass_instance_methods = component_class.instance_methods(false)
39
35
 
@@ -51,9 +47,8 @@ module ViewComponent
51
47
  end
52
48
 
53
49
  if subclass_instance_methods.include?(:before_render_check)
54
- ViewComponent::Deprecation.warn(
55
- "`#before_render_check` will be removed in v3.0.0.\n\n" \
56
- "To fix this issue, use `#before_render` instead."
50
+ ViewComponent::Deprecation.deprecation_warning(
51
+ "`before_render_check`", :"`before_render`"
57
52
  )
58
53
  end
59
54
 
@@ -92,7 +87,7 @@ module ViewComponent
92
87
 
93
88
  def define_render_template_for
94
89
  variant_elsifs = variants.compact.uniq.map do |variant|
95
- "elsif variant.to_sym == :#{variant}\n #{call_method_name(variant)}"
90
+ "elsif variant.to_sym == :'#{variant}'\n #{call_method_name(variant)}"
96
91
  end.join("\n")
97
92
 
98
93
  body = <<-RUBY
@@ -163,6 +158,19 @@ module ViewComponent
163
158
  "There can only be a template file or inline render method per variant."
164
159
  end
165
160
 
161
+ uniq_variants = variants.compact.uniq
162
+ normalized_variants = uniq_variants.map { |variant| normalized_variant_name(variant) }
163
+
164
+ colliding_variants = uniq_variants.select do |variant|
165
+ normalized_variants.count(normalized_variant_name(variant)) > 1
166
+ end
167
+
168
+ unless colliding_variants.empty?
169
+ errors <<
170
+ "Colliding templates #{colliding_variants.sort.map { |v| "'#{v}'" }.to_sentence} " \
171
+ "found in #{component_class}."
172
+ end
173
+
166
174
  errors
167
175
  end
168
176
  end
@@ -176,7 +184,7 @@ module ViewComponent
176
184
  pieces = File.basename(path).split(".")
177
185
  memo << {
178
186
  path: path,
179
- variant: pieces.second.split("+").second&.to_sym,
187
+ variant: pieces[1..-2].join(".").split("+").second&.to_sym,
180
188
  handler: pieces.last
181
189
  }
182
190
  end
@@ -234,12 +242,16 @@ module ViewComponent
234
242
 
235
243
  def call_method_name(variant)
236
244
  if variant.present? && variants.include?(variant)
237
- "call_#{variant}"
245
+ "call_#{normalized_variant_name(variant)}"
238
246
  else
239
247
  "call"
240
248
  end
241
249
  end
242
250
 
251
+ def normalized_variant_name(variant)
252
+ variant.to_s.gsub("-", "__").gsub(".", "___")
253
+ end
254
+
243
255
  def should_compile_superclass?
244
256
  development? &&
245
257
  templates.empty? &&
@@ -12,7 +12,7 @@ module ViewComponent
12
12
 
13
13
  def defaults
14
14
  ActiveSupport::OrderedOptions.new.merge!({
15
- generate: ActiveSupport::OrderedOptions.new(false),
15
+ generate: default_generate_options,
16
16
  preview_controller: "ViewComponentsController",
17
17
  preview_route: "/rails/view_components",
18
18
  show_previews_source: false,
@@ -34,25 +34,25 @@ module ViewComponent
34
34
  # All options under this namespace default to `false` unless otherwise
35
35
  # stated.
36
36
  #
37
- # #### #sidecar
37
+ # #### `#sidecar`
38
38
  #
39
39
  # Always generate a component with a sidecar directory:
40
40
  #
41
41
  # config.view_component.generate.sidecar = true
42
42
  #
43
- # #### #stimulus_controller
43
+ # #### `#stimulus_controller`
44
44
  #
45
45
  # Always generate a Stimulus controller alongside the component:
46
46
  #
47
47
  # config.view_component.generate.stimulus_controller = true
48
48
  #
49
- # #### #locale
49
+ # #### `#locale`
50
50
  #
51
51
  # Always generate translations file alongside the component:
52
52
  #
53
53
  # config.view_component.generate.locale = true
54
54
  #
55
- # #### #distinct_locale_files
55
+ # #### `#distinct_locale_files`
56
56
  #
57
57
  # Always generate as many translations files as available locales:
58
58
  #
@@ -61,11 +61,22 @@ module ViewComponent
61
61
  # One file will be generated for each configured `I18n.available_locales`,
62
62
  # falling back to `[:en]` when no `available_locales` is defined.
63
63
  #
64
- # #### #preview
64
+ # #### `#preview`
65
65
  #
66
66
  # Always generate a preview alongside the component:
67
67
  #
68
68
  # config.view_component.generate.preview = true
69
+ #
70
+ # #### #preview_path
71
+ #
72
+ # Path to generate preview:
73
+ #
74
+ # config.view_component.generate.preview_path = "test/components/previews"
75
+ #
76
+ # Required when there is more than one path defined in preview_paths.
77
+ # Defaults to `""`. If this is blank, the generator will use
78
+ # `ViewComponent.config.preview_paths` if defined,
79
+ # `"test/components/previews"` otherwise
69
80
 
70
81
  # @!attribute preview_controller
71
82
  # @return [String]
@@ -135,6 +146,12 @@ module ViewComponent
135
146
 
136
147
  ["#{Rails.root}/test/components/previews"]
137
148
  end
149
+
150
+ def default_generate_options
151
+ options = ActiveSupport::OrderedOptions.new(false)
152
+ options.preview_path = ""
153
+ options
154
+ end
138
155
  end
139
156
 
140
157
  def initialize
@@ -146,7 +163,7 @@ module ViewComponent
146
163
  end
147
164
 
148
165
  def preview_path=(new_value)
149
- ViewComponent::Deprecation.warn("`preview_path` will be removed in v3.0.0. Use `preview_paths` instead.")
166
+ ViewComponent::Deprecation.deprecation_warning("`preview_path`", :"`preview_paths`")
150
167
  self.preview_paths = Array.wrap(new_value)
151
168
  end
152
169
 
@@ -31,9 +31,8 @@ module ViewComponent
31
31
 
32
32
  class_methods do
33
33
  def with_content_areas(*areas)
34
- ViewComponent::Deprecation.warn(
35
- "`with_content_areas` is deprecated and will be removed in ViewComponent v3.0.0.\n\n" \
36
- "Use slots (https://viewcomponent.org/guide/slots.html) instead."
34
+ ViewComponent::Deprecation.deprecation_warning(
35
+ "`with_content_areas`", "use slots (https://viewcomponent.org/guide/slots.html) instead"
37
36
  )
38
37
 
39
38
  if areas.include?(:content)
@@ -3,6 +3,6 @@
3
3
  require "active_support/deprecation"
4
4
 
5
5
  module ViewComponent
6
- DEPRECATION_HORIZON = 3
7
- Deprecation = ActiveSupport::Deprecation.new(DEPRECATION_HORIZON.to_s, "ViewComponent")
6
+ DEPRECATION_HORIZON = "3.0.0"
7
+ Deprecation = ActiveSupport::Deprecation.new(DEPRECATION_HORIZON, "ViewComponent")
8
8
  end
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  layout: default
3
- title: API
3
+ title: API reference
4
4
  nav_order: 3
5
5
  ---
6
6
 
@@ -57,7 +57,7 @@ module ViewComponent
57
57
 
58
58
  def call
59
59
  <<~DOCS.chomp
60
- #{separator}#{signature_or_name}#{types}#{suffix}
60
+ `#{separator}#{signature_or_name}`#{types}#{suffix}
61
61
 
62
62
  #{docstring_and_deprecation_text}
63
63
  DOCS
@@ -131,6 +131,12 @@ module ViewComponent
131
131
  end
132
132
  end
133
133
 
134
+ if Rails.env.test?
135
+ app.routes.prepend do
136
+ get("_system_test_entrypoint", to: "view_components_system_test#system_test_entrypoint")
137
+ end
138
+ end
139
+
134
140
  app.executor.to_run :before do
135
141
  CompileCache.invalidate! unless ActionView::Base.cache_template_loading
136
142
  end
@@ -138,13 +144,17 @@ module ViewComponent
138
144
  end
139
145
  end
140
146
 
147
+ if RUBY_VERSION < "2.7.0"
148
+ ViewComponent::Deprecation.deprecation_warning("Support for Ruby versions < 2.7.0")
149
+ end
150
+
141
151
  # :nocov:
142
152
  unless defined?(ViewComponent::Base)
143
153
  require "view_component/deprecation"
144
154
 
145
- ViewComponent::Deprecation.warn(
146
- "This manually engine loading is deprecated and will be removed in v3.0.0. " \
147
- 'Remove `require "view_component/engine"`.'
155
+ ViewComponent::Deprecation.deprecation_warning(
156
+ "Manually loading the engine",
157
+ "remove `require \"view_component/engine\"`"
148
158
  )
149
159
 
150
160
  require "view_component"
@@ -62,9 +62,9 @@ module ViewComponent
62
62
 
63
63
  define_method(setter_name) do |*args, &block|
64
64
  if _warn_on_deprecated_slot_setter
65
- ViewComponent::Deprecation.warn(
66
- "polymorphic slot setters like `#{setter_name}` are deprecated and will be removed in " \
67
- "ViewComponent v3.0.0.\n\nUse `with_#{setter_name}` instead."
65
+ ViewComponent::Deprecation.deprecation_warning(
66
+ "Using polymorphic slot setters like `#{setter_name}`",
67
+ :"`with_#{setter_name}`"
68
68
  )
69
69
  end
70
70
 
@@ -89,7 +89,7 @@ module ViewComponent
89
89
  def set_polymorphic_slot(slot_name, poly_type = nil, *args, &block)
90
90
  slot_definition = self.class.registered_slots[slot_name]
91
91
 
92
- if !slot_definition[:collection] && get_slot(slot_name)
92
+ if !slot_definition[:collection] && (defined?(@__vc_set_slots) && @__vc_set_slots[slot_name])
93
93
  raise ArgumentError, "content for slot '#{slot_name}' has already been provided"
94
94
  end
95
95
 
@@ -23,9 +23,8 @@ module ViewComponent
23
23
  # class_name: "Header" # class name string, used to instantiate Slot
24
24
  # )
25
25
  def with_slot(*slot_names, collection: false, class_name: nil)
26
- ViewComponent::Deprecation.warn(
27
- "`with_slot` is deprecated and will be removed in ViewComponent v3.0.0.\n" \
28
- "Use the new slots API (https://viewcomponent.org/guide/slots.html) instead."
26
+ ViewComponent::Deprecation.deprecation_warning(
27
+ "`with_slot`", "use the new slots API (https://viewcomponent.org/guide/slots.html) instead"
29
28
  )
30
29
 
31
30
  slot_names.each do |slot_name|
@@ -93,10 +93,12 @@ module ViewComponent
93
93
  else
94
94
  if _warn_on_deprecated_slot_setter
95
95
  stack = caller_locations(3)
96
- msg = "Setting a slot with `##{slot_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
97
- "Use `#with_#{slot_name}` to set the slot instead."
98
96
 
99
- ViewComponent::Deprecation.warn(msg, stack)
97
+ ViewComponent::Deprecation.deprecation_warning(
98
+ "Setting a slot with `##{slot_name}`",
99
+ "use `#with_#{slot_name}` to set the slot instead",
100
+ stack
101
+ )
100
102
  end
101
103
 
102
104
  set_slot(slot_name, nil, *args, &block)
@@ -159,9 +161,9 @@ module ViewComponent
159
161
 
160
162
  define_method singular_name do |*args, &block|
161
163
  if _warn_on_deprecated_slot_setter
162
- ViewComponent::Deprecation.warn(
163
- "Setting a slot with `##{singular_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
164
- "Use `#with_#{singular_name}` to set the slot instead."
164
+ ViewComponent::Deprecation.deprecation_warning(
165
+ "Setting a slot with `##{singular_name}`",
166
+ "use `#with_#{singular_name}` to set the slot instead"
165
167
  )
166
168
  end
167
169
 
@@ -187,9 +189,9 @@ module ViewComponent
187
189
  get_slot(slot_name)
188
190
  else
189
191
  if _warn_on_deprecated_slot_setter
190
- ViewComponent::Deprecation.warn(
191
- "Setting a slot with `##{slot_name}` is deprecated and will be removed in ViewComponent v3.0.0. " \
192
- "Use `#with_#{slot_name}` to set the slot instead."
192
+ ViewComponent::Deprecation.deprecation_warning(
193
+ "Setting a slot with `##{slot_name}`",
194
+ "use `#with_#{slot_name}` to set the slot instead"
193
195
  )
194
196
  end
195
197
 
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/test_case"
4
+
5
+ module ViewComponent
6
+ class SystemTestCase < ActionDispatch::SystemTestCase
7
+ include ViewComponent::SystemTestHelpers
8
+
9
+ def page
10
+ Capybara.current_session
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ViewComponent
4
+ module SystemTestHelpers
5
+ include TestHelpers
6
+
7
+ #
8
+ # Returns a block that can be used to visit the path of the inline rendered component.
9
+ # @param fragment [Nokogiri::Fragment] The fragment returned from `render_inline`.
10
+ # @param layout [String] The (optional) layout to use.
11
+ # @return [Proc] A block that can be used to visit the path of the inline rendered component.
12
+ def with_rendered_component_path(fragment, layout: false, &block)
13
+ # Add './tmp/view_components/' directory if it doesn't exist to store the rendered component HTML
14
+ FileUtils.mkdir_p("./tmp/view_components/") unless Dir.exist?("./tmp/view_components/")
15
+
16
+ file = Tempfile.new(["rendered_#{fragment.class.name}", ".html"], "tmp/view_components/")
17
+ begin
18
+ file.write(controller.render_to_string(html: fragment.to_html.html_safe, layout: layout))
19
+ file.rewind
20
+
21
+ block.call("/_system_test_entrypoint?file=#{file.path.split("/").last}")
22
+ ensure
23
+ file.unlink
24
+ end
25
+ end
26
+ end
27
+ end
@@ -35,10 +35,7 @@ module ViewComponent
35
35
  #
36
36
  # @return [String]
37
37
  def rendered_component
38
- ViewComponent::Deprecation.warn(
39
- "`rendered_component` is deprecated and will be removed in v3.0.0. " \
40
- "Use `page` instead."
41
- )
38
+ ViewComponent::Deprecation.deprecation_warning("`rendered_component`", :"`page`")
42
39
 
43
40
  rendered_content
44
41
  end
@@ -81,22 +78,10 @@ module ViewComponent
81
78
  # In RSpec, `Preview` is appended to `described_class`.
82
79
  #
83
80
  # @param name [String] The name of the preview to be rendered.
81
+ # @param from [ViewComponent::Preview] The class of the preview to be rendered.
84
82
  # @param params [Hash] Parameters to be passed to the preview.
85
83
  # @return [Nokogiri::HTML]
86
- def render_preview(name, params: {})
87
- begin
88
- preview_klass = if respond_to?(:described_class)
89
- raise "`render_preview` expected a described_class, but it is nil." if described_class.nil?
90
-
91
- "#{described_class}Preview"
92
- else
93
- self.class.name.gsub("Test", "Preview")
94
- end
95
- preview_klass = preview_klass.constantize
96
- rescue NameError
97
- raise NameError, "`render_preview` expected to find #{preview_klass}, but it does not exist."
98
- end
99
-
84
+ def render_preview(name, from: preview_class, params: {})
100
85
  previews_controller = build_controller(Rails.application.config.view_component.preview_controller.constantize)
101
86
 
102
87
  # From what I can tell, it's not possible to overwrite all request parameters
@@ -105,8 +90,8 @@ module ViewComponent
105
90
  previews_controller.request.params[k] = v
106
91
  end
107
92
 
108
- previews_controller.request.params[:path] = "#{preview_klass.preview_name}/#{name}"
109
- previews_controller.response = ActionDispatch::Response.new
93
+ previews_controller.request.params[:path] = "#{from.preview_name}/#{name}"
94
+ previews_controller.set_response!(ActionDispatch::Response.new)
110
95
  result = previews_controller.previews
111
96
 
112
97
  @rendered_content = result
@@ -114,21 +99,23 @@ module ViewComponent
114
99
  Nokogiri::HTML.fragment(@rendered_content)
115
100
  end
116
101
 
117
- # Execute the given block in the view context. Internally sets `page` to be a
118
- # `Capybara::Node::Simple`, allowing for Capybara assertions to be used:
102
+ # Execute the given block in the view context (using `instance_exec`).
103
+ # Internally sets `page` to be a `Capybara::Node::Simple`, allowing for
104
+ # Capybara assertions to be used. All arguments are forwarded to the block.
119
105
  #
120
106
  # ```ruby
121
- # render_in_view_context do
122
- # render(MyComponent.new)
107
+ # render_in_view_context(arg1, arg2:) do |arg1, arg2:|
108
+ # render(MyComponent.new(arg1, arg2))
123
109
  # end
124
110
  #
125
111
  # assert_text("Hello, World!")
126
112
  # ```
127
- def render_in_view_context(&block)
113
+ def render_in_view_context(*args, &block)
128
114
  @page = nil
129
- @rendered_content = controller.view_context.instance_exec(&block)
115
+ @rendered_content = controller.view_context.instance_exec(*args, &block)
130
116
  Nokogiri::HTML.fragment(@rendered_content)
131
117
  end
118
+ ruby2_keywords(:render_in_view_context) if respond_to?(:ruby2_keywords, true)
132
119
 
133
120
  # @private
134
121
  def controller
@@ -216,5 +203,20 @@ module ViewComponent
216
203
  def build_controller(klass)
217
204
  klass.new.tap { |c| c.request = request }.extend(Rails.application.routes.url_helpers)
218
205
  end
206
+
207
+ private
208
+
209
+ def preview_class
210
+ result = if respond_to?(:described_class)
211
+ raise "`render_preview` expected a described_class, but it is nil." if described_class.nil?
212
+
213
+ "#{described_class}Preview"
214
+ else
215
+ self.class.name.gsub("Test", "Preview")
216
+ end
217
+ result = result.constantize
218
+ rescue NameError
219
+ raise NameError, "`render_preview` expected to find #{result}, but it does not exist."
220
+ end
219
221
  end
220
222
  end
@@ -3,8 +3,8 @@
3
3
  module ViewComponent
4
4
  module VERSION
5
5
  MAJOR = 2
6
- MINOR = 74
7
- PATCH = 1
6
+ MINOR = 82
7
+ PATCH = 0
8
8
 
9
9
  STRING = [MAJOR, MINOR, PATCH].join(".")
10
10
  end
@@ -16,16 +16,18 @@ module ViewComponent
16
16
  autoload :Preview
17
17
  autoload :PreviewTemplateError
18
18
  autoload :TestHelpers
19
+ autoload :SystemTestHelpers
19
20
  autoload :TestCase
21
+ autoload :SystemTestCase
20
22
  autoload :TemplateError
21
23
  autoload :Translatable
22
24
  end
23
25
 
24
26
  # :nocov:
25
27
  if defined?(ViewComponent::Engine)
26
- ViewComponent::Deprecation.warn(
27
- "Manually loading the engine is deprecated and will be removed in v3.0.0. " \
28
- "Remove `require \"view_component/engine\"`."
28
+ ViewComponent::Deprecation.deprecation_warning(
29
+ "Manually loading the engine",
30
+ "remove `require \"view_component/engine\"`"
29
31
  )
30
32
  elsif defined?(Rails::Engine)
31
33
  require "view_component/engine"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: view_component
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.74.1
4
+ version: 2.82.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - ViewComponent Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-10-10 00:00:00.000000000 Z
11
+ date: 2023-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.0.0
19
+ version: 5.2.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: '8.0'
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 5.0.0
29
+ version: 5.2.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '8.0'
@@ -322,6 +322,7 @@ files:
322
322
  - app/assets/vendor/prism.min.js
323
323
  - app/controllers/concerns/view_component/preview_actions.rb
324
324
  - app/controllers/view_components_controller.rb
325
+ - app/controllers/view_components_system_test_controller.rb
325
326
  - app/helpers/preview_helper.rb
326
327
  - app/views/test_mailer/test_email.html.erb
327
328
  - app/views/view_components/_preview_source.html.erb
@@ -377,6 +378,8 @@ files:
377
378
  - lib/view_component/slot_v2.rb
378
379
  - lib/view_component/slotable.rb
379
380
  - lib/view_component/slotable_v2.rb
381
+ - lib/view_component/system_test_case.rb
382
+ - lib/view_component/system_test_helpers.rb
380
383
  - lib/view_component/template_error.rb
381
384
  - lib/view_component/test_case.rb
382
385
  - lib/view_component/test_helpers.rb