diff --git a/lib/gherkin/formatter/html_formatter.rb b/lib/gherkin/formatter/html_formatter.rb new file mode 100644 index 00000000..8c529480 --- /dev/null +++ b/lib/gherkin/formatter/html_formatter.rb @@ -0,0 +1,182 @@ +# encoding: utf-8 +require 'gherkin/formatter/argument' +require 'gherkin/formatter/escaping' +require 'gherkin/formatter/model' +require 'gherkin/native' + +module Gherkin + module Formatter + class HtmlFormatter + native_impl('gherkin') + + include Escaping + + def initialize(io, executing) + @io = io + @executing = executing + @background = nil + @tag_statement = nil + @steps = [] + @io.puts "
" + end + + def uri(uri) + @uri = uri + end + + def feature(feature) + print_comments(feature.comments) + print_tags(feature.tags) + @io.puts "

#{feature.keyword}: #{feature.name}

" + print_description(feature.description, false) + end + + def background(background) + replay + @statement = background + end + + def scenario(scenario) + replay + @io.puts "
" + print_tags(scenario.tags) + @io.puts "

" + scenario.keyword + ": " + escape_brackets(scenario.name) + "

" + end + + def scenario_outline(scenario_outline) + scenario scenario_outline + end + + def replay + print_statement + print_steps + end + + def print_statement + return if @statement.nil? + @io.puts + print_comments(@statement.comments) + print_tags(@statement.tags) if @statement.respond_to?(:tags) # Background doesn't + @io.write " #{@statement.keyword}: #{@statement.name}" + location = @executing ? "#{@uri}:#{@statement.line}" : nil + @io.write location + print_description(@statement.description) + @statement = nil + end + + def print_steps + while(@steps.any?) + print_step('b', [], nil, true) + end + end + + def examples(examples) + replay + @io.puts + print_comments(examples.comments) + print_tags(examples.tags) + @io.write "#{examples.keyword}: #{examples.name}" + print_description(examples.description) + table(examples.rows, true) + end + + def step(step) + @steps << step + end + + def match(match) + @match = match + print_statement + print_step('executing', @match.arguments, @match.location, false) + end + + def result(result) + @io.write(up(1)) + print_step(result.status, @match.arguments, @match.location, true) + end + + def print_step(status, arguments, location, proceed) + step = proceed ? @steps.shift : @steps[0] + + print_comments(step.comments) + @io.write("<" + status + ">" + step.keyword + "") + @io.write(escape_brackets(step.name)) + @io.write(escape_brackets(location)) + @io.puts("
") + + doc_string(step.doc_string) if step.doc_string + table(step.rows) if step.rows + end + + def eof + replay + # NO-OP + end + + def done + @io.puts("
") + end + + def table(rows, header=false) + @io.puts("") + + rows.each_with_index do |row, i| + @io.puts("") + row.cells.each do |cell| + bal = header && i == 0 ? "th" : "td" + @io.puts(" <" + bal + ">" + cell + "") + end + @io.puts("") + end + + @io.puts("
") + end + + private + def escape_brackets(s) + return if s.nil? + s.gsub("<", "<").gsub(">", ">") + end + + def doc_string(doc_string) + @io.puts doc_string.content_type + "
\n" + escape_triple_quotes(doc_string.value) + "
\n" + end + + def exception(exception) + exception_text = "#{exception.message} (#{exception.class})\n#{(exception.backtrace || []).join("\n")}".gsub(/^/, ' ') + @io.puts(failed(exception_text)) + end + + if(RUBY_VERSION =~ /^1\.9|2\.0/) + START = /#{'^'.encode('UTF-8')}/ + TRIPLE_QUOTES = /#{'"""'.encode('UTF-8')}/ + else + START = /^/ + TRIPLE_QUOTES = /"""/ + end + + def escape_triple_quotes(s) + s.gsub(TRIPLE_QUOTES, '\"\"\"') + end + + def print_tags(tags) + # @MonTag + @io.write(tags.empty? ? '' : tags.map{|tag| "" + tag.name + "" }.join(' ') + "\n") + end + + def print_comments(comments) + @io.puts(comments.empty? ? '' : "

" + comments.map{|comment| "" + comment.value.gsub( /#/m, "" ) + ""}.join("
\n") + "

\n") + end + + def print_description(description, newline=true) + if description != "" + description = description.gsub( //m, ">" ) + description = description.gsub( /\n/m, "
\n\r" ) + @io.puts "

" + description + "

" + @io.puts if newline + end + end + end + end +end