dream_test/reporters/progress

Live progress bar reporter.

This module renders a single-line progress bar that updates in-place using carriage returns, and adapts to the current terminal width.

Because it uses \r (carriage return) to rewrite the current line, it is best suited for interactive terminals. In CI logs (or when other output is printed concurrently), the output may be less readable.

Terminal width

Width is detected via Erlang io:columns/0 with fallbacks:

It is designed to be driven by dream_test/reporters/types.ReporterEvent, but most users should not call it directly. Prefer attaching it via runner.progress_reporter(progress.new()) and letting the runner drive events.

Example

pub fn main() {
  runner.new([tests()])
  |> runner.progress_reporter(progress.new())
  |> runner.exit_on_failure()
  |> runner.run()
}

Types

A progress-bar reporter that renders a single-line UI during a run.

Construct one with progress.new() and attach it to the runner via runner.progress_reporter(...).

pub opaque type ProgressReporter

Values

pub fn handle_event(
  reporter reporter: ProgressReporter,
  event event: types.ReporterEvent,
) -> option.Option(String)

Handle a single reporter event by writing an in-place progress bar line.

  • For RunStarted, prints an initial 0% bar.
  • For TestFinished, prints an updated bar using the included counts.
  • For RunFinished, prints a final 100% bar and a newline.

This function ignores hook events (HookStarted / HookFinished) so hook chatter doesn’t scramble the single-line UI.

Parameters

  • event: a ReporterEvent emitted by the runner
  • write: an output sink (typically io.print). For best results this should write without adding extra newlines.

When should I use this?

Usually you shouldn’t call it directly—prefer attaching it via runner.progress_reporter(progress.new()) and letting the runner drive events.

You may call it directly only if you are building your own reporter/driver and you are already receiving ReporterEvents.

Example

progress.handle_event(
  reporter_types.RunStarted(total: 10),
  write_progress_line_to_file,
)

use text <- result.try(
  file.read("test/tmp/progress_handle_event.txt")
  |> result.map_error(file.error_to_string),
)

text
|> should
|> match_snapshot("./test/snapshots/progress_handle_event_run_started.snap")
|> or_fail_with("expected handle_event output snapshot match")
pub fn new() -> ProgressReporter

Create a new progress reporter.

pub fn render(
  columns columns: Int,
  event event: types.ReporterEvent,
) -> String

Render a progress bar line for a given terminal width.

This is pure and is intended for testing and for custom reporter work.

Width is measured in graphemes (user-visible characters), so Unicode stays aligned. The width is clamped to a minimum of 20 so the bar remains readable.

Note: The columns input is typically a terminal column count (from io:columns/0), but rendering is done by grapheme count so we can safely pad/truncate Unicode.

Parameters

  • columns: terminal width (in columns)
  • event: event to render

Returns

A single line of text exactly columns graphemes wide (after clamping).

Example

progress.render(30, reporter_types.RunStarted(total: 10))
|> should
|> match_snapshot("./test/snapshots/progress_render_run_started.snap")
|> or_fail_with("expected render output snapshot match")
Search Document