class InspecRspecJson

def add_profile(profile)

Called by the runner during example collection.
def add_profile(profile)
  @profiles.push(profile)
end

def dump_one_example(example, control)

def dump_one_example(example, control)
  control[:results] ||= []
  example.delete(:id)
  example.delete(:profile_id)
  control[:results].push(example)
end

def dump_summary(summary)

def dump_summary(summary)
  super(summary)
  total = 0
  failed = 0
  skipped = 0
  passed = 0
  @profiles_info.each do |_name, profile|
    total += profile[:controls].length
    profile[:controls].each do |_control_name, control|
      next unless control[:results]
      if control[:results].any? { |r| r[:status] == 'failed' }
        failed += 1
      elsif control[:results].any? { |r| r[:status] == 'skipped' }
        skipped += 1
      else
        passed += 1
      end
    end
  end
  # TODO: provide this information in the output
end

def example2control(example, profiles)

def example2control(example, profiles)
  p = example2profile(example, profiles)
  p[:controls][example[:id]] if p && p[:controls]
end

def example2profile(example, profiles)


this heuristic matching.
by registrying all dependent profiles with the formatter. The we could remove
the profile_id of the top level profile when it is included as a dependency, or
TODO(ssd+vj): We should probably solve this by either ensuring the example has
def example2profile(example, profiles)
  profiles.values.find { |p| profile_contains_example?(p, example) }
end

def format_example(example)

def format_example(example)
  super(example).tap do |res|
    res[:run_time]   = example.execution_result.run_time
    res[:start_time] = example.execution_result.started_at.to_s
  end
end

def initialize(*args)

def initialize(*args)
  super(*args)
  @profiles = []
  # Will be valid after "start" state is reached.
  @profiles_info = nil
  @backend = nil
end

def profile_contains_example?(profile, example)

def profile_contains_example?(profile, example)
  # Heuristic for finding the profile an example came from:
  # Case 1: The profile_id on the example matches the name of the profile
  # Case 2: The profile contains a control that matches the id of the example
  if profile[:name] == example[:profile_id]
    true
  elsif profile[:controls] && profile[:controls].key?(example[:id])
    true
  else
    false
  end
end

def profile_info(profile)

def profile_info(profile)
  info = profile.info.dup
  [info[:name], info]
end

def start(_notification)

test execution has begun.
Called after all examples have been collected but before rspec
def start(_notification)
  # Note that the default profile may have no name - therefore
  # the hash may have a valid nil => entry.
  @profiles_info ||= Hash[@profiles.map { |x| profile_info(x) }]
end

def stop(notification)

def stop(notification)
  super(notification)
  examples = @output_hash.delete(:controls)
  missing = []
  examples.each do |example|
    control = example2control(example, @profiles_info)
    next missing.push(example) if control.nil?
    dump_one_example(example, control)
  end
  @output_hash[:profiles] = @profiles_info
  @output_hash[:other_checks] = missing
end