# typed: strict # frozen_string_literal: true require 'io/console' module Minitest module Distributed module Reporters class DistributedPogressReporter < Minitest::Reporter extend T::Sig sig { returns(Coordinators::CoordinatorInterface) } attr_reader :coordinator sig { params(io: IO, options: T::Hash[Symbol, T.untyped]).void } def initialize(io, options) super if io.tty? io.sync = true end @coordinator = T.let(options[:distributed].coordinator, Coordinators::CoordinatorInterface) end # Note: due to batching and parallel tests, we have no guarantee that `prerecord` # and `record` will be called in succession for the same test without calls to # either method being interjected for other tests. # # As a result we have no idea what will be on the last line of the console. # We always clear the full line before printing output. sig { override.params(klass: T.class_of(Runnable), name: String).void } def prerecord(klass, name) if io.tty? line_width = clear_current_line io.print("[#{results.acks}/#{results.size}] #{klass}##{name}".slice(0...line_width)) end end sig { override.params(result: Minitest::Result).void } def record(result) clear_current_line if io.tty? case (result_type = ResultType.of(result)) when ResultType::Passed # TODO: warn for tests that are slower than the test timeout. when ResultType::Skipped io.puts("#{result}\n") if options[:verbose] when ResultType::Error, ResultType::Failed io.puts("#{result}\n") else T.absurd(result_type) end end sig { override.void } def report clear_current_line if io.tty? end private sig { returns(Integer) } def clear_current_line _height, width = IO.console.winsize io.print("\r" + (' ' * width) + "\r") width end sig { returns(ResultAggregate) } def results coordinator.combined_results end end end end end