formtastic 5.0.0 → 6.0.0.alpha

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/integration.yaml +36 -0
  3. data/.github/workflows/test.yml +26 -20
  4. data/.gitignore +2 -1
  5. data/Appraisals +23 -0
  6. data/CHANGELOG.md +18 -0
  7. data/CONTRIBUTING.md +27 -0
  8. data/Gemfile +5 -0
  9. data/MIT-LICENSE +1 -1
  10. data/README.md +9 -41
  11. data/Rakefile +1 -1
  12. data/formtastic.gemspec +17 -10
  13. data/gemfiles/rails_72.gemfile +9 -0
  14. data/gemfiles/rails_80.gemfile +9 -0
  15. data/gemfiles/rails_81.gemfile +9 -0
  16. data/gemfiles/rails_edge.gemfile +9 -0
  17. data/lib/formtastic/form_builder.rb +25 -25
  18. data/lib/formtastic/helpers/action_helper.rb +0 -1
  19. data/lib/formtastic/helpers/errors_helper.rb +71 -14
  20. data/lib/formtastic/helpers/input_helper.rb +4 -2
  21. data/lib/formtastic/i18n.rb +0 -1
  22. data/lib/formtastic/inputs/base/aria.rb +26 -0
  23. data/lib/formtastic/inputs/base/collections.rb +1 -1
  24. data/lib/formtastic/inputs/base/errors.rb +1 -1
  25. data/lib/formtastic/inputs/base/html.rb +1 -1
  26. data/lib/formtastic/inputs/base/labelling.rb +1 -1
  27. data/lib/formtastic/inputs/base/validations.rb +32 -8
  28. data/lib/formtastic/inputs/base.rb +4 -2
  29. data/lib/formtastic/inputs/country_input.rb +9 -6
  30. data/lib/formtastic/version.rb +1 -1
  31. data/lib/formtastic.rb +6 -2
  32. data/lib/generators/formtastic/form/form_generator.rb +2 -3
  33. data/lib/generators/formtastic/install/install_generator.rb +0 -1
  34. data/lib/generators/formtastic/stylesheets/stylesheets_generator.rb +15 -0
  35. data/{app/assets/stylesheets → lib/generators/templates}/formtastic.css +4 -4
  36. data/lib/generators/templates/formtastic.rb +7 -1
  37. data/script/integration-template.rb +14 -11
  38. data/script/integration.sh +17 -4
  39. data/spec/action_class_finder_spec.rb +0 -1
  40. data/spec/actions/button_action_spec.rb +0 -1
  41. data/spec/actions/generic_action_spec.rb +0 -1
  42. data/spec/actions/input_action_spec.rb +0 -1
  43. data/spec/actions/link_action_spec.rb +0 -1
  44. data/spec/builder/custom_builder_spec.rb +0 -1
  45. data/spec/builder/error_proc_spec.rb +0 -1
  46. data/spec/builder/semantic_fields_for_spec.rb +72 -2
  47. data/spec/fast_spec_helper.rb +0 -1
  48. data/spec/generators/formtastic/stylesheets/stylesheets_generator_spec.rb +22 -0
  49. data/spec/helpers/actions_helper_spec.rb +0 -1
  50. data/spec/helpers/form_helper_spec.rb +0 -1
  51. data/spec/helpers/input_helper_spec.rb +12 -1
  52. data/spec/helpers/inputs_helper_spec.rb +0 -1
  53. data/spec/helpers/reflection_helper_spec.rb +0 -1
  54. data/spec/helpers/semantic_errors_helper_spec.rb +114 -7
  55. data/spec/i18n_spec.rb +0 -1
  56. data/spec/input_class_finder_spec.rb +0 -1
  57. data/spec/inputs/base/collections_spec.rb +41 -0
  58. data/spec/inputs/boolean_input_spec.rb +0 -1
  59. data/spec/inputs/check_boxes_input_spec.rb +1 -2
  60. data/spec/inputs/color_input_spec.rb +0 -1
  61. data/spec/inputs/country_input_spec.rb +5 -6
  62. data/spec/inputs/custom_input_spec.rb +0 -1
  63. data/spec/inputs/datalist_input_spec.rb +0 -1
  64. data/spec/inputs/date_picker_input_spec.rb +0 -1
  65. data/spec/inputs/date_select_input_spec.rb +1 -2
  66. data/spec/inputs/datetime_picker_input_spec.rb +0 -1
  67. data/spec/inputs/datetime_select_input_spec.rb +1 -2
  68. data/spec/inputs/email_input_spec.rb +0 -1
  69. data/spec/inputs/file_input_spec.rb +0 -1
  70. data/spec/inputs/hidden_input_spec.rb +0 -1
  71. data/spec/inputs/include_blank_spec.rb +0 -1
  72. data/spec/inputs/label_spec.rb +32 -1
  73. data/spec/inputs/number_input_spec.rb +0 -1
  74. data/spec/inputs/password_input_spec.rb +1 -2
  75. data/spec/inputs/phone_input_spec.rb +0 -1
  76. data/spec/inputs/placeholder_spec.rb +0 -1
  77. data/spec/inputs/radio_input_spec.rb +0 -1
  78. data/spec/inputs/range_input_spec.rb +0 -1
  79. data/spec/inputs/readonly_spec.rb +0 -1
  80. data/spec/inputs/search_input_spec.rb +0 -1
  81. data/spec/inputs/select_input_spec.rb +0 -1
  82. data/spec/inputs/string_input_spec.rb +67 -2
  83. data/spec/inputs/text_input_spec.rb +0 -1
  84. data/spec/inputs/time_picker_input_spec.rb +0 -1
  85. data/spec/inputs/time_select_input_spec.rb +1 -2
  86. data/spec/inputs/time_zone_input_spec.rb +0 -1
  87. data/spec/inputs/url_input_spec.rb +0 -1
  88. data/spec/inputs/with_options_spec.rb +0 -1
  89. data/spec/localizer_spec.rb +0 -1
  90. data/spec/namespaced_class_finder_spec.rb +0 -1
  91. data/spec/spec_helper.rb +2 -1
  92. data/spec/support/custom_macros.rb +11 -3
  93. data/spec/support/specialized_class_finder_shared_example.rb +0 -1
  94. data/spec/support/test_environment.rb +1 -1
  95. metadata +53 -40
  96. data/Gemfile.lock +0 -140
  97. data/app/assets/stylesheets/formtastic_ie6.css +0 -33
  98. data/app/assets/stylesheets/formtastic_ie7.css +0 -23
  99. data/gemfiles/rails_6.0/Gemfile +0 -5
  100. data/gemfiles/rails_6.1/Gemfile +0 -5
  101. data/gemfiles/rails_7.0/Gemfile +0 -5
  102. data/gemfiles/rails_7.1/Gemfile +0 -5
  103. data/gemfiles/rails_edge/Gemfile +0 -13
  104. data/lib/formtastic/engine.rb +0 -14
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+ module Formtastic
3
+ module Inputs
4
+ module Base
5
+ module Aria
6
+
7
+ def error_aria_attributes
8
+ return {} unless builder.semantic_errors_link_to_inputs
9
+ return {} unless errors?
10
+
11
+ {
12
+ 'aria-describedby': describedby,
13
+ 'aria-invalid': options.dig(:input_html, :'aria-invalid') || 'true'
14
+ }
15
+ end
16
+
17
+ def describedby
18
+ describedby = options.dig(:input_html, :'aria-describedby') || ''
19
+ describedby += ' ' unless describedby.empty?
20
+ describedby += "#{method}_error"
21
+ end
22
+
23
+ end
24
+ end
25
+ end
26
+ end
@@ -53,7 +53,7 @@ module Formtastic
53
53
 
