actionview 5.2.3

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.
Files changed (108) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +142 -0
  3. data/MIT-LICENSE +21 -0
  4. data/README.rdoc +38 -0
  5. data/lib/action_view.rb +97 -0
  6. data/lib/action_view/base.rb +215 -0
  7. data/lib/action_view/buffers.rb +52 -0
  8. data/lib/action_view/context.rb +36 -0
  9. data/lib/action_view/dependency_tracker.rb +175 -0
  10. data/lib/action_view/digestor.rb +134 -0
  11. data/lib/action_view/flows.rb +76 -0
  12. data/lib/action_view/gem_version.rb +17 -0
  13. data/lib/action_view/helpers.rb +68 -0
  14. data/lib/action_view/helpers/active_model_helper.rb +55 -0
  15. data/lib/action_view/helpers/asset_tag_helper.rb +511 -0
  16. data/lib/action_view/helpers/asset_url_helper.rb +469 -0
  17. data/lib/action_view/helpers/atom_feed_helper.rb +205 -0
  18. data/lib/action_view/helpers/cache_helper.rb +263 -0
  19. data/lib/action_view/helpers/capture_helper.rb +212 -0
  20. data/lib/action_view/helpers/controller_helper.rb +36 -0
  21. data/lib/action_view/helpers/csp_helper.rb +24 -0
  22. data/lib/action_view/helpers/csrf_helper.rb +35 -0
  23. data/lib/action_view/helpers/date_helper.rb +1156 -0
  24. data/lib/action_view/helpers/debug_helper.rb +36 -0
  25. data/lib/action_view/helpers/form_helper.rb +2337 -0
  26. data/lib/action_view/helpers/form_options_helper.rb +887 -0
  27. data/lib/action_view/helpers/form_tag_helper.rb +917 -0
  28. data/lib/action_view/helpers/javascript_helper.rb +94 -0
  29. data/lib/action_view/helpers/number_helper.rb +451 -0
  30. data/lib/action_view/helpers/output_safety_helper.rb +70 -0
  31. data/lib/action_view/helpers/record_tag_helper.rb +23 -0
  32. data/lib/action_view/helpers/rendering_helper.rb +99 -0
  33. data/lib/action_view/helpers/sanitize_helper.rb +177 -0
  34. data/lib/action_view/helpers/tag_helper.rb +313 -0
  35. data/lib/action_view/helpers/tags.rb +44 -0
  36. data/lib/action_view/helpers/tags/base.rb +192 -0
  37. data/lib/action_view/helpers/tags/check_box.rb +66 -0
  38. data/lib/action_view/helpers/tags/checkable.rb +18 -0
  39. data/lib/action_view/helpers/tags/collection_check_boxes.rb +36 -0
  40. data/lib/action_view/helpers/tags/collection_helpers.rb +119 -0
  41. data/lib/action_view/helpers/tags/collection_radio_buttons.rb +31 -0
  42. data/lib/action_view/helpers/tags/collection_select.rb +30 -0
  43. data/lib/action_view/helpers/tags/color_field.rb +27 -0
  44. data/lib/action_view/helpers/tags/date_field.rb +15 -0
  45. data/lib/action_view/helpers/tags/date_select.rb +74 -0
  46. data/lib/action_view/helpers/tags/datetime_field.rb +32 -0
  47. data/lib/action_view/helpers/tags/datetime_local_field.rb +21 -0
  48. data/lib/action_view/helpers/tags/datetime_select.rb +10 -0
  49. data/lib/action_view/helpers/tags/email_field.rb +10 -0
  50. data/lib/action_view/helpers/tags/file_field.rb +10 -0
  51. data/lib/action_view/helpers/tags/grouped_collection_select.rb +31 -0
  52. data/lib/action_view/helpers/tags/hidden_field.rb +10 -0
  53. data/lib/action_view/helpers/tags/label.rb +81 -0
  54. data/lib/action_view/helpers/tags/month_field.rb +15 -0
  55. data/lib/action_view/helpers/tags/number_field.rb +20 -0
  56. data/lib/action_view/helpers/tags/password_field.rb +14 -0
  57. data/lib/action_view/helpers/tags/placeholderable.rb +24 -0
  58. data/lib/action_view/helpers/tags/radio_button.rb +33 -0
  59. data/lib/action_view/helpers/tags/range_field.rb +10 -0
  60. data/lib/action_view/helpers/tags/search_field.rb +27 -0
  61. data/lib/action_view/helpers/tags/select.rb +43 -0
  62. data/lib/action_view/helpers/tags/tel_field.rb +10 -0
  63. data/lib/action_view/helpers/tags/text_area.rb +24 -0
  64. data/lib/action_view/helpers/tags/text_field.rb +34 -0
  65. data/lib/action_view/helpers/tags/time_field.rb +15 -0
  66. data/lib/action_view/helpers/tags/time_select.rb +10 -0
  67. data/lib/action_view/helpers/tags/time_zone_select.rb +22 -0
  68. data/lib/action_view/helpers/tags/translator.rb +44 -0
  69. data/lib/action_view/helpers/tags/url_field.rb +10 -0
  70. data/lib/action_view/helpers/tags/week_field.rb +15 -0
  71. data/lib/action_view/helpers/text_helper.rb +486 -0
  72. data/lib/action_view/helpers/translation_helper.rb +141 -0
  73. data/lib/action_view/helpers/url_helper.rb +676 -0
  74. data/lib/action_view/layouts.rb +433 -0
  75. data/lib/action_view/locale/en.yml +56 -0
  76. data/lib/action_view/log_subscriber.rb +96 -0
  77. data/lib/action_view/lookup_context.rb +274 -0
  78. data/lib/action_view/model_naming.rb +14 -0
  79. data/lib/action_view/path_set.rb +100 -0
  80. data/lib/action_view/railtie.rb +82 -0
  81. data/lib/action_view/record_identifier.rb +112 -0
  82. data/lib/action_view/renderer/abstract_renderer.rb +55 -0
  83. data/lib/action_view/renderer/partial_renderer.rb +552 -0
  84. data/lib/action_view/renderer/partial_renderer/collection_caching.rb +57 -0
  85. data/lib/action_view/renderer/renderer.rb +56 -0
  86. data/lib/action_view/renderer/streaming_template_renderer.rb +105 -0
  87. data/lib/action_view/renderer/template_renderer.rb +102 -0
  88. data/lib/action_view/rendering.rb +151 -0
  89. data/lib/action_view/routing_url_for.rb +145 -0
  90. data/lib/action_view/tasks/cache_digests.rake +25 -0
  91. data/lib/action_view/template.rb +361 -0
  92. data/lib/action_view/template/error.rb +141 -0
  93. data/lib/action_view/template/handlers.rb +66 -0
  94. data/lib/action_view/template/handlers/builder.rb +25 -0
  95. data/lib/action_view/template/handlers/erb.rb +74 -0
  96. data/lib/action_view/template/handlers/erb/erubi.rb +83 -0
  97. data/lib/action_view/template/handlers/html.rb +11 -0
  98. data/lib/action_view/template/handlers/raw.rb +11 -0
  99. data/lib/action_view/template/html.rb +34 -0
  100. data/lib/action_view/template/resolver.rb +391 -0
  101. data/lib/action_view/template/text.rb +33 -0
  102. data/lib/action_view/template/types.rb +57 -0
  103. data/lib/action_view/test_case.rb +300 -0
  104. data/lib/action_view/testing/resolvers.rb +54 -0
  105. data/lib/action_view/version.rb +10 -0
  106. data/lib/action_view/view_paths.rb +105 -0
  107. data/lib/assets/compiled/rails-ujs.js +720 -0
  108. metadata +255 -0
