Created
May 27, 2024 13:42
-
-
Save masasakano/6cdfb389e8ac3e13735d2b3a306de114 to your computer and use it in GitHub Desktop.
Ruby-on-Rails helper to use a local VNU server to validate HTML with W3C validator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
require 'w3c_validators' | |
# Module to deal with W3C Validator | |
# | |
# == Usage | |
# | |
# Put this file in one of your library-load paths in the test environment. | |
# Then, in /test/test_helper.rb | |
# | |
# class ActiveSupport::TestCase | |
# include TestW3cValidateHelper | |
# | |
# You may need to write in your +test_helper.rb+ | |
# | |
# require_relative './test_w3c_validate_helper' | |
# | |
# == Preparation | |
# | |
# Make sure your Gemfile contains: | |
# | |
# group :test do | |
# gem 'w3c_validators' | |
# end | |
# | |
# To use these methods with your local VNU server (Default), | |
# you must install vnu first. | |
# See https://stackoverflow.com/a/3586244/3577922 | |
# or for macOS Homebrew, +brew install vnu+ | |
# | |
# Then, start up a local VNU server in a separate terminal with (in the case of Homebrew): | |
# | |
# java -Dnu.validator.servlet.bind-address=127.0.0.1 -cp $HOMEBREW_CELLAR/vnu/`vnu --version`/libexec/vnu.jar \ | |
# nu.validator.servlet.Main 8888 | |
# | |
# NOTE1: If +$HOMEBREW_CELLAR+ is not defined, your machine is probably Intel and it is /usr/local/Cellar | |
# NOTE2: The vnu default server may be http://0.0.0.0:8888/ but vnu warns it will be changed to http://127.0.0.1:8888/ | |
# NOTE3: If the server address is different from the default, you simply give is to the methods in thi module, | |
# making sure you include the forward slash '/' at the tail. | |
module TestW3cValidateHelper | |
extend ActiveSupport::Concern | |
# Default parameters for the methods in this module. | |
# | |
# @note For +validator_uri+, the trailing "/" is indispensable. | |
DEF_W3C_VALIDATOR_PARAMS = { | |
use_local: true, | |
validator_uri: "http://127.0.0.1:8888/", | |
}.with_indifferent_access | |
#module ClassMethods | |
#end | |
# Validates HTML with W3C (vnu) validator | |
# | |
# If environmental variable SKIP_W3C_VALIDATE is set and not '0' or 'false', | |
# validation is skipped. | |
# | |
# The caller information is printed if fails. | |
# | |
# If the error message is insufficient, you may simply print out 'response.body', | |
# before the calling statement in the caller, or better | |
# | |
# @validator.validate_text(response.body).debug_messages.each do |key, value| | |
# puts "#{key}: #{value}" | |
# end | |
# | |
# (Note that +css_select('table').to_html+ in Controller tests etc may not work well | |
# for HTML-debugging purposes because it would filter out invalid HTMLs like stray end tags.) | |
# | |
# @example to call this for the output of the index method of ArticlesController | |
# w3c_validate "Article index" | |
# | |
# @option name [String] Identifier for the error message. | |
# @param use_local: #see setup_w3c_validator! | |
# @param validator_uri: #see setup_w3c_validator! | |
def w3c_validate(name="caller", use_local: nil, validator_uri: DEF_W3C_VALIDATOR_PARAMS[:validator_uri]) | |
return if is_env_set_positive?('SKIP_W3C_VALIDATE') | |
bind = caller_locations(1,1)[0] # Ruby 2.0+ | |
caller_info = sprintf "%s:%d", bind.absolute_path.sub(%r@.*(/test/)@, '\1'), bind.lineno | |
# NOTE: bind.label returns "block in <class:TranslationIntegrationTest>" | |
## W3C HTML validation (Costly operation) | |
setup_w3c_validator!(use_local: use_local, validator_uri: validator_uri) if !instance_variable_defined?(:@validator) | |
arerr = @validator.validate_text(response.body).errors | |
arerr = _may_ignore_autocomplete_errors_for_hidden(arerr, "Ignores W3C validation errors for #{name} (#{caller_info}): ") | |
assert_empty arerr, "Failed for #{name} (#{caller_info}): W3C-HTML-validation-Errors(Size=#{arerr.size}): ("+arerr.map(&:to_s).join(") (")+")" | |
end | |
# Sets up the instance variable +@validator+ for preparation for running {#w3c_validate} | |
# | |
# Note that +validator_uri+ is ignored unless +use_local+ is true (Def: false). | |
# | |
# See [TestW3cValidateHelper::DEF_W3C_VALIDATOR_PARAMS] and also the comment for this modeule | |
# for the default +validator_uri+ | |
# | |
# If the optional argument +use_local+ is nil, the environmental variable +USE_W3C_SERVER_VALIDATOR+ | |
# is read; then, if it is not set or set "0" or "false", +use_local+ is set true, | |
# and this method (attempts to) use the local VNU server. Make sure your local VNU server is | |
# up and running (the comment for this modeule for detail); otherwise, | |
# +W3CValidators::ValidatorUnavailable+ exception is raised, perhams many times. | |
# | |
# @param use_local: [Boolean, NilClass] If true (Def), use the local server. Otherwise, use the W3C server (use it sensibly!) | |
# @param validator_uri: [String, NilClass] read only when use_local is true (Def). | |
def setup_w3c_validator!(use_local: nil, validator_uri: DEF_W3C_VALIDATOR_PARAMS[:validator_uri]) | |
use_local = !is_env_set_positive?('USE_W3C_SERVER_VALIDATOR') if use_local.nil? | |
hsin = {} | |
hsin[:validator_uri] = validator_uri if use_local | |
@validator = W3CValidators::NuValidator.new(**hsin) | |
end | |
if !method_defined?(:is_env_set_positive?) | |
# true if the environmental variable is set and non-false | |
def is_env_set_positive?(key) | |
ENV.keys.include?(key.to_s) && !(%w(0 false FALSE f F)<<"").include?(ENV[key]) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment