view_component 2.74.1 → 2.82.0

Sign up to get free protection for your applications and to get access to all the features.

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