54
54
  # Return if we have an Array of strings, integers or arrays
55
55
  return raw_collection if (raw_collection.instance_of?(Array) || raw_collection.instance_of?(Range)) &&
56
- ([Array, String].include?(raw_collection.first.class) || raw_collection.first.is_a?(Integer)) &&
56
+ ([Array, String, Symbol].include?(raw_collection.first.class) || raw_collection.first.is_a?(Integer)) &&
57
57
  !(options.include?(:member_label) || options.include?(:member_value))
58
58
 
59
59
  raw_collection.map { |o| [send_or_call(label_method, o), send_or_call(value_method, o)] }
@@ -10,7 +10,7 @@ module Formtastic
10
10
 
11
11
  def error_sentence_html
12
12
  error_class = builder.default_inline_error_class
13
- template.content_tag(:p, errors.to_sentence, :class => error_class)
13
+ template.content_tag(:p, errors.to_sentence, id: "#{method}_error", :class => error_class)
14
14
  end
15
15
 
16
16
  def error_list_html
@@ -25,7 +25,7 @@ module Formtastic
25
25
  :required => required_attribute?,
26
26
  :autofocus => autofocus?,
27
27
  :readonly => readonly?
28
- }.merge(options[:input_html] || {})
28
+ }.merge(options[:input_html] || {}).merge(error_aria_attributes)
29
29
  end
30
30
 
31
31
  def dom_id
@@ -14,7 +14,7 @@ module Formtastic
14
14
  {
15
15
  :for => input_html_options[:id],
16
16
  :class => ['label'],
17
- }
17
+ }.merge(options[:label_html] || {})
18
18
  end
19
19
 
20
20
  def label_text
@@ -57,7 +57,8 @@ module Formtastic
57
57
  validation.kind == :length
58
58
  end
59
59
  if validation
60
- validation.options[:maximum] || (validation.options[:within].present? ? validation.options[:within].max : nil)
60
+ option_value(validation.options[:maximum], object) ||
61
+ (validation.options[:within].present? ? option_value(validation.options[:within], object).max : nil)
61
62
  else
62
63
  nil
63
64
  end
@@ -145,8 +146,8 @@ module Formtastic
145
146
  validator.options[:allow_blank] != true
146
147
  when :length
147
148
  validator.options[:allow_blank] != true &&
148
- validator.options[:minimum].to_i > 0 ||
149
- validator.options[:within].try(:first).to_i > 0
149
+ option_value(validator.options[:minimum], object).to_i > 0 ||
150
+ option_value(validator.options[:within], object).try(:first).to_i > 0
150
151
  else
151
152
  false
152
153
  end
@@ -183,7 +184,22 @@ module Formtastic
183
184
  end
184
185
 
185
186
  def column_limit
186
- column.limit if column? && column.respond_to?(:limit)
187
+ return unless column?
188
+ return unless column.respond_to?(:limit)
189
+
190
+ limit = column.limit # already in characters for string, text, etc
191
+
192
+ if column.type == :integer && column.limit.is_a?(Integer)
193
+ return {
194
+ 1 => 3, # 8 bit
195
+ 2 => 5, # 16 bit
196
+ 3 => 7, # 24 bit
197
+ 4 => 10, # 32 bit
198
+ 8 => 19, # 64 bit
199
+ }[limit] || nil
200
+ end
201
+
202
+ return limit
187
203
  end
188
204
 
189
205
  def limit
@@ -208,16 +224,24 @@ module Formtastic
208
224
 
209
225
  private
210
226
 
211
- # Loosely based on
212
- # https://github.com/rails/rails/blob/459e7cf62252558bbf65f582a230562ab1a76c5e/activemodel/lib/active_model/validations/numericality.rb#L65-L70
227
+ # Implements `ActiveModel::Validations::ResolveValue`, introduced by Rails 7.1.
228
+ # https://github.com/rails/rails/blob/v7.1.0/activemodel/lib/active_model/validations/resolve_value.rb
213
229
  def option_value(option, object)
214
230
  case option
215
231
  when Symbol
216
232
  object.send(option)
217
233
  when Proc
218
- option.call(object)
234
+ if option.arity == 0
235
+ option.call
236
+ else
237
+ option.call(object)
238
+ end
219
239
  else
220
- option
240
+ if option.respond_to?(:call)
241
+ option.call(object)
242
+ else
243
+ option
244
+ end
221
245
  end
222
246
  end
223
247
  end
@@ -22,7 +22,7 @@ module Formtastic
22
22
  # Usefull for deprecating options.
23
23
  def warn_and_correct_option!(old_option_name, new_option_name)
24
24
  if options.key?(old_option_name)
25
- Deprecation.warn("The :#{old_option_name} option is deprecated in favour of :#{new_option_name} and will be removed from Formtastic in the next version", caller(6))
25
+ Deprecation.warn("The :#{old_option_name} option is deprecated in favour of :#{new_option_name} and will be removed from Formtastic in the next version", caller_locations(6))
26
26
  options[new_option_name] = options.delete(old_option_name)
27
27
  end
28
28
  end
@@ -30,7 +30,7 @@ module Formtastic
30
30
  # Usefull for deprecating options.
31
31
  def warn_deprecated_option!(old_option_name, instructions)
32
32
  if options.key?(old_option_name)
33
- Deprecation.warn("The :#{old_option_name} option is deprecated in favour of `#{instructions}`. :#{old_option_name} will be removed in the next version", caller(6))
33
+ Deprecation.warn("The :#{old_option_name} option is deprecated in favour of `#{instructions}`. :#{old_option_name} will be removed in the next version", caller_locations(6))
34
34
  end
35
35
  end
36
36
 
@@ -59,6 +59,7 @@ module Formtastic
59
59
  autoload :Timeish
60
60
  autoload :Validations
61
61
  autoload :Wrapping
62
+ autoload :Aria
62
63
 
63
64
  include Html
64
65
  include Options
@@ -71,6 +72,7 @@ module Formtastic
71
72
  include Associations
72
73
  include Labelling
73
74
  include Wrapping
75
+ include Aria
74
76
 
75
77
  end
76
78
  end
@@ -5,13 +5,10 @@ module Formtastic
5
5
  # Rails doesn't come with a `country_select` helper by default any more, so you'll need to do
6
6
  # one of the following:
7
7
  #
8
- # * install the [country_select](https://github.com/stefanpenner/country_select) gem
8
+ # * install the [country_select](https://github.com/countries/country_select) gem
9
9
  # * install any other country_select plugin that behaves in a similar way
10
10
  # * roll your own `country_select` helper with the same args and options as the Rails one
11
11
  #
12
- # Formtastic supports both 1.x and 2.x of stefanpenner/country_select, but if you're upgrading
13
- # from 1.x, they behave quite differently, so please see their [upgrade instructions](https://github.com/stefanpenner/country_select/blob/master/UPGRADING.md).
14
- #
15
12
  # By default, Formtastic includes a handful of English-speaking countries as "priority
16
13
  # countries", which can be set in the `priority_countries` configuration array in the
17
14
  # formtastic.rb initializer to suit your market and user base (see README for more info on
@@ -71,12 +68,18 @@ module Formtastic
71
68
  CountrySelectPluginMissing = Class.new(StandardError)
72
69
 
73
70
  def to_html
74
- raise CountrySelectPluginMissing, "To use the :country input, please install a country_select plugin, like this one: https://github.com/stefanpenner/country_select" unless builder.respond_to?(:country_select)
71
+ raise CountrySelectPluginMissing, "To use the :country input, please install a country_select plugin, like this one: https://github.com/countries/country_select" unless builder.respond_to?(:country_select)
75
72
  input_wrapping do
76
73
  label_html <<