@@ -0,0 +1,300 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/redefine_method"
4
+ require "action_controller"
5
+ require "action_controller/test_case"
6
+ require "action_view"
7
+
8
+ require "rails-dom-testing"
9
+
10
+ module ActionView
11
+ # = Action View Test Case
12
+ class TestCase < ActiveSupport::TestCase
13
+ class TestController < ActionController::Base
14
+ include ActionDispatch::TestProcess
15
+
16
+ attr_accessor :request, :response, :params
17
+
18
+ class << self
19
+ attr_writer :controller_path
20
+ end
21
+
22
+ def controller_path=(path)
23
+ self.class.controller_path = (path)
24
+ end
25
+
26
+ def initialize
27
+ super
28
+ self.class.controller_path = ""
29
+ @request = ActionController::TestRequest.create(self.class)
30
+ @response = ActionDispatch::TestResponse.new
31
+
32
+ @request.env.delete("PATH_INFO")
33
+ @params = ActionController::Parameters.new
34
+ end
35
+ end
36
+
37
+ module Behavior
38
+ extend ActiveSupport::Concern
39
+
40
+ include ActionDispatch::Assertions, ActionDispatch::TestProcess
41
+ include Rails::Dom::Testing::Assertions
42
+ include ActionController::TemplateAssertions
43
+ include ActionView::Context
44
+
45
+ include ActionDispatch::Routing::PolymorphicRoutes
46
+
47
+ include AbstractController::Helpers
48
+ include ActionView::Helpers
49
+ include ActionView::RecordIdentifier
50
+ include ActionView::RoutingUrlFor
51
+
52
+ include ActiveSupport::Testing::ConstantLookup
53
+
54
+ delegate :lookup_context, to: :controller
55
+ attr_accessor :controller, :output_buffer, :rendered
56
+
57
+ module ClassMethods
58
+ def tests(helper_class)
59
+ case helper_class
60
+ when String, Symbol
61
+ self.helper_class = "#{helper_class.to_s.underscore}_helper".camelize.safe_constantize
62
+ when Module
63
+ self.helper_class = helper_class
64
+ end
65
+ end
66
+
67
+ def determine_default_helper_class(name)
68
+ determine_constant_from_test_name(name) do |constant|
69
+ Module === constant && !(Class === constant)
70
+ end
71
+ end
72
+
73
+ def helper_method(*methods)
74
+ # Almost a duplicate from ActionController::Helpers
75
+ methods.flatten.each do |method|
76
+ _helpers.module_eval <<-end_eval, __FILE__, __LINE__ + 1
77
+ def #{method}(*args, &block) # def current_user(*args, &block)
78
+ _test_case.send(%(#{method}), *args, &block) # _test_case.send(%(current_user), *args, &block)
79
+ end # end
80
+ end_eval
81
+ end
82
+ end
83
+
84
+ attr_writer :helper_class
85
+
86
+ def helper_class
87
+ @helper_class ||= determine_default_helper_class(name)
88
+ end
89
+
90
+ def new(*)
91
+ include_helper_modules!
92
+ super
93
+ end
94
+
95
+ private
96
+
97
+ def include_helper_modules!
98
+ helper(helper_class) if helper_class
99
+ include _helpers
100
+ end
101
+ end
102
+
103
+ def setup_with_controller
104
+ @controller = ActionView::TestCase::TestController.new
105
+ @request = @controller.request
106
+ @view_flow = ActionView::OutputFlow.new
107
+ # empty string ensures buffer has UTF-8 encoding as
108
+ # new without arguments returns ASCII-8BIT encoded buffer like String#new
109
+ @output_buffer = ActiveSupport::SafeBuffer.new ""
110
+ @rendered = "".dup
111
+
112
+ make_test_case_available_to_view!
113
+ say_no_to_protect_against_forgery!
114
+ end
115
+
116
+ def config
117
+ @controller.config if @controller.respond_to?(:config)
118
+ end
119
+
120
+ def render(options = {}, local_assigns = {}, &block)
121
+ view.assign(view_assigns)
122
+ @rendered << output = view.render(options, local_assigns, &block)
123
+ output
124
+ end
125
+
126
+ def rendered_views
127
+ @_rendered_views ||= RenderedViewsCollection.new
128
+ end
129
+
130
+ def _routes
131
+ @controller._routes if @controller.respond_to?(:_routes)
132
+ end
133
+
134
+ # Need to experiment if this priority is the best one: rendered => output_buffer
135
+ class RenderedViewsCollection
136
+ def initialize
137
+ @rendered_views ||= Hash.new { |hash, key| hash[key] = [] }
138
+ end
139
+
140
+ def add(view, locals)
141
+ @rendered_views[view] ||= []
142
+ @rendered_views[view] << locals
143
+ end
144
+
145
+ def locals_for(view)
146
+ @rendered_views[view]
147
+ end
148
+
149
+ def rendered_views
150
+ @rendered_views.keys
151
+ end
152
+
153
+ def view_rendered?(view, expected_locals)
154
+ locals_for(view).any? do |actual_locals|
155
+ expected_locals.all? { |key, value| value == actual_locals[key] }
156
+ end
157
+ end
158
+ end
159
+
160
+ included do
161
+ setup :setup_with_controller
162
+ ActiveSupport.run_load_hooks(:action_view_test_case, self)
163
+ end
164
+
165
+ private
166
+
167
+ # Need to experiment if this priority is the best one: rendered => output_buffer
168
+ def document_root_element
169
+ Nokogiri::HTML::Document.parse(@rendered.blank? ? @output_buffer : @rendered).root
170
+ end
171
+
172
+ def say_no_to_protect_against_forgery!
173
+ _helpers.module_eval do
174
+ silence_redefinition_of_method :protect_against_forgery?
175
+ def protect_against_forgery?
176
+ false
177
+ end
178
+ end
179
+ end
180
+
181
+ def make_test_case_available_to_view!
182
+ test_case_instance = self
183
+ _helpers.module_eval do
184
+ unless private_method_defined?(:_test_case)
185
+ define_method(:_test_case) { test_case_instance }
186
+ private :_test_case
187
+ end
188
+ end
189
+ end
190
+
191
+ module Locals
192
+ attr_accessor :rendered_views
193
+
194
+ def render(options = {}, local_assigns = {})
195
+ case options
196
+ when Hash
197
+ if block_given?
198
+ rendered_views.add options[:layout], options[:locals]
199
+ elsif options.key?(:partial)
200
+ rendered_views.add options[:partial], options[:locals]
201
+ end
202
+ else
203
+ rendered_views.add options, local_assigns
204
+ end
205
+
206
+ super
207
+ end
208
+ end
209
+
210
+ # The instance of ActionView::Base that is used by +render+.
211
+ def view
212
+ @view ||= begin
213
+ view = @controller.view_context
214
+ view.singleton_class.include(_helpers)
215
+ view.extend(Locals)
216
+ view.rendered_views = rendered_views
217
+ view.output_buffer = output_buffer
218
+ view
219
+ end
220
+ end
221
+
222
+ alias_method :_view, :view
223
+
224
+ INTERNAL_IVARS = [
225
+ :@NAME,
226
+ :@failures,
227
+ :@assertions,
228
+ :@__io__,
229
+ :@_assertion_wrapped,
230
+ :@_assertions,
231
+ :@_result,
232
+ :@_routes,
233
+ :@controller,
234
+ :@_layouts,
235
+ :@_files,
236
+ :@_rendered_views,
237
+ :@method_name,
238
+ :@output_buffer,
239
+ :@_partials,
240
+ :@passed,
241
+ :@rendered,
242
+ :@request,
243
+ :@routes,
244
+ :@tagged_logger,
245
+ :@_templates,
246
+ :@options,
247
+ :@test_passed,
248
+ :@view,
249
+ :@view_context_class,
250
+ :@view_flow,
251
+ :@_subscribers,
252
+ :@html_document
253
+ ]
254
+
255
+ def _user_defined_ivars
256
+ instance_variables - INTERNAL_IVARS
257
+ end
258
+
259
+ # Returns a Hash of instance variables and their values, as defined by
260
+ # the user in the test case, which are then assigned to the view being
261
+ # rendered. This is generally intended for internal use and extension
262
+ # frameworks.
263
+ def view_assigns
264
+ Hash[_user_defined_ivars.map do |ivar|
265
+ [ivar[1..-1].to_sym, instance_variable_get(ivar)]
266
+ end]
267
+ end
268
+
269
+ def method_missing(selector, *args)
270
+ begin
271
+ routes = @controller.respond_to?(:_routes) && @controller._routes
272
+ rescue
273
+ # Don't call routes, if there is an error on _routes call
274
+ end
275
+
276
+ if routes &&
277
+ (routes.named_routes.route_defined?(selector) ||
278
+ routes.mounted_helpers.method_defined?(selector))
279
+ @controller.__send__(selector, *args)
280
+ else
281
+ super
282
+ end
283
+ end
284
+
285
+ def respond_to_missing?(name, include_private = false)
286
+ begin
287
+ routes = @controller.respond_to?(:_routes) && @controller._routes
288
+ rescue
289
+ # Don't call routes, if there is an error on _routes call
290
+ end
291
+
292
+ routes &&
293
+ (routes.named_routes.route_defined?(name) ||
294
+ routes.mounted_helpers.method_defined?(name))
295
+ end
296
+ end
297
+
298
+ include Behavior
299
+ end
300
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "action_view/template/resolver"
4
+
5
+ module ActionView #:nodoc:
6
+ # Use FixtureResolver in your tests to simulate the presence of files on the
7
+ # file system. This is used internally by Rails' own test suite, and is
8
+ # useful for testing extensions that have no way of knowing what the file
9
+ # system will look like at runtime.
10
+ class FixtureResolver < PathResolver
11
+ attr_reader :hash
12
+
13
+ def initialize(hash = {}, pattern = nil)
14
+ super(pattern)
15
+ @hash = hash
16
+ end
17
+
18
+ def to_s
19
+ @hash.keys.join(", ")
20
+ end
21
+
22
+ private
23
+
24
+ def query(path, exts, _, _)
25
+ query = "".dup
26
+ EXTENSIONS.each_key do |ext|
27
+ query << "(" << exts[ext].map { |e| e && Regexp.escape(".#{e}") }.join("|") << "|)"
28
+ end
29
+ query = /^(#{Regexp.escape(path)})#{query}$/
30
+
31
+ templates = []
32
+ @hash.each do |_path, array|
33
+ source, updated_at = array
34
+ next unless query.match?(_path)
35
+ handler, format, variant = extract_handler_and_format_and_variant(_path)
36
+ templates << Template.new(source, _path, handler,
37
+ virtual_path: path.virtual,
38
+ format: format,
39
+ variant: variant,
40
+ updated_at: updated_at
41
+ )
42
+ end
43
+
44
+ templates.sort_by { |t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
45
+ end
46
+ end
47
+
48
+ class NullResolver < PathResolver
49
+ def query(path, exts, _, _)
50
+ handler, format, variant = extract_handler_and_format_and_variant(path)
51
+ [ActionView::Template.new("Template generated by Null Resolver", path.virtual, handler, virtual_path: path.virtual, format: format, variant: variant)]
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "gem_version"
4
+
5
+ module ActionView
6
+ # Returns the version of the currently loaded ActionView as a <tt>Gem::Version</tt>
7
+ def self.version
8
+ gem_version
9
+ end
10
+ end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActionView
4
+ module ViewPaths
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_view_paths, default: ActionView::PathSet.new.freeze
9
+ end
10
+
11
+ delegate :template_exists?, :any_templates?, :view_paths, :formats, :formats=,
12
+ :locale, :locale=, to: :lookup_context
13
+
14
+ module ClassMethods
15
+ def _prefixes # :nodoc:
16
+ @_prefixes ||= begin
17
+ return local_prefixes if superclass.abstract?
18
+
19
+ local_prefixes + superclass._prefixes
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ # Override this method in your controller if you want to change paths prefixes for finding views.
26
+ # Prefixes defined here will still be added to parents' <tt>._prefixes</tt>.
27
+ def local_prefixes
28
+ [controller_path]
29
+ end
30
+ end
31
+
32
+ # The prefixes used in render "foo" shortcuts.
33
+ def _prefixes # :nodoc:
34
+ self.class._prefixes
35
+ end
36
+
37
+ # <tt>LookupContext</tt> is the object responsible for holding all
38
+ # information required for looking up templates, i.e. view paths and
39
+ # details. Check <tt>ActionView::LookupContext</tt> for more information.
40
+ def lookup_context
41
+ @_lookup_context ||=
42
+ ActionView::LookupContext.new(self.class._view_paths, details_for_lookup, _prefixes)
43
+ end
44
+
45
+ def details_for_lookup
46
+ {}
47
+ end
48
+
49
+ # Append a path to the list of view paths for the current <tt>LookupContext</tt>.
50
+ #
51
+ # ==== Parameters
52
+ # * <tt>path</tt> - If a String is provided, it gets converted into
53
+ # the default view path. You may also provide a custom view path
54
+ # (see ActionView::PathSet for more information)
55
+ def append_view_path(path)
56
+ lookup_context.view_paths.push(*path)
57
+ end
58
+
59
+ # Prepend a path to the list of view paths for the current <tt>LookupContext</tt>.
60
+ #
61
+ # ==== Parameters
62
+ # * <tt>path</tt> - If a String is provided, it gets converted into
63
+ # the default view path. You may also provide a custom view path
64
+ # (see ActionView::PathSet for more information)
65
+ def prepend_view_path(path)
66
+ lookup_context.view_paths.unshift(*path)
67
+ end
68
+
69
+ module ClassMethods
70
+ # Append a path to the list of view paths for this controller.
71
+ #
72
+ # ==== Parameters
73
+ # * <tt>path</tt> - If a String is provided, it gets converted into
74
+ # the default view path. You may also provide a custom view path
75
+ # (see ActionView::PathSet for more information)
76
+ def append_view_path(path)
77
+ self._view_paths = view_paths + Array(path)
78
+ end
79
+
80
+ # Prepend a path to the list of view paths for this controller.
81
+ #
82
+ # ==== Parameters
83
+ # * <tt>path</tt> - If a String is provided, it gets converted into
84
+ # the default view path. You may also provide a custom view path
85
+ # (see ActionView::PathSet for more information)
86
+ def prepend_view_path(path)
87
+ self._view_paths = ActionView::PathSet.new(Array(path) + view_paths)
88
+ end
89
+
90
+ # A list of all of the default view paths for this controller.
91
+ def view_paths
92
+ _view_paths
93
+ end
94
+
95
+ # Set the view paths.
96
+ #
97
+ # ==== Parameters
98
+ # * <tt>paths</tt> - If a PathSet is provided, use that;
99
+ # otherwise, process the parameter into a PathSet.
100
+ def view_paths=(paths)
101
+ self._view_paths = ActionView::PathSet.new(Array(paths))
102
+ end
103
+ end
104
+ end
105
+ end