From 62136a48e75e375a12d78c4f90cfc3f6ad13d69c Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Mon, 3 Nov 2025 20:33:18 +0100 Subject: [PATCH 1/2] Engine: Add helpers to compare compiled/rendered outputs of Erubi and Herb --- Gemfile | 2 + Gemfile.lock | 2 + bin/compare | 100 ++++++++++++++++++++++ bin/compare-compile | 89 +++++++++++++++++++ bin/compare-render | 80 +++++++++++++++++ bin/lib/compare_helpers.rb | 171 +++++++++++++++++++++++++++++++++++++ test/snapshot_utils.rb | 101 ++++++++++++++++++++-- 7 files changed, 539 insertions(+), 6 deletions(-) create mode 100755 bin/compare create mode 100755 bin/compare-compile create mode 100755 bin/compare-render create mode 100644 bin/lib/compare_helpers.rb diff --git a/Gemfile b/Gemfile index cce0da4bc..87da51e09 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ gemspec gem "prism", github: "ruby/prism", tag: "v1.6.0" gem "actionview", "~> 8.0" +gem "difftastic", "~> 0.7" +gem "erubi" gem "lz_string" gem "maxitest" gem "minitest-difftastic", "~> 0.2" diff --git a/Gemfile.lock b/Gemfile.lock index 8897f77d3..06032489a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -183,6 +183,8 @@ PLATFORMS DEPENDENCIES actionview (~> 8.0) + difftastic (~> 0.7) + erubi herb! lz_string maxitest diff --git a/bin/compare b/bin/compare new file mode 100755 index 000000000..c64477795 --- /dev/null +++ b/bin/compare @@ -0,0 +1,100 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "pathname" +require "optparse" + +require_relative "lib/compare_helpers" + +include CompareHelpers + +def usage + puts "Usage: #{$PROGRAM_NAME} [options] " + puts "" + puts "Compares an ERB template with both Herb and Erubi (compile and render)." + puts "" + puts "Options:" + puts " --no-escape Disable HTML escaping" + puts " --escape Enable HTML escaping (default: false)" + puts " -h, --help Show this help message" + exit(1) +end + +options = {} +options[:escape] = false + +OptionParser.new do |opts| + opts.banner = "Usage: #{$PROGRAM_NAME} [options] " + + opts.on("--no-escape", "Disable HTML escaping") do + options[:escape] = false + end + + opts.on("--escape", "Enable HTML escaping") do + options[:escape] = true + end + + opts.on("-h", "--help", "Show this help message") do + usage + end +end.parse! + +file_path = ARGV[0] + +unless file_path + puts "Error: No file specified" + usage +end + +unless File.exist?(file_path) + puts "Error: File '#{file_path}' not found" + exit(1) +end + +bin_dir = File.expand_path(__dir__) + +template = File.read(file_path) +show_template(file_path, template) + +args = [] +args << "--escape" if options[:escape] +args << "--no-escape" unless options[:escape] +args << "--no-template" +args << file_path + +box_header("Compiled HTML+ERB Template Output") +puts "" + +compile_result = system(File.join(bin_dir, "compare-compile"), *args) + +puts "" +box_header("Rendered HTML+ERB Template Output") +puts "" + +render_result = system(File.join(bin_dir, "compare-render"), *args) + +puts "" +box_header("Summary") + +if render_result && compile_result + puts "✓ All comparisons passed!" + puts "" + puts " • Rendered outputs match" + puts " • Compiled sources match" + exit(0) +elsif render_result + puts "⚠ Rendered outputs match, but compiled sources differ" + puts "" + puts " • ✓ Rendered outputs match (what matters!)" + puts " • ✗ Compiled sources differ (different formatting is OK)" + puts "" + puts "This is usually fine. Herb and Erubi format generated code differently," + puts "but produce the same final output." + exit(0) +else + puts "✗ Comparisons failed" + puts "" + puts " • Rendered output: #{render_result ? '✓ Match' : '✗ Differ'}" + puts " • Compiled source: #{compile_result ? '✓ Match' : '✗ Differ'}" + exit(1) +end diff --git a/bin/compare-compile b/bin/compare-compile new file mode 100755 index 000000000..062e64764 --- /dev/null +++ b/bin/compare-compile @@ -0,0 +1,89 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "pathname" +require "optparse" +require_relative "lib/compare_helpers" + +include CompareHelpers + +def usage + puts "Usage: #{$PROGRAM_NAME} [options] " + puts "" + puts "Compiles an ERB template with both Erubi::Engine and Herb::Engine and shows the diff." + puts "" + puts "Options:" + puts " --no-escape Disable HTML escaping" + puts " --escape Enable HTML escaping (default: false)" + puts " -h, --help Show this help message" + exit(1) +end + +options = {} +options[:escape] = false + +OptionParser.new do |opts| + opts.banner = "Usage: #{$PROGRAM_NAME} [options] " + parse_common_options(opts, options) { usage } +end.parse! + +options[:show_template] = true unless options.key?(:show_template) + +file_path = ARGV[0] + +unless file_path + puts "Error: No file specified" + usage +end + +unless File.exist?(file_path) + puts "Error: File '#{file_path}' not found" + exit(1) +end + +load_dependencies + +template = File.read(file_path) +show_template(file_path, template) if options[:show_template] + +begin + herb_engine = Herb::Engine.new(template, options) + herb_src = herb_engine.src +rescue StandardError => e + puts "Herb compile error: #{e.message}" + exit(1) +end + +begin + erubi_engine = Erubi::Engine.new(template, options) + erubi_src = erubi_engine.src +rescue StandardError => e + puts "Erubi compile error: #{e.message}" + exit(1) +end + +herb_normalized = herb_src.gsub("__herb", "__engine") +erubi_normalized = erubi_src.gsub("__erubi", "__engine") + +if herb_normalized == erubi_normalized + puts "✓ Compiled sources match (after normalization)!" + puts "" + puts "Herb output:" + puts herb_src + exit(0) +elsif herb_src == erubi_src + puts "✓ Compiled sources match exactly!" + puts "" + puts "Output:" + puts herb_src + exit(0) +else + puts "✗ Compiled sources differ!" + puts "" + puts "" + + diff_output = diff_compiled_sources(erubi_src, herb_src) + puts diff_output if diff_output + + exit(1) +end diff --git a/bin/compare-render b/bin/compare-render new file mode 100755 index 000000000..c5b1c546a --- /dev/null +++ b/bin/compare-render @@ -0,0 +1,80 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "pathname" +require "optparse" +require_relative "lib/compare_helpers" + +include CompareHelpers + +def usage + puts "Usage: #{$PROGRAM_NAME} [options] " + puts "" + puts "Renders an ERB template with both Erubi::Engine and Herb::Engine and shows the diff." + puts "" + puts "Options:" + puts " --no-escape Disable HTML escaping" + puts " --escape Enable HTML escaping (default: false)" + puts " -h, --help Show this help message" + exit(1) +end + +options = {} +options[:escape] = false + +OptionParser.new do |opts| + opts.banner = "Usage: #{$PROGRAM_NAME} [options] " + parse_common_options(opts, options) { usage } +end.parse! + +options[:show_template] = true unless options.key?(:show_template) + +file_path = ARGV[0] + +unless file_path + puts "Error: No file specified" + usage +end + +unless File.exist?(file_path) + puts "Error: File '#{file_path}' not found" + exit(1) +end + +load_dependencies + +template = File.read(file_path) +show_template(file_path, template) if options[:show_template] + +begin + herb_engine = Herb::Engine.new(template, options) + herb_output = eval(herb_engine.src) +rescue StandardError => e + puts "Herb render error: #{e.message}" + exit(1) +end + +begin + erubi_engine = Erubi::Engine.new(template, options) + erubi_output = eval(erubi_engine.src) +rescue StandardError => e + puts "Erubi render error: #{e.message}" + exit(1) +end + +if herb_output == erubi_output + puts "✓ Outputs match!" + puts "" + puts "Output:" + puts herb_output + exit(0) +else + puts "✗ Outputs differ!" + puts "" + puts "" + + diff_output = diff_rendered_outputs(erubi_output, herb_output) + puts diff_output if diff_output + + exit(1) +end diff --git a/bin/lib/compare_helpers.rb b/bin/lib/compare_helpers.rb new file mode 100644 index 000000000..249785add --- /dev/null +++ b/bin/lib/compare_helpers.rb @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +module CompareHelpers + def box_header(title, width = 80) + padding = width - title.length - 2 + left_pad = padding / 2 + right_pad = padding - left_pad + + puts "╔#{'═' * (width - 2)}╗" + puts "║#{' ' * left_pad}#{title}#{' ' * right_pad}║" + puts "╚#{'═' * (width - 2)}╝" + end + + def box_with_content(title, content, width = 80) + padding = width - title.length - 2 + left_pad = padding / 2 + right_pad = padding - left_pad + + puts "╔#{'═' * (width - 2)}╗" + puts "║#{' ' * left_pad}#{title}#{' ' * right_pad}║" + puts "╠#{'═' * (width - 2)}╣" + puts content + puts "╚#{'═' * (width - 2)}╝" + end + + def section_header(title, width = 80) + puts "" + puts "" + puts "#{title}:" + puts "─" * width + end + + def show_template(file_path, template, width = 80) + puts "Template: #{file_path}" + puts "─" * width + puts template + puts "─" * width + puts "" + end + + def load_dependencies + $LOAD_PATH.unshift File.expand_path("../../lib", __dir__) + require "herb" + + begin + original_verbose = $VERBOSE + $VERBOSE = nil + require "erubi" + rescue LoadError + puts "Error: Erubi gem is not available." + puts "Install with: gem install erubi" + exit(1) + ensure + $VERBOSE = original_verbose + end + + begin + require "difftastic" + rescue LoadError + puts "Error: Difftastic gem is not available." + puts "Install with: gem install difftastic" + exit(1) + end + end + + def parse_common_options(opts, options) + opts.on("--no-escape", "Disable HTML escaping") do + options[:escape] = false + end + + opts.on("--escape", "Enable HTML escaping") do + options[:escape] = true + end + + opts.on("--no-template", "Don't show the input template") do + options[:show_template] = false + end + + opts.on("-h", "--help", "Show this help message") do + yield if block_given? + end + end + + def require_erubi_silently + original_verbose = $VERBOSE + $VERBOSE = nil + require "erubi" + ensure + $VERBOSE = original_verbose + end + + def diff_compiled_sources(erubi_src, herb_src) + return nil if erubi_src == herb_src + + output = "" + output += "String Comparison (including formatting differences):\n" + output += "─" * 80 + "\n" + + string_diff = Difftastic::Differ.new( + color: :always, + left_label: "Erubi::Engine compiled", + right_label: "Herb::Engine compiled" + ).diff_strings(erubi_src, herb_src) + + output += string_diff + + if !string_diff.strip.empty? && !string_diff.include?("No changes.") + output += "\n\n" + output += "Ruby AST Comparison (semantic differences only):\n" + output += "─" * 80 + "\n" + + begin + ast_diff = Difftastic::Differ.new( + color: :always, + left_label: "Erubi::Engine compiled", + right_label: "Herb::Engine compiled" + ).diff_ruby(erubi_src, herb_src) + + if ast_diff.strip.empty? || ast_diff.include?("No changes.") + output += "✓ ASTs are identical (only formatting differs)" + else + output += ast_diff + end + rescue StandardError => e + output += "Could not parse as Ruby: #{e.message}" + end + end + + output + end + + def diff_rendered_outputs(erubi_output, herb_output) + return nil if erubi_output == herb_output + + output = "" + output += "String Comparison:\n" + output += "─" * 80 + "\n" + + string_diff = Difftastic::Differ.new( + color: :always, + left_label: "Erubi::Engine output", + right_label: "Herb::Engine output" + ).diff_strings(erubi_output, herb_output) + + output += string_diff + + if !string_diff.strip.empty? && !string_diff.include?("No changes.") + output += "\n\n" + output += "HTML Semantic Comparison:\n" + output += "─" * 80 + "\n" + + begin + html_diff = Difftastic::Differ.new( + color: :always, + left_label: "Erubi::Engine output", + right_label: "Herb::Engine output" + ).diff_html(erubi_output, herb_output) + + if html_diff.strip.empty? || html_diff.include?("No changes.") + output += "✓ HTML semantics are identical (only formatting/whitespace differs)" + else + output += html_diff + end + rescue StandardError => e + output += "Could not parse as HTML: #{e.message}" + end + end + + output + end +end diff --git a/test/snapshot_utils.rb b/test/snapshot_utils.rb index a6cb545fe..3551273d3 100644 --- a/test/snapshot_utils.rb +++ b/test/snapshot_utils.rb @@ -3,12 +3,15 @@ require "fileutils" require "readline" require "digest" +require_relative "../bin/lib/compare_helpers" def ask?(prompt = "") Readline.readline("===> #{prompt}? (y/N) ", true).squeeze(" ").strip == "y" end module SnapshotUtils + include CompareHelpers + def assert_lexed_snapshot(source) result = Herb.lex(source) expected = result.value.inspect @@ -31,22 +34,32 @@ def assert_parsed_snapshot(source, **options) result end - def assert_compiled_snapshot(source, options = {}) + def assert_compiled_snapshot(source, options = {}, **kwargs) require_relative "../lib/herb/engine" - engine = Herb::Engine.new(source, options) + enforce_erubi_equality = kwargs.delete(:enforce_erubi_equality) || false + engine_options = options.merge(kwargs) + + engine = Herb::Engine.new(source, engine_options) expected = engine.src - snapshot_key = { source: source, options: options }.to_s + snapshot_key = { source: source, options: engine_options }.to_s assert_snapshot_matches(expected, snapshot_key) + if should_compare_with_erubi? || enforce_erubi_equality + compare_with_erubi_compiled(source, engine.src, engine_options, enforce_erubi_equality) + end + engine end - def assert_evaluated_snapshot(source, locals = {}, options = {}) + def assert_evaluated_snapshot(source, locals = {}, options = {}, **kwargs) require_relative "../lib/herb/engine" - engine = Herb::Engine.new(source, options) + enforce_erubi_equality = kwargs.delete(:enforce_erubi_equality) || false + engine_options = options.merge(kwargs) + + engine = Herb::Engine.new(source, engine_options) binding_context = Object.new locals.each do |key, value| @@ -58,11 +71,15 @@ def assert_evaluated_snapshot(source, locals = {}, options = {}) snapshot_key = { source: source, locals: locals, - options: options, + options: engine_options, }.to_s assert_snapshot_matches(result, snapshot_key) + if should_compare_with_erubi? || enforce_erubi_equality + compare_with_erubi_evaluated(source, result, locals, engine_options, enforce_erubi_equality) + end + { engine: engine, result: result } end @@ -176,6 +193,78 @@ def snapshot_file(source, options = {}) expected_snapshot_path end + def should_compare_with_erubi? + return false if class_name.include?("DebugMode") + !ENV["COMPARE_WITH_ERUBI"].nil? + end + + def compare_with_erubi_compiled(source, herb_src, options, enforce_equality = false) + require_erubi_silently + + begin + erubi_engine = Erubi::Engine.new(source, options) + erubi_src = erubi_engine.src + + diff_output = diff_compiled_sources(erubi_src, herb_src) + return unless diff_output + + message = "\n" + "=" * 80 + "\n" + message += "WARNING: Herb compiled output differs from Erubi\n" + message += "=" * 80 + "\n" + message += "Test: #{class_name} #{name}\n" + message += "\nTemplate:\n#{source.inspect}\n" + message += "\n" + message += diff_output + message += "\n" + message += "=" * 80 + "\n" + + if ENV["FAIL_ON_ERUBI_MISMATCH"] || enforce_equality + flunk(message) + else + puts message + end + rescue StandardError + return + end + end + + def compare_with_erubi_evaluated(source, herb_result, locals, options, enforce_equality = false) + require_erubi_silently + + begin + erubi_engine = Erubi::Engine.new(source, options) + binding_context = Object.new + + locals.each do |key, value| + binding_context.define_singleton_method(key) { value } + end + + erubi_result = binding_context.instance_eval(erubi_engine.src) + + diff_output = diff_rendered_outputs(erubi_result, herb_result) + return unless diff_output + + message = "\n" + "=" * 80 + "\n" + message += "WARNING: Herb evaluated output differs from Erubi\n" + message += "=" * 80 + "\n" + message += "Test: #{class_name} #{name}\n" + message += "\nTemplate:\n#{source.inspect}\n" + message += "\nLocals: #{locals.inspect}\n" + message += "\n" + message += diff_output + message += "\n" + message += "=" * 80 + "\n" + + if ENV["FAIL_ON_ERUBI_MISMATCH"] || enforce_equality + flunk(message) + else + puts message + end + rescue StandardError + return + end + end + private def sanitize_name_for_filesystem(name) From 5ebb3edc1e0a8142ffd345b698419a0fe650be8a Mon Sep 17 00:00:00 2001 From: Marco Roth Date: Mon, 3 Nov 2025 21:29:04 +0100 Subject: [PATCH 2/2] RuboCop --- .rubocop.yml | 9 ++++++++ bin/compare | 4 ++-- bin/lib/compare_helpers.rb | 42 +++++++++++++++++++------------------- test/snapshot_utils.rb | 21 ++++++++++--------- 4 files changed, 43 insertions(+), 33 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index 793a7639e..b20494689 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -12,6 +12,12 @@ Style/StringLiterals: Enabled: true EnforcedStyle: double_quotes +Style/MixinUsage: + Exclude: + - bin/compare + - bin/compare-render + - bin/compare-compile + Style/ClassAndModuleChildren: Enabled: false @@ -94,6 +100,7 @@ Metrics/ModuleLength: Exclude: - test/**/*.rb - templates/**/*.rb + - bin/lib/compare_helpers.rb Metrics/BlockLength: Max: 30 @@ -160,6 +167,8 @@ Security/Eval: - lib/herb/cli.rb - test/**/*.rb - bin/erubi-render + - bin/compare-render + - bin/compare-render Security/MarshalLoad: Exclude: diff --git a/bin/compare b/bin/compare index c64477795..f32cd97ed 100755 --- a/bin/compare +++ b/bin/compare @@ -94,7 +94,7 @@ elsif render_result else puts "✗ Comparisons failed" puts "" - puts " • Rendered output: #{render_result ? '✓ Match' : '✗ Differ'}" - puts " • Compiled source: #{compile_result ? '✓ Match' : '✗ Differ'}" + puts " • Rendered output: #{render_result ? "✓ Match" : "✗ Differ"}" + puts " • Compiled source: #{compile_result ? "✓ Match" : "✗ Differ"}" exit(1) end diff --git a/bin/lib/compare_helpers.rb b/bin/lib/compare_helpers.rb index 249785add..47bcacfec 100644 --- a/bin/lib/compare_helpers.rb +++ b/bin/lib/compare_helpers.rb @@ -6,9 +6,9 @@ def box_header(title, width = 80) left_pad = padding / 2 right_pad = padding - left_pad - puts "╔#{'═' * (width - 2)}╗" - puts "║#{' ' * left_pad}#{title}#{' ' * right_pad}║" - puts "╚#{'═' * (width - 2)}╝" + puts "╔#{"═" * (width - 2)}╗" + puts "║#{" " * left_pad}#{title}#{" " * right_pad}║" + puts "╚#{"═" * (width - 2)}╝" end def box_with_content(title, content, width = 80) @@ -16,11 +16,11 @@ def box_with_content(title, content, width = 80) left_pad = padding / 2 right_pad = padding - left_pad - puts "╔#{'═' * (width - 2)}╗" - puts "║#{' ' * left_pad}#{title}#{' ' * right_pad}║" - puts "╠#{'═' * (width - 2)}╣" + puts "╔#{"═" * (width - 2)}╗" + puts "║#{" " * left_pad}#{title}#{" " * right_pad}║" + puts "╠#{"═" * (width - 2)}╣" puts content - puts "╚#{'═' * (width - 2)}╝" + puts "╚#{"═" * (width - 2)}╝" end def section_header(title, width = 80) @@ -94,7 +94,7 @@ def diff_compiled_sources(erubi_src, herb_src) output = "" output += "String Comparison (including formatting differences):\n" - output += "─" * 80 + "\n" + output += "#{"─" * 80}\n" string_diff = Difftastic::Differ.new( color: :always, @@ -107,7 +107,7 @@ def diff_compiled_sources(erubi_src, herb_src) if !string_diff.strip.empty? && !string_diff.include?("No changes.") output += "\n\n" output += "Ruby AST Comparison (semantic differences only):\n" - output += "─" * 80 + "\n" + output += "#{"─" * 80}\n" begin ast_diff = Difftastic::Differ.new( @@ -116,11 +116,11 @@ def diff_compiled_sources(erubi_src, herb_src) right_label: "Herb::Engine compiled" ).diff_ruby(erubi_src, herb_src) - if ast_diff.strip.empty? || ast_diff.include?("No changes.") - output += "✓ ASTs are identical (only formatting differs)" - else - output += ast_diff - end + output += if ast_diff.strip.empty? || ast_diff.include?("No changes.") + "✓ ASTs are identical (only formatting differs)" + else + ast_diff + end rescue StandardError => e output += "Could not parse as Ruby: #{e.message}" end @@ -134,7 +134,7 @@ def diff_rendered_outputs(erubi_output, herb_output) output = "" output += "String Comparison:\n" - output += "─" * 80 + "\n" + output += "#{"─" * 80}\n" string_diff = Difftastic::Differ.new( color: :always, @@ -147,7 +147,7 @@ def diff_rendered_outputs(erubi_output, herb_output) if !string_diff.strip.empty? && !string_diff.include?("No changes.") output += "\n\n" output += "HTML Semantic Comparison:\n" - output += "─" * 80 + "\n" + output += "#{"─" * 80}\n" begin html_diff = Difftastic::Differ.new( @@ -156,11 +156,11 @@ def diff_rendered_outputs(erubi_output, herb_output) right_label: "Herb::Engine output" ).diff_html(erubi_output, herb_output) - if html_diff.strip.empty? || html_diff.include?("No changes.") - output += "✓ HTML semantics are identical (only formatting/whitespace differs)" - else - output += html_diff - end + output += if html_diff.strip.empty? || html_diff.include?("No changes.") + "✓ HTML semantics are identical (only formatting/whitespace differs)" + else + html_diff + end rescue StandardError => e output += "Could not parse as HTML: #{e.message}" end diff --git a/test/snapshot_utils.rb b/test/snapshot_utils.rb index 3551273d3..562df24ec 100644 --- a/test/snapshot_utils.rb +++ b/test/snapshot_utils.rb @@ -195,10 +195,11 @@ def snapshot_file(source, options = {}) def should_compare_with_erubi? return false if class_name.include?("DebugMode") + !ENV["COMPARE_WITH_ERUBI"].nil? end - def compare_with_erubi_compiled(source, herb_src, options, enforce_equality = false) + def compare_with_erubi_compiled(source, herb_src, options, enforce_equality: false) require_erubi_silently begin @@ -208,15 +209,15 @@ def compare_with_erubi_compiled(source, herb_src, options, enforce_equality = fa diff_output = diff_compiled_sources(erubi_src, herb_src) return unless diff_output - message = "\n" + "=" * 80 + "\n" + message = "\n#{"=" * 80}\n" message += "WARNING: Herb compiled output differs from Erubi\n" - message += "=" * 80 + "\n" + message += "#{"=" * 80}\n" message += "Test: #{class_name} #{name}\n" message += "\nTemplate:\n#{source.inspect}\n" message += "\n" message += diff_output message += "\n" - message += "=" * 80 + "\n" + message += "#{"=" * 80}\n" if ENV["FAIL_ON_ERUBI_MISMATCH"] || enforce_equality flunk(message) @@ -224,11 +225,11 @@ def compare_with_erubi_compiled(source, herb_src, options, enforce_equality = fa puts message end rescue StandardError - return + nil end end - def compare_with_erubi_evaluated(source, herb_result, locals, options, enforce_equality = false) + def compare_with_erubi_evaluated(source, herb_result, locals, options, enforce_equality: false) require_erubi_silently begin @@ -244,16 +245,16 @@ def compare_with_erubi_evaluated(source, herb_result, locals, options, enforce_e diff_output = diff_rendered_outputs(erubi_result, herb_result) return unless diff_output - message = "\n" + "=" * 80 + "\n" + message = "\n#{"=" * 80}\n" message += "WARNING: Herb evaluated output differs from Erubi\n" - message += "=" * 80 + "\n" + message += "#{"=" * 80}\n" message += "Test: #{class_name} #{name}\n" message += "\nTemplate:\n#{source.inspect}\n" message += "\nLocals: #{locals.inspect}\n" message += "\n" message += diff_output message += "\n" - message += "=" * 80 + "\n" + message += "#{"=" * 80}\n" if ENV["FAIL_ON_ERUBI_MISMATCH"] || enforce_equality flunk(message) @@ -261,7 +262,7 @@ def compare_with_erubi_evaluated(source, herb_result, locals, options, enforce_e puts message end rescue StandardError - return + nil end end