77
- builder.country_select(method, priority_countries, input_options, input_html_options)
74
+ builder.country_select(method, input_options_including_priorities, input_html_options)
78
75
  end
79
76
  end
77
+
78
+ def input_options_including_priorities
79
+ return input_options unless priority_countries
80
+
81
+ input_options.merge(:priority_countries => priority_countries)
82
+ end
80
83
 
81
84
  def priority_countries
82
85
  options[:priority_countries] || builder.priority_countries
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Formtastic
3
- VERSION = "5.0.0"
3
+ VERSION = "6.0.0.alpha"
4
4
  end
data/lib/formtastic.rb CHANGED
@@ -1,6 +1,4 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
- require 'formtastic/engine' if defined?(::Rails)
4
2
 
5
3
  module Formtastic
6
4
  extend ActiveSupport::Autoload
@@ -42,3 +40,9 @@ module Formtastic
42
40
  end
43
41
 
44
42
  end
43
+
44
+ if defined?(::Rails)
45
+ ActiveSupport.on_load(:action_view) do
46
+ include Formtastic::Helpers::FormHelper
47
+ end
48
+ end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  module Formtastic
4
3
  # Generates a Formtastic form partial based on an existing model. It will not overwrite existing
@@ -33,7 +32,7 @@ module Formtastic
33
32
  class_option :copy, :type => :boolean, :default => false, :group => :formtastic,
34
33
  :desc => 'Copy the generated code the clipboard instead of generating a partial file."'
35
34
 
36
- class_option :controller, :type => :string, :default => false, :group => :formtastic,
35
+ class_option :controller, :type => :string, :default => nil, :group => :formtastic,
37
36
  :desc => 'Generate for custom controller/view path - in case model and controller namespace is different, i.e. "admin/posts"'
38
37
 
39
38
  def create_or_show
@@ -43,7 +42,7 @@ module Formtastic
43
42
 
44
43
  if options[:copy]
45
44
  template = File.read("#{self.class.source_root}/_form.html.#{engine}")
46
- erb = ERB.new(template, nil, '-')
45
+ erb = ERB.new(template, trim_mode: '-')
47
46
  generated_code = erb.result(binding).strip rescue nil
48
47
  puts "The following code has been copied to the clipboard, just paste it in your views:" if save_to_clipboard(generated_code)
49
48
  puts generated_code || "Error: Nothing generated. Does the model exist?"
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  module Formtastic
@@ -0,0 +1,15 @@
1
+ module Formtastic
2
+ # Copies a stylesheet into to app/assets/stylesheets/formtastic.css
3
+ #
4
+ # @example
5
+ # !!!shell
6
+ # $ rails generate formtastic:stylesheets
7
+ class StylesheetsGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("../../../templates", __FILE__)
9
+
10
+ desc "Copies Formtastic example stylesheet into your app"
11
+ def copy_files
12
+ copy_file "formtastic.css", "app/assets/stylesheets/formtastic.css"
13
+ end
14
+ end
15
+ end
@@ -4,8 +4,8 @@ It's *strongly* suggested that you don't modify this file. Instead, load a new
4
4
  this one in your layouts (eg formtastic_changes.css) and override the styles to suit your needs.
5
5
  This will allow you to update formtastic.css with new releases without clobbering your own changes.
6
6
 
7
- This stylesheet forms part of the Formtastic Rails Plugin
8
- (c) 2008-2011 Justin French
7
+ This stylesheet forms part of the Formtastic Rails gem
8
+ (c) Justin French
9
9
 
10
10
  --------------------------------------------------------------------------------------------------*/
11
11
 
@@ -84,13 +84,13 @@ This stylesheet forms part of the Formtastic Rails Plugin
84
84
 
85
85
  /* BUTTONS & ACTIONS
86
86
  --------------------------------------------------------------------------------------------------*/
87
- .formtastic .buttons,
87
+ .formtastic .buttons,
88
88
  .formtastic .actions {
89
89
  overflow:hidden; /* clear containing floats */
90
90
  padding-left:25%;
91
91
  }
92
92
 
93
- .formtastic .button,
93
+ .formtastic .button,
94
94
  .formtastic .action {
95
95
  float:left;
96
96
  padding-right:0.5em;
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
 
4
3
  # Set the default text field size when input is a string. Default is nil.
@@ -110,3 +109,10 @@
110
109
 
111
110
  # Which columns to skip when automatically rendering a form without any fields specified.
112
111
  # Formtastic::FormBuilder.skipped_columns = [:created_at, :updated_at, :created_on, :updated_on, :lock_version, :version]
112
+
113
+ # You can opt-in to accessibility features for the `semantic_errors` helper by setting
114
+ # this to true. Doing so will render the attributes in the error summary list
115
+ # as `<li> <a>` links to the inputs that have errors. the inline error sentence's id is added to
116
+ # the errored input's aria-describedby. This ensures that the errored input is read out with
117
+ # the inline error sentence's error explanation, aria-invalid is set to true for errored inputs
118
+ # Formtastic::FormBuilder.semantic_errors_link_to_inputs = true
@@ -1,20 +1,21 @@
1
1
  # frozen_string_literal: true
2
2
  gem 'formtastic', path: '..'
3
- gem 'bcrypt', '~> 3.1.7'
3
+ gem 'bcrypt'
4
4
  gem 'rails-dom-testing', group: :test
5
- gem 'rexml', '~> 3.2' # to compensate for missing dependency in selenium-webdriver
5
+
6
+ gem 'minitest', '~> 5.27' # TODO: Remove this line when the Rails version used for integration tests will include rails/rails#56202
6
7
 
7
8
  # to speed up bundle install, reuse the bundle path
8
9
  def bundle_path
9
10
  File.expand_path ENV.fetch('BUNDLE_PATH', 'vendor/bundle')
10
11
  end
11
12
 
12
- if Rails.version >= '6.2'
13
- gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails'"
14
- elsif Rails.version >= '6.1'
15
- gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '6-1-stable'"
16
- elsif Rails.version >= '6.0'
17
- gsub_file 'Gemfile', /gem 'rails'.*/, "gem 'rails', '~> #{Rails.version}', github: 'rails/rails', branch: '6-0-stable'"
13
+ if Rails.version >= '8.1'
14
+ gsub_file 'Gemfile', /gem "rails".*/, %(gem "rails", "~> #{Rails.version}", github: "rails/rails", branch: "8-1-stable")
15
+ elsif Rails.version >= '8.0'
16
+ gsub_file 'Gemfile', /gem "rails".*/, %(gem "rails", "~> #{Rails.version}", github: "rails/rails", branch: "8-0-stable")
17
+ elsif Rails.version >= '7.2'
18
+ gsub_file 'Gemfile', /gem "rails".*/, %(gem "rails", "~> #{Rails.version}", github: "rails/rails", branch: "7-2-stable")
18
19
  end
19
20
 
20
21
  ### Ensure Dummy App's Ruby version matches the current environments Ruby Version
@@ -26,8 +27,9 @@ if bundle_install?
26
27
  previous_bundle_path = bundle_path
27
28
 
28
29
  require "bundler"
29
- Bundler.with_clean_env do
30
- system("bundle install --jobs=3 --retry=3 --path=#{previous_bundle_path}")
30
+ Bundler.with_original_env do
31
+ system("bundle config set path '#{previous_bundle_path}'")
32
+ system("bundle install --jobs=3 --retry=3")
31
33
  end
32
34
  end
33
35
  end
@@ -40,12 +42,13 @@ formtastic = -> do
40
42
  generate(:scaffold, 'user name:string password:digest')
41
43
  generate('formtastic:install')
42
44
  generate('formtastic:form', 'user name password --force')
45
+ generate('formtastic:stylesheets')
43
46
 
44
47
  rails_command('db:migrate')
48
+ rails_command('assets:precompile')
45
49
 
46
50
  in_root do
47
51
  inject_into_class 'app/models/user.rb', 'User', " has_secure_password\n"
48
- inject_into_file 'app/assets/stylesheets/application.css', " *= require formtastic\n", before: ' *= require_self'
49
52
  inject_into_class 'test/controllers/users_controller_test.rb', 'UsersControllerTest', <<-RUBY
50
53
 
51
54
  test "should show form" do
@@ -4,16 +4,29 @@ set -e
4
4
  set -o verbose
5
5
 
6
6
  test_app=dummy
7
-
8
7
  rm -rf ${test_app}
9
8
 
10
- bundle exec rails new ${test_app} \
9
+ export RAILS_INTEGRATION_VERSION="8.1.2"
10
+ gem install rails -v ${RAILS_INTEGRATION_VERSION}
11
+ rails -v
12
+
13
+ rails new ${test_app} \
11
14
  --template=$(dirname "$0")/integration-template.rb \
12
15
  --skip-bootsnap \
16
+ --skip-brakeman \
17
+ --skip-bundler-audit \
18
+ --skip-ci \
19
+ --skip-git \
13
20
  --skip-javascript \
21
+ --skip-jbuilder \
22
+ --skip-kamal \
23
+ --skip-rubocop \
24
+ --skip-solid \
14
25
  --skip-spring \
15
- --skip-turbolinks
26
+ --skip-thruster
16
27
 
17
- cd ${test_app} && export BUNDLE_GEMFILE=Gemfile
28
+ cd ${test_app}
18
29
 
30
+ bundle add formtastic --path=../formtastic
31
+ bundle install
19
32
  bundle exec rake test
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
  require 'formtastic/action_class_finder'
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -112,7 +111,6 @@ RSpec.describe 'Formtastic::FormBuilder#fields_for' do
112
111
  end)
113
112
  expect(output_buffer.to_str).to match(/oh noes/)
114
113
  end
115
-
116
114
  end
117
115
 
118
116
  context "when I rendered my own hidden id input" do
@@ -140,4 +138,76 @@ RSpec.describe 'Formtastic::FormBuilder#fields_for' do
140
138
  end
141
139
  end
142
140
 
141
+ context "when FormBuilder.semantic_errors_link_to_inputs is true" do
142
+ before do
143
+ Formtastic::FormBuilder.semantic_errors_link_to_inputs = true
144
+ end
145
+
146
+ after do
147
+ Formtastic::FormBuilder.semantic_errors_link_to_inputs = false
148
+ end
149
+
150
+ context "when there are errors" do
151
+ before do
152
+ @errors = double('errors')
153
+ allow(@errors).to receive(:[]).with(errors_matcher(:login)).and_return(['oh noes'])
154
+ allow(@errors).to receive(:[]).with(errors_matcher(:name)).and_return([])
155
+ allow(@bob).to receive(:errors).and_return(@errors)
156
+
157
+ concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
158
+ concat(builder.semantic_fields_for(@bob) do |nested_builder|
159
+ concat(nested_builder.inputs(:login, :name))
160
+ end)
161
+ end)
162
+ end
163
+
164
+ it 'should render errors on the nested inputs with default aria attributes' do
165
+ expect(output_buffer.to_str).to include('aria-invalid="true"')
166
+ expect(output_buffer.to_str).to \
167
+ have_tag 'input#context2_post_author_login[aria-describedby="login_error"]', \
168
+ count: 1
169
+ end
170
+
171
+ it 'should preserve developer-set aria attributes' do
172
+ concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
173
+ concat(builder.semantic_fields_for(@bob) do |nested_builder|
174
+ concat(nested_builder.input(:login, input_html: { 'aria-describedby': 'hint_for_email_field', 'aria-invalid': 'false' } ))
175
+ end)
176
+ end)
177
+
178
+ expect(output_buffer.to_str).to \
179
+ have_tag 'input#context2_post_author_login[aria-describedby="hint_for_email_field login_error"]', \
180
+ count: 1
181
+ expect(output_buffer.to_str).to \
182
+ have_tag 'input#context2_post_author_login[aria-invalid="false"]', \
183
+ count: 1
184
+ end
185
+ end
186
+
187
+ context "when there are no errors" do
188
+ before do
189
+ concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
190
+ concat(builder.semantic_fields_for(@bob) do |nested_builder|
191
+ concat(nested_builder.input(:login))
192
+ end)
193
+ end)
194
+ end
195
+
196
+ it 'should not aria attributes on nested inputs' do
197
+ expect(output_buffer.to_str).not_to include('aria-invalid')
198
+ expect(output_buffer.to_str).not_to include('aria-describedby')
199
+ end
200
+
201
+ it 'should render aria attributes I set' do
202
+ concat(semantic_form_for(@new_post, :namespace => 'context2') do |builder|
203
+ concat(builder.semantic_fields_for(@bob) do |nested_builder|
204
+ concat(nested_builder.input(:login, input_html: { 'aria-describedby': 'hint_for_email_field', 'aria-invalid': 'false' } ))
205
+ end)
206
+ end)
207
+
208
+ expect(output_buffer.to_str).to include('aria-describedby="hint_for_email_field"')
209
+ expect(output_buffer.to_str).to include('aria-invalid="false"')
210
+ end
211
+ end
212
+ end
143
213
  end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  $LOAD_PATH << 'lib/formtastic'
4
3
  require 'active_support/all'
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+ require 'spec_helper'
3
+
4
+ # Generators are not automatically loaded by Rails
5
+ require 'generators/formtastic/stylesheets/stylesheets_generator'
6
+
7
+ RSpec.describe Formtastic::StylesheetsGenerator do
8
+ # Tell the generator where to put its output (what it thinks of as Rails.root)
9
+ destination File.expand_path("../../../../../tmp", __FILE__)
10
+
11
+ before { prepare_destination }
12
+
13
+ describe 'no arguments' do
14
+ before { run_generator }
15
+
16
+ describe 'app/assets/stylesheets/formtastic.css' do
17
+ subject { file('app/assets/stylesheets/formtastic.css') }
18
+ it { is_expected.to exist }
19
+ it { is_expected.to contain ".formtastic" }
20
+ end
21
+ end
22
+ end
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -492,6 +491,7 @@ RSpec.describe 'with input class finder' do
492
491
  it 'should default to :datetime_select for :datetime and :timestamp column types' do
493
492
  expect(default_input_type(:datetime)).to eq(:datetime_select)
494
493
  expect(default_input_type(:timestamp)).to eq(:datetime_select)
494
+ expect(default_input_type(:timestamptz)).to eq(:datetime_select)
495
495
  end
496
496
 
497
497
  it 'should default to :time_select for :time column types' do
@@ -731,6 +731,17 @@ RSpec.describe 'with input class finder' do
731
731
 
732
732
  end
733
733
 
734
+ describe ':label_method option' do
735
+ it "should allow label_html to add custom attributes" do
736
+ concat(semantic_form_for(@new_post) do |builder|
737
+ concat(builder.input(:title, :label_html => { :data => { :tooltip => 'Great Tooltip' } }))
738
+ end)
739
+ aggregate_failures do
740
+ expect(output_buffer.to_str).to have_tag('form li label[data-tooltip="Great Tooltip"]')
741
+ end
742
+ end
743
+ end
744
+
734
745
  describe ':hint option' do
735
746
 
736
747
  describe 'when provided' do
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3
 
@@ -1,4 +1,3 @@
1
- # encoding: utf-8
2
1
  # frozen_string_literal: true
3
2
  require 'spec_helper'
4
3