Skip to content

Instantly share code, notes, and snippets.

@masasakano
Last active November 2, 2022 22:56
Show Gist options
  • Save masasakano/57d40a1a8a630a9ca78ac22fae375161 to your computer and use it in GitHub Desktop.
Save masasakano/57d40a1a8a630a9ca78ac22fae375161 to your computer and use it in GitHub Desktop.
Rails (test-)helper to circumvent W3C validation errors for button_to
# coding: utf-8
ENV['RAILS_ENV'] ||= 'test'
require_relative '../config/environment'
require 'rails/test_help'
require 'w3c_validators' # Key module. Write in Gemfile: gem 'w3c_validators'
# meant to be included in /test/test_helper.rb
class ActiveSupport::TestCase
# Botch fix of W3C validation errors for HTMLs generated by button_to
#
# On 2022-10-26, W3C validation implemented a check, which may raise an error:
#
# > An input element with a type attribute whose value is hidden must not have an autocomplete attribute whose value is on or off.
#
# This is particularly the case for HTMLs generated by button_to as of Rails 7.0.4.
# It seems the implementation in Rails was deliberate to deal with mal-behaviours of
# Firefox (Github Issue-42610: https://github.com/rails/rails/issues/42610 ).
#
# Whatever the reason is, it is highly inconvenient for developers who
# use W3C validation for their Rails apps.
#
# This routine takes a W3C-validation error object (Array) and
# return the same Array where the specific errors are deleted
# so that one could still test the other potential errors with the W3C validation.
# The said errors are recorded with +logger.warn+ (if +prefix+ is given).
#
# Note that this routine does nothing *unless* the config parameter
# config.ignore_w3c_validate_hidden_autocomplete = true
# is set in config, e.g., in the file (if for testing use only):
# /config/environments/test.rb
#
# == References
#
# * Stackoverflow: https://stackoverflow.com/questions/74256523/rails-button-to-fails-with-w3c-validator
# * Github: https://github.com/validator/validator/pull/1458
# * HTML Spec: https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofilling-form-controls:-the-autocomplete-attribute:autofill-anchor-mantle-2
#
# @example Usage, maybe in /test/test_helper.rb
# # Make sure to write in /config/environments/test.rb
# # config.ignore_w3c_validate_hidden_autocomplete = true
# #
# #require 'w3c_validators'
# bind = caller_locations(1,1)[0] # Ruby 2.0+
# caller_info = sprintf "%s:%d", bind.absolute_path.sub(%r@.*(/test/)@, '\1'), bind.lineno
# errors = @validator.validate_text(response.body).errors
# prefix = "Ignores W3C validation errors (#{caller_info}): "
# errors = _may_ignore_autocomplete_errors_for_hidden(errors, prefix)
# assert_empty errors, "Failed in W3C validation: "+errors.map(&:to_s).inspect
#
# @param errs [Array<W3CValidators::Message>] Output of [email protected]_text(response.body).errors+
# @param prefix [String] Prefix of the warning message recorded with Logger.
# If empty, no message is recorded in Logger.
# @return [Array<String, W3CValidators::Message>]
def _may_ignore_autocomplete_errors_for_hidden(errs, prefix="")
removeds = []
return errs if !Rails.configuration.ignore_w3c_validate_hidden_autocomplete
errs.map{ |es|
# Example of an Error:
# ERROR; line 165: An “input” element with a “type” attribute whose value is “hidden” must not have an “autocomplete” attribute whose value is “on” or “off”
if /\AERROR\b.+\binput\b[^a-z]+\belement.+\btype\b.+\bhidden\b.+\bautocomplete\b[^a-z]+\battribute\b/i =~ es.to_s
removeds << es
nil
else
es
end
}.compact
ensure
# Records it in Logger
if !removeds.empty? && !prefix.blank?
Rails.logger.warn(prefix + removeds.map(&:to_s).uniq.inspect)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment