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:
- if
io:columns/0fails, it reads theCOLUMNSenvironment variable - if that is missing/invalid, it defaults to 80 columns
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: aReporterEventemitted by the runnerwrite: an output sink (typicallyio.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 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")