require 'cgi' require 'base64' module Spectre::Reporter class HTML def initialize config @config = config @date_format = '%FT%T.%L' end def get_error_info error non_spectre_files = error.backtrace.select { |x| !x.include? 'lib/spectre' } if non_spectre_files.count > 0 causing_file = non_spectre_files.first else causing_file = error.backtrace[0] end matches = causing_file.match(/(.*\.rb):(\d+)/) return [nil, nil] unless matches file, line = matches.captures file.slice!(Dir.pwd + '/') return [file, line] end def read_resource filename file_path = File.join(__dir__, '../../../resources/', filename) File.open(file_path, 'rb') do |file| return file.read end end def report run_infos now = Time.now failures = run_infos.select { |x| x.failure != nil } errors = run_infos.select { |x| x.error != nil } skipped = run_infos.select { |x| x.skipped? } succeeded_count = run_infos.count - failures.count - errors.count - skipped.count if failures.count > 0 overall_status = 'failed' elsif errors.count > 0 overall_status = 'error' elsif skipped.count > 0 overall_status = 'skipped' else overall_status = 'success' end json_report = { command: $COMMAND, project: @config['project'], date: now.strftime(@date_format), environment: @config['environment'], hostname: Socket.gethostname, duration: run_infos.sum { |x| x.duration }, failures: failures.count, errors: errors.count, skipped: skipped.count, succeeded: succeeded_count, total: run_infos.count, overall_status: overall_status, tags: run_infos .map { |x| x.spec.tags } .flatten .uniq .sort, run_infos: run_infos.map do |run_info| failure = nil error = nil if run_info.failed? and not run_info.failure.cause failure_message = "Expected #{run_info.failure.expectation}" failure_message += " with #{run_info.data}" if run_info.data failure_message += " but it failed" failure_message += " with message: #{run_info.failure.message}" if run_info.failure.message failure = { message: failure_message, expected: run_info.failure.expected, actual: run_info.failure.actual, } end if run_info.error or (run_info.failed? and run_info.failure.cause) error = run_info.error || run_info.failure.cause file, line = get_error_info(error) error = { type: error.class.name, message: error.message, file: file, line: line, stack_trace: error.backtrace, } end { status: run_info.status, subject: run_info.spec.subject.desc, context: run_info.spec.context.__desc, tags: run_info.spec.tags, name: run_info.spec.name, desc: run_info.spec.desc, file: run_info.spec.file, started: run_info.started.strftime(@date_format), finished: run_info.finished.strftime(@date_format), duration: run_info.duration, properties: run_info.properties, data: run_info.data, failure: failure, error: error, # the
{{ spectreReport.overall_status }}
#{icon} {{ spectreReport.project }} {{ spectreReport.environment }} {{ new Date(spectreReport.date).toLocaleString() }} {{ spectreReport.duration.toDurationString() }} {{ spectreReport.hostname }}
{{ spectreCommand }}
  • {{ tag }}
  • {{ spectreReport.succeeded }} succeeded
  • {{ spectreReport.skipped }} skipped
  • {{ spectreReport.failures }} failures
  • {{ spectreReport.errors }} errors
  • {{ spectreReport.total }} total
  • {{ subject }}
    • {{ context }}
      • {{ runInfo.name }} {{ runInfo.data }} {{ subject }} {{ runInfo.desc }}
        Run Info
        Status{{ runInfo.status }}
        Name{{ runInfo.name }}
        Description{{ runInfo.desc }}
        Tags
        • {{ tag }}
        File{{ runInfo.file }}
        Started{{ runInfo.started }}
        Finished{{ runInfo.finished }}
        Duration{{ runInfo.duration.toDurationString() }}
        Data
        {{ runInfo.data }}
        Properties
        {{ key }}{{ item }}
        Failure
        Message{{ runInfo.failure.message }}
        Expected{{ runInfo.failure.expected }}
        Actual{{ runInfo.failure.actual }}
        Error
        File{{ runInfo.error.file }}
        Line{{ runInfo.error.line }}
        Type{{ runInfo.error.type }}
        Message{{ runInfo.error.message }}
        • {{ stackTraceEntry }}
        Log
        • {{ logEntry[0] }} {{ logEntry[2] }} -- {{ logEntry[3] }}: {{ logEntry[1] }}
#{ CGI::escapeHTML(YAML.dump json_report[:config]) }
HTML Dir.mkdir @config['out_path'] unless Dir.exist? @config['out_path'] file_path = File.join(@config['out_path'], "spectre-html_#{now.strftime('%s')}.html") File.write(file_path, html_str) end end end