ratatui_ruby 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.builds/ruby-3.2.yml +1 -1
- data/.builds/ruby-3.3.yml +1 -1
- data/.builds/ruby-3.4.yml +1 -1
- data/.builds/ruby-4.0.0.yml +1 -1
- data/AGENTS.md +12 -4
- data/CHANGELOG.md +49 -0
- data/README.md +7 -7
- data/Rakefile +1 -1
- data/doc/{application_architecture.md → concepts/application_architecture.md} +30 -0
- data/doc/{application_testing.md → concepts/application_testing.md} +4 -2
- data/doc/{event_handling.md → concepts/event_handling.md} +1 -1
- data/doc/contributors/auditing/parity.md +233 -0
- data/doc/contributors/developing_examples.md +10 -10
- data/doc/contributors/upstream_requests/tab_rects.md +173 -0
- data/doc/contributors/upstream_requests/title_rects.md +132 -0
- data/doc/contributors/v1.0.0_blockers.md +54 -747
- data/doc/{quickstart.md → getting_started/quickstart.md} +26 -26
- data/doc/{why.md → getting_started/why.md} +1 -1
- data/doc/index.md +23 -9
- data/doc/{terminal_limitations.md → troubleshooting/terminal_limitations.md} +33 -0
- data/doc/troubleshooting/tui_output.md +76 -0
- data/examples/app_all_events/README.md +1 -0
- data/examples/app_all_events/app.rb +2 -0
- data/examples/app_all_events/model/app_model.rb +2 -0
- data/examples/app_all_events/model/event_color_cycle.rb +2 -0
- data/examples/app_all_events/model/event_entry.rb +2 -0
- data/examples/app_all_events/model/msg.rb +2 -0
- data/examples/app_all_events/model/timestamp.rb +2 -0
- data/examples/app_all_events/update.rb +2 -0
- data/examples/app_all_events/view/app_view.rb +2 -0
- data/examples/app_all_events/view/controls_view.rb +2 -0
- data/examples/app_all_events/view/counts_view.rb +2 -0
- data/examples/app_all_events/view/live_view.rb +2 -0
- data/examples/app_all_events/view/log_view.rb +2 -0
- data/examples/app_all_events/view.rb +2 -0
- data/examples/app_color_picker/README.md +2 -0
- data/examples/app_color_picker/app.rb +2 -0
- data/examples/app_color_picker/clipboard.rb +2 -0
- data/examples/app_color_picker/color.rb +2 -0
- data/examples/app_color_picker/controls.rb +2 -0
- data/examples/app_color_picker/copy_dialog.rb +2 -0
- data/examples/app_color_picker/export_pane.rb +2 -0
- data/examples/app_color_picker/harmony.rb +2 -0
- data/examples/app_color_picker/input.rb +2 -0
- data/examples/app_color_picker/main_container.rb +2 -0
- data/examples/app_color_picker/palette.rb +2 -0
- data/examples/app_login_form/README.md +3 -0
- data/examples/app_login_form/app.rb +2 -0
- data/examples/app_stateful_interaction/README.md +2 -0
- data/examples/app_stateful_interaction/app.rb +2 -0
- data/examples/timeout_demo.rb +2 -0
- data/examples/verify_quickstart_dsl/README.md +2 -2
- data/examples/verify_quickstart_dsl/app.rb +2 -0
- data/examples/verify_quickstart_layout/README.md +2 -2
- data/examples/verify_quickstart_layout/app.rb +2 -0
- data/examples/verify_quickstart_lifecycle/README.md +2 -2
- data/examples/verify_quickstart_lifecycle/app.rb +2 -0
- data/examples/verify_readme_usage/app.rb +2 -0
- data/examples/{widget_barchart_demo → widget_barchart}/README.md +5 -3
- data/examples/{widget_barchart_demo → widget_barchart}/app.rb +7 -5
- data/examples/{widget_block_demo → widget_block}/README.md +5 -3
- data/examples/{widget_block_demo → widget_block}/app.rb +6 -4
- data/examples/{widget_box_demo → widget_box}/README.md +7 -4
- data/examples/{widget_box_demo → widget_box}/app.rb +7 -5
- data/examples/{widget_calendar_demo → widget_calendar}/README.md +6 -3
- data/examples/{widget_calendar_demo → widget_calendar}/app.rb +6 -4
- data/examples/{widget_canvas_demo → widget_canvas}/README.md +2 -2
- data/examples/{widget_canvas_demo → widget_canvas}/app.rb +6 -4
- data/examples/{widget_cell_demo → widget_cell}/README.md +6 -3
- data/examples/{widget_cell_demo → widget_cell}/app.rb +7 -5
- data/examples/{widget_center_demo → widget_center}/README.md +2 -2
- data/examples/{widget_center_demo → widget_center}/app.rb +6 -4
- data/examples/{widget_chart_demo → widget_chart}/README.md +7 -4
- data/examples/{widget_chart_demo → widget_chart}/app.rb +7 -5
- data/examples/{widget_gauge_demo → widget_gauge}/README.md +6 -3
- data/examples/{widget_gauge_demo → widget_gauge}/app.rb +7 -5
- data/examples/widget_layout_split/README.md +5 -2
- data/examples/widget_layout_split/app.rb +3 -1
- data/examples/{widget_line_gauge_demo → widget_line_gauge}/README.md +6 -3
- data/examples/{widget_line_gauge_demo → widget_line_gauge}/app.rb +7 -5
- data/examples/{widget_list_demo → widget_list}/README.md +7 -4
- data/examples/{widget_list_demo → widget_list}/app.rb +7 -5
- data/examples/{widget_map_demo → widget_map}/README.md +7 -4
- data/examples/{widget_map_demo → widget_map}/app.rb +4 -2
- data/examples/{widget_overlay_demo → widget_overlay}/README.md +6 -3
- data/examples/{widget_overlay_demo → widget_overlay}/app.rb +5 -3
- data/examples/{widget_popup_demo → widget_popup}/README.md +7 -4
- data/examples/{widget_popup_demo → widget_popup}/app.rb +6 -4
- data/examples/{widget_ratatui_logo_demo → widget_ratatui_logo}/README.md +6 -3
- data/examples/{widget_ratatui_logo_demo → widget_ratatui_logo}/app.rb +8 -6
- data/examples/{widget_ratatui_mascot_demo → widget_ratatui_mascot}/README.md +6 -3
- data/examples/{widget_ratatui_mascot_demo → widget_ratatui_mascot}/app.rb +6 -4
- data/examples/widget_rect/README.md +5 -2
- data/examples/widget_rect/app.rb +2 -0
- data/examples/widget_render/README.md +4 -1
- data/examples/widget_render/app.rb +2 -0
- data/examples/widget_rich_text/README.md +4 -1
- data/examples/widget_rich_text/app.rb +2 -0
- data/examples/widget_scroll_text/README.md +4 -1
- data/examples/widget_scroll_text/app.rb +3 -1
- data/examples/{widget_scrollbar_demo → widget_scrollbar}/README.md +7 -4
- data/examples/{widget_scrollbar_demo → widget_scrollbar}/app.rb +6 -4
- data/examples/{widget_sparkline_demo → widget_sparkline}/README.md +6 -3
- data/examples/{widget_sparkline_demo → widget_sparkline}/app.rb +7 -5
- data/examples/widget_style_colors/README.md +4 -1
- data/examples/widget_style_colors/app.rb +2 -0
- data/examples/{widget_table_demo → widget_table}/README.md +7 -4
- data/examples/{widget_table_demo → widget_table}/app.rb +4 -2
- data/examples/{widget_tabs_demo → widget_tabs}/README.md +6 -3
- data/examples/{widget_tabs_demo → widget_tabs}/app.rb +7 -5
- data/examples/widget_text_width/README.md +5 -2
- data/examples/widget_text_width/app.rb +2 -0
- data/exe/.gitkeep +0 -0
- data/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/ext/ratatui_ruby/extconf.rb +2 -0
- data/ext/ratatui_ruby/src/lib.rs +2 -2
- data/ext/ratatui_ruby/src/rendering.rs +9 -0
- data/ext/ratatui_ruby/src/style.rs +22 -2
- data/ext/ratatui_ruby/src/text.rs +26 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +8 -6
- data/ext/ratatui_ruby/src/widgets/chart.rs +31 -4
- data/ext/ratatui_ruby/src/widgets/table.rs +13 -5
- data/ext/ratatui_ruby/src/widgets/tabs.rs +49 -9
- data/lib/ratatui_ruby/buffer/cell.rb +2 -0
- data/lib/ratatui_ruby/buffer.rb +2 -0
- data/lib/ratatui_ruby/cell.rb +2 -0
- data/lib/ratatui_ruby/event/focus_gained.rb +2 -0
- data/lib/ratatui_ruby/event/focus_lost.rb +2 -0
- data/lib/ratatui_ruby/event/key/character.rb +2 -0
- data/lib/ratatui_ruby/event/key/media.rb +2 -0
- data/lib/ratatui_ruby/event/key/modifier.rb +2 -0
- data/lib/ratatui_ruby/event/key/navigation.rb +2 -0
- data/lib/ratatui_ruby/event/key/system.rb +2 -0
- data/lib/ratatui_ruby/event/key.rb +2 -0
- data/lib/ratatui_ruby/event/mouse.rb +2 -0
- data/lib/ratatui_ruby/event/none.rb +2 -0
- data/lib/ratatui_ruby/event/paste.rb +2 -0
- data/lib/ratatui_ruby/event/resize.rb +2 -0
- data/lib/ratatui_ruby/event.rb +2 -0
- data/lib/ratatui_ruby/frame.rb +2 -0
- data/lib/ratatui_ruby/layout/constraint.rb +2 -0
- data/lib/ratatui_ruby/layout/layout.rb +2 -0
- data/lib/ratatui_ruby/layout/rect.rb +2 -0
- data/lib/ratatui_ruby/layout.rb +2 -0
- data/lib/ratatui_ruby/list_state.rb +2 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar.rb +2 -0
- data/lib/ratatui_ruby/schema/bar_chart/bar_group.rb +2 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +4 -2
- data/lib/ratatui_ruby/schema/block.rb +4 -2
- data/lib/ratatui_ruby/schema/calendar.rb +4 -2
- data/lib/ratatui_ruby/schema/canvas.rb +2 -0
- data/lib/ratatui_ruby/schema/center.rb +2 -0
- data/lib/ratatui_ruby/schema/chart.rb +4 -2
- data/lib/ratatui_ruby/schema/clear.rb +2 -0
- data/lib/ratatui_ruby/schema/constraint.rb +2 -0
- data/lib/ratatui_ruby/schema/cursor.rb +2 -0
- data/lib/ratatui_ruby/schema/draw.rb +2 -0
- data/lib/ratatui_ruby/schema/gauge.rb +4 -2
- data/lib/ratatui_ruby/schema/layout.rb +2 -0
- data/lib/ratatui_ruby/schema/line_gauge.rb +4 -2
- data/lib/ratatui_ruby/schema/list.rb +3 -1
- data/lib/ratatui_ruby/schema/list_item.rb +2 -0
- data/lib/ratatui_ruby/schema/overlay.rb +2 -0
- data/lib/ratatui_ruby/schema/paragraph.rb +2 -0
- data/lib/ratatui_ruby/schema/ratatui_logo.rb +4 -2
- data/lib/ratatui_ruby/schema/ratatui_mascot.rb +4 -2
- data/lib/ratatui_ruby/schema/rect.rb +2 -0
- data/lib/ratatui_ruby/schema/row.rb +2 -0
- data/lib/ratatui_ruby/schema/scrollbar.rb +4 -2
- data/lib/ratatui_ruby/schema/shape/label.rb +2 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +4 -2
- data/lib/ratatui_ruby/schema/style.rb +2 -0
- data/lib/ratatui_ruby/schema/table.rb +2 -0
- data/lib/ratatui_ruby/schema/tabs.rb +4 -2
- data/lib/ratatui_ruby/schema/text.rb +2 -0
- data/lib/ratatui_ruby/scrollbar_state.rb +2 -0
- data/lib/ratatui_ruby/style/style.rb +3 -0
- data/lib/ratatui_ruby/style.rb +2 -0
- data/lib/ratatui_ruby/table_state.rb +2 -0
- data/lib/ratatui_ruby/test_helper/event_injection.rb +2 -0
- data/lib/ratatui_ruby/test_helper/snapshot.rb +62 -21
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/axis_labels_alignment.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.ansi +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/barchart_styled_label.txt +5 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.ansi +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/chart_rendering.txt +24 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/half_block_marker.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_bottom.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_left.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_right.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.ansi +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/legend_position_top.txt +12 -0
- data/lib/ratatui_ruby/test_helper/snapshots/my_snapshot.txt +1 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_axis_title.txt +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi +10 -0
- data/lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt +10 -0
- data/lib/ratatui_ruby/test_helper/style_assertions.rb +2 -0
- data/lib/ratatui_ruby/test_helper/terminal.rb +5 -0
- data/lib/ratatui_ruby/test_helper/test_doubles.rb +2 -0
- data/lib/ratatui_ruby/test_helper.rb +6 -4
- data/lib/ratatui_ruby/tui/buffer_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/canvas_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/core.rb +2 -0
- data/lib/ratatui_ruby/tui/layout_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/state_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/style_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/text_factories.rb +2 -0
- data/lib/ratatui_ruby/tui/widget_factories.rb +2 -0
- data/lib/ratatui_ruby/tui.rb +2 -0
- data/lib/ratatui_ruby/version.rb +3 -1
- data/lib/ratatui_ruby/widgets/bar_chart/bar.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart/bar_group.rb +2 -0
- data/lib/ratatui_ruby/widgets/bar_chart.rb +7 -4
- data/lib/ratatui_ruby/widgets/block.rb +46 -2
- data/lib/ratatui_ruby/widgets/calendar.rb +4 -2
- data/lib/ratatui_ruby/widgets/canvas.rb +2 -0
- data/lib/ratatui_ruby/widgets/cell.rb +2 -0
- data/lib/ratatui_ruby/widgets/center.rb +2 -0
- data/lib/ratatui_ruby/widgets/chart.rb +13 -6
- data/lib/ratatui_ruby/widgets/clear.rb +2 -0
- data/lib/ratatui_ruby/widgets/cursor.rb +2 -0
- data/lib/ratatui_ruby/widgets/gauge.rb +4 -2
- data/lib/ratatui_ruby/widgets/line_gauge.rb +4 -2
- data/lib/ratatui_ruby/widgets/list.rb +3 -1
- data/lib/ratatui_ruby/widgets/list_item.rb +2 -0
- data/lib/ratatui_ruby/widgets/overlay.rb +2 -0
- data/lib/ratatui_ruby/widgets/paragraph.rb +2 -0
- data/lib/ratatui_ruby/widgets/ratatui_logo.rb +4 -2
- data/lib/ratatui_ruby/widgets/ratatui_mascot.rb +4 -2
- data/lib/ratatui_ruby/widgets/row.rb +2 -0
- data/lib/ratatui_ruby/widgets/scrollbar.rb +4 -2
- data/lib/ratatui_ruby/widgets/shape/label.rb +2 -0
- data/lib/ratatui_ruby/widgets/sparkline.rb +7 -4
- data/lib/ratatui_ruby/widgets/table.rb +2 -0
- data/lib/ratatui_ruby/widgets/tabs.rb +12 -8
- data/lib/ratatui_ruby/widgets.rb +2 -0
- data/lib/ratatui_ruby.rb +130 -9
- data/tasks/autodoc/examples.rb +2 -0
- data/tasks/autodoc/member.rb +2 -0
- data/tasks/autodoc/name.rb +2 -0
- data/tasks/autodoc.rake +2 -0
- data/tasks/bump/cargo_lockfile.rb +2 -0
- data/tasks/bump/changelog.rb +2 -0
- data/tasks/bump/header.rb +2 -0
- data/tasks/bump/history.rb +2 -0
- data/tasks/bump/links.rb +2 -0
- data/tasks/bump/manifest.rb +2 -0
- data/tasks/bump/ruby_gem.rb +2 -0
- data/tasks/bump/sem_ver.rb +2 -0
- data/tasks/bump/unreleased_section.rb +2 -0
- data/tasks/bump.rake +2 -0
- data/tasks/doc.rake +268 -0
- data/tasks/extension.rake +2 -0
- data/tasks/lint.rake +115 -0
- data/tasks/rdoc_config.rb +18 -4
- data/tasks/sourcehut.rake +2 -0
- data/tasks/terminal_preview/app_screenshot.rb +2 -0
- data/tasks/terminal_preview/crash_report.rb +2 -0
- data/tasks/terminal_preview/example_app.rb +2 -0
- data/tasks/terminal_preview/launcher_script.rb +2 -0
- data/tasks/terminal_preview/preview_collection.rb +2 -0
- data/tasks/terminal_preview/preview_timing.rb +2 -0
- data/tasks/terminal_preview/safety_confirmation.rb +2 -0
- data/tasks/terminal_preview/saved_screenshot.rb +2 -0
- data/tasks/terminal_preview/system_appearance.rb +2 -0
- data/tasks/terminal_preview/terminal_window.rb +2 -0
- data/tasks/terminal_preview/window_id.rb +2 -0
- data/tasks/terminal_preview.rake +2 -0
- data/tasks/test.rake +2 -0
- data/tasks/website/index_page.rb +2 -0
- data/tasks/website/version.rb +12 -2
- data/tasks/website/version_menu.rb +2 -0
- data/tasks/website/versioned_documentation.rb +2 -0
- data/tasks/website/website.rb +2 -0
- data/tasks/website.rake +2 -0
- metadata +97 -75
- data/doc/contributors/architectural_overhaul/chat_conversations.md +0 -4952
- data/doc/contributors/architectural_overhaul/implementation_plan.md +0 -60
- data/doc/contributors/architectural_overhaul/task.md +0 -37
- /data/doc/{async.md → concepts/async.md} +0 -0
- /data/doc/{interactive_design.md → concepts/interactive_design.md} +0 -0
- /data/doc/images/{widget_barchart_demo.png → widget_barchart.png} +0 -0
- /data/doc/images/{widget_block_demo.png → widget_block.png} +0 -0
- /data/doc/images/{widget_box_demo.png → widget_box.png} +0 -0
- /data/doc/images/{widget_calendar_demo.png → widget_calendar.png} +0 -0
- /data/doc/images/{widget_canvas_demo.png → widget_canvas.png} +0 -0
- /data/doc/images/{widget_cell_demo.png → widget_cell.png} +0 -0
- /data/doc/images/{widget_center_demo.png → widget_center.png} +0 -0
- /data/doc/images/{widget_chart_demo.png → widget_chart.png} +0 -0
- /data/doc/images/{widget_gauge_demo.png → widget_gauge.png} +0 -0
- /data/doc/images/{widget_line_gauge_demo.png → widget_line_gauge.png} +0 -0
- /data/doc/images/{widget_list_demo.png → widget_list.png} +0 -0
- /data/doc/images/{widget_map_demo.png → widget_map.png} +0 -0
- /data/doc/images/{widget_overlay_demo.png → widget_overlay.png} +0 -0
- /data/doc/images/{widget_popup_demo.png → widget_popup.png} +0 -0
- /data/doc/images/{widget_ratatui_logo_demo.png → widget_ratatui_logo.png} +0 -0
- /data/doc/images/{widget_ratatui_mascot_demo.png → widget_ratatui_mascot.png} +0 -0
- /data/doc/images/{widget_scrollbar_demo.png → widget_scrollbar.png} +0 -0
- /data/doc/images/{widget_sparkline_demo.png → widget_sparkline.png} +0 -0
- /data/doc/images/{widget_table_demo.png → widget_table.png} +0 -0
- /data/doc/images/{widget_tabs_demo.png → widget_tabs.png} +0 -0
- /data/doc/{v0.7.0_migration.md → migration/v0_7_0.md} +0 -0
- /data/doc/{debugging.md → troubleshooting/debugging.md} +0 -0
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
#--
|
|
3
4
|
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
5
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
+
#++
|
|
5
7
|
|
|
6
8
|
require "fileutils"
|
|
7
9
|
|
|
@@ -13,9 +15,10 @@ module RatatuiRuby
|
|
|
13
15
|
# Verifying every character of a TUI screen by hand is tedious. Snapshots let you
|
|
14
16
|
# capture the screen once and compare against it in future runs.
|
|
15
17
|
#
|
|
16
|
-
# This mixin provides <tt>
|
|
17
|
-
# <tt>assert_rich_snapshot</tt> for styled ANSI output
|
|
18
|
-
#
|
|
18
|
+
# This mixin provides <tt>assert_plain_snapshot</tt> for plain text,
|
|
19
|
+
# <tt>assert_rich_snapshot</tt> for styled ANSI output, and
|
|
20
|
+
# <tt>assert_snapshots</tt> (plural) for both. All auto-create snapshot
|
|
21
|
+
# files on first run.
|
|
19
22
|
#
|
|
20
23
|
# Use it to verify complex layouts, styles, and interactions without manual assertions.
|
|
21
24
|
#
|
|
@@ -60,38 +63,46 @@ module RatatuiRuby
|
|
|
60
63
|
#
|
|
61
64
|
# Mask dynamic content (timestamps, IDs) with a normalization block:
|
|
62
65
|
#
|
|
63
|
-
#
|
|
66
|
+
# assert_snapshots("dashboard") do |lines|
|
|
64
67
|
# lines.map { |l| l.gsub(/\d{4}-\d{2}-\d{2}/, "YYYY-MM-DD") }
|
|
65
68
|
# end
|
|
66
69
|
#
|
|
67
70
|
module Snapshot
|
|
68
71
|
##
|
|
69
|
-
# Asserts that the current screen content matches a stored snapshot.
|
|
72
|
+
# Asserts that the current screen content matches a stored plain text snapshot.
|
|
70
73
|
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
#
|
|
74
|
+
# Plain text snapshots capture layout but miss styling bugs: wrong colors, missing bold,
|
|
75
|
+
# invisible text on a matching background. *Prefer <tt>assert_snapshots</tt>* (plural) to catch
|
|
76
|
+
# styling regressions.
|
|
74
77
|
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
+
# Plain text snapshots are human-readable when viewed in any editor or diff tool. They
|
|
79
|
+
# pair well with rich snapshots for documentation. Use <tt>assert_snapshots</tt> to generate both.
|
|
80
|
+
#
|
|
81
|
+
# assert_plain_snapshot("login_screen")
|
|
82
|
+
# # Compares against: test/snapshots/login_screen.txt
|
|
78
83
|
#
|
|
79
84
|
# # With normalization block
|
|
80
|
-
#
|
|
85
|
+
# assert_plain_snapshot("clock") do |actual|
|
|
81
86
|
# actual.map { |l| l.gsub(/\d{2}:\d{2}/, "XX:XX") }
|
|
82
87
|
# end
|
|
83
88
|
#
|
|
84
89
|
# [name] String name of the snapshot (without extension).
|
|
85
90
|
# [msg] String optional failure message.
|
|
86
|
-
def
|
|
91
|
+
def assert_plain_snapshot(name, msg = nil, snapshot_dir: nil, &)
|
|
87
92
|
# Get the path of the test file calling this method
|
|
88
|
-
|
|
89
|
-
snapshot_dir = File.join(File.dirname(caller_path), "snapshots")
|
|
93
|
+
snapshot_dir ||= File.join(File.dirname(caller_locations(1, 1).first.path), "snapshots")
|
|
90
94
|
snapshot_path = File.join(snapshot_dir, "#{name}.txt")
|
|
91
95
|
|
|
92
96
|
assert_screen_matches(snapshot_path, msg, &)
|
|
93
97
|
end
|
|
94
98
|
|
|
99
|
+
##
|
|
100
|
+
# @deprecated Use {#assert_plain_snapshot} instead.
|
|
101
|
+
def assert_snapshot(name, msg = nil, &)
|
|
102
|
+
warn "assert_snapshot is deprecated; use assert_plain_snapshot instead", uplevel: 1
|
|
103
|
+
assert_plain_snapshot(name, msg, &)
|
|
104
|
+
end
|
|
105
|
+
|
|
95
106
|
##
|
|
96
107
|
# Asserts that the current screen content matches the expected content.
|
|
97
108
|
#
|
|
@@ -184,12 +195,17 @@ module RatatuiRuby
|
|
|
184
195
|
end
|
|
185
196
|
|
|
186
197
|
##
|
|
187
|
-
# Asserts that the current screen content (including colors
|
|
198
|
+
# Asserts that the current screen content (including colors and styles) matches a stored ANSI snapshot.
|
|
199
|
+
#
|
|
200
|
+
# TUIs communicate meaning through colors and styles. Rich snapshots capture everything:
|
|
201
|
+
# wrong colors, missing bold, invisible text on a matching background. *Prefer <tt>assert_snapshots</tt>*
|
|
202
|
+
# (plural) to also generate human-readable plain text files for documentation.
|
|
188
203
|
#
|
|
189
|
-
#
|
|
190
|
-
#
|
|
204
|
+
# The <tt>.ansi</tt> snapshot files contain ANSI escape codes. You can <tt>cat</tt> them in a terminal
|
|
205
|
+
# to see exactly what the screen looked like.
|
|
191
206
|
#
|
|
192
207
|
# assert_rich_snapshot("login_screen")
|
|
208
|
+
# # Compares against: test/snapshots/login_screen.ansi
|
|
193
209
|
#
|
|
194
210
|
# # With normalization
|
|
195
211
|
# assert_rich_snapshot("log_view") do |lines|
|
|
@@ -198,9 +214,8 @@ module RatatuiRuby
|
|
|
198
214
|
#
|
|
199
215
|
# [name] String snapshot name.
|
|
200
216
|
# [msg] String optional failure message.
|
|
201
|
-
def assert_rich_snapshot(name, msg = nil)
|
|
202
|
-
|
|
203
|
-
snapshot_dir = File.join(File.dirname(caller_path), "snapshots")
|
|
217
|
+
def assert_rich_snapshot(name, msg = nil, snapshot_dir: nil)
|
|
218
|
+
snapshot_dir ||= File.join(File.dirname(caller_locations(1, 1).first.path), "snapshots")
|
|
204
219
|
snapshot_path = File.join(snapshot_dir, "#{name}.ansi")
|
|
205
220
|
|
|
206
221
|
actual_content = _render_buffer_with_ansi
|
|
@@ -252,6 +267,32 @@ module RatatuiRuby
|
|
|
252
267
|
end
|
|
253
268
|
end
|
|
254
269
|
|
|
270
|
+
##
|
|
271
|
+
# Asserts both plain text and rich (ANSI-styled) snapshots match.
|
|
272
|
+
#
|
|
273
|
+
# This is the recommended snapshot assertion. It calls both <tt>assert_plain_snapshot</tt> and
|
|
274
|
+
# <tt>assert_rich_snapshot</tt> with the same name, generating <tt>.txt</tt> and <tt>.ansi</tt> files.
|
|
275
|
+
#
|
|
276
|
+
# Rich snapshots catch styling bugs that plain text misses. Plain text snapshots are
|
|
277
|
+
# human-readable in any editor or diff tool, making them valuable for documentation and
|
|
278
|
+
# code review. Together, they provide comprehensive coverage and discoverability.
|
|
279
|
+
#
|
|
280
|
+
# assert_snapshots("login_screen")
|
|
281
|
+
# # Creates/compares: snapshots/login_screen.txt AND snapshots/login_screen.ansi
|
|
282
|
+
#
|
|
283
|
+
# # With normalization (masks dynamic content like timestamps)
|
|
284
|
+
# assert_snapshots("dashboard") do |lines|
|
|
285
|
+
# lines.map { |l| l.gsub(/\d{2}:\d{2}:\d{2}/, "HH:MM:SS") }
|
|
286
|
+
# end
|
|
287
|
+
#
|
|
288
|
+
# [name] String snapshot name (without extension).
|
|
289
|
+
# [msg] String optional failure message.
|
|
290
|
+
def assert_snapshots(name, msg = nil, &)
|
|
291
|
+
snapshot_dir = File.join(File.dirname(caller_locations(1, 1).first.path), "snapshots")
|
|
292
|
+
assert_plain_snapshot(name, msg, snapshot_dir:, &)
|
|
293
|
+
assert_rich_snapshot(name, msg, snapshot_dir:, &)
|
|
294
|
+
end
|
|
295
|
+
|
|
255
296
|
##
|
|
256
297
|
# Returns the current buffer content as an ANSI-encoded string.
|
|
257
298
|
#
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[0m┌Aligned Chart─────────────────────────────────────────────────────────────────┐[0m
|
|
2
|
+
[0m│10│Value ┌──────┐│[0m
|
|
3
|
+
[0m│ │ │[32mTestDS││[0m
|
|
4
|
+
[0m│ │ [32m••└──────┘│[0m
|
|
5
|
+
[0m│ │ [32m•••• │[0m
|
|
6
|
+
[0m│ │ [32m•••• │[0m
|
|
7
|
+
[0m│ │ [32m•••• │[0m
|
|
8
|
+
[0m│ │ [32m•••• │[0m
|
|
9
|
+
[0m│ │ [32m•••• │[0m
|
|
10
|
+
[0m│ │ [32m•••• │[0m
|
|
11
|
+
[0m│ │ [32m••• │[0m
|
|
12
|
+
[0m│ 5│ [32m•••• │[0m
|
|
13
|
+
[0m│ │ [32m•••• │[0m
|
|
14
|
+
[0m│ │ [32m•••• │[0m
|
|
15
|
+
[0m│ │ [32m•••• │[0m
|
|
16
|
+
[0m│ │ [32m•••• │[0m
|
|
17
|
+
[0m│ │ [32m•••• │[0m
|
|
18
|
+
[0m│ │ [32m•••• │[0m
|
|
19
|
+
[0m│ │ [32m•••• │[0m
|
|
20
|
+
[0m│ │ [32m•••• │[0m
|
|
21
|
+
[0m│ 0│[32m•• Time│[0m
|
|
22
|
+
[0m│ └───────────────────────────────────────────────────────────────────────────│[0m
|
|
23
|
+
[0m│ 0 5 10│[0m
|
|
24
|
+
[0m└──────────────────────────────────────────────────────────────────────────────┘[0m
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
┌Aligned Chart─────────────────────────────────────────────────────────────────┐
|
|
2
|
+
│10│Value ┌──────┐│
|
|
3
|
+
│ │ │TestDS││
|
|
4
|
+
│ │ ••└──────┘│
|
|
5
|
+
│ │ •••• │
|
|
6
|
+
│ │ •••• │
|
|
7
|
+
│ │ •••• │
|
|
8
|
+
│ │ •••• │
|
|
9
|
+
│ │ •••• │
|
|
10
|
+
│ │ •••• │
|
|
11
|
+
│ │ ••• │
|
|
12
|
+
│ 5│ •••• │
|
|
13
|
+
│ │ •••• │
|
|
14
|
+
│ │ •••• │
|
|
15
|
+
│ │ •••• │
|
|
16
|
+
│ │ •••• │
|
|
17
|
+
│ │ •••• │
|
|
18
|
+
│ │ •••• │
|
|
19
|
+
│ │ •••• │
|
|
20
|
+
│ │ •••• │
|
|
21
|
+
│ 0│•• Time│
|
|
22
|
+
│ └───────────────────────────────────────────────────────────────────────────│
|
|
23
|
+
│ 0 5 10│
|
|
24
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
[0m┌Test Chart────────────────────────────────────────────────────────────────────┐[0m
|
|
2
|
+
[0m│10│Value ┌──────┐│[0m
|
|
3
|
+
[0m│ │ │[31mTestDS││[0m
|
|
4
|
+
[0m│ │ [31m••└──────┘│[0m
|
|
5
|
+
[0m│ │ [31m•••• │[0m
|
|
6
|
+
[0m│ │ [31m•••• │[0m
|
|
7
|
+
[0m│ │ [31m•••• │[0m
|
|
8
|
+
[0m│ │ [31m•••• │[0m
|
|
9
|
+
[0m│ │ [31m•••• │[0m
|
|
10
|
+
[0m│ │ [31m•••• │[0m
|
|
11
|
+
[0m│ │ [31m••• │[0m
|
|
12
|
+
[0m│ │ [31m•••• │[0m
|
|
13
|
+
[0m│ │ [31m•••• │[0m
|
|
14
|
+
[0m│ │ [31m•••• │[0m
|
|
15
|
+
[0m│ │ [31m•••• │[0m
|
|
16
|
+
[0m│ │ [31m•••• │[0m
|
|
17
|
+
[0m│ │ [31m•••• │[0m
|
|
18
|
+
[0m│ │ [31m•••• │[0m
|
|
19
|
+
[0m│ │ [31m•••• │[0m
|
|
20
|
+
[0m│ │ [31m•••• │[0m
|
|
21
|
+
[0m│0 │[31m•• Time│[0m
|
|
22
|
+
[0m│ └───────────────────────────────────────────────────────────────────────────│[0m
|
|
23
|
+
[0m│ 0 10│[0m
|
|
24
|
+
[0m└──────────────────────────────────────────────────────────────────────────────┘[0m
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
┌Test Chart────────────────────────────────────────────────────────────────────┐
|
|
2
|
+
│10│Value ┌──────┐│
|
|
3
|
+
│ │ │TestDS││
|
|
4
|
+
│ │ ••└──────┘│
|
|
5
|
+
│ │ •••• │
|
|
6
|
+
│ │ •••• │
|
|
7
|
+
│ │ •••• │
|
|
8
|
+
│ │ •••• │
|
|
9
|
+
│ │ •••• │
|
|
10
|
+
│ │ •••• │
|
|
11
|
+
│ │ ••• │
|
|
12
|
+
│ │ •••• │
|
|
13
|
+
│ │ •••• │
|
|
14
|
+
│ │ •••• │
|
|
15
|
+
│ │ •••• │
|
|
16
|
+
│ │ •••• │
|
|
17
|
+
│ │ •••• │
|
|
18
|
+
│ │ •••• │
|
|
19
|
+
│ │ •••• │
|
|
20
|
+
│ │ •••• │
|
|
21
|
+
│0 │•• Time│
|
|
22
|
+
│ └───────────────────────────────────────────────────────────────────────────│
|
|
23
|
+
│ 0 10│
|
|
24
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Snapshot Content
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
#--
|
|
3
4
|
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
5
|
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
+
#++
|
|
5
7
|
|
|
6
8
|
require "timeout"
|
|
7
9
|
require "minitest/mock"
|
|
@@ -46,6 +48,9 @@ module RatatuiRuby
|
|
|
46
48
|
# # render and test your app
|
|
47
49
|
# end
|
|
48
50
|
def with_test_terminal(width = 80, height = 24, **opts)
|
|
51
|
+
# Defensive cleanup: reset any stale session state from previous test failures
|
|
52
|
+
RatatuiRuby.instance_variable_set(:@tui_session_active, false)
|
|
53
|
+
|
|
49
54
|
RatatuiRuby.init_test_terminal(width, height)
|
|
50
55
|
# Flush any lingering events from previous tests
|
|
51
56
|
while (event = RatatuiRuby.poll_event) && !event.none?; end
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
3
8
|
require "fileutils"
|
|
4
9
|
require_relative "test_helper/terminal"
|
|
5
10
|
require_relative "test_helper/snapshot"
|
|
@@ -7,9 +12,6 @@ require_relative "test_helper/event_injection"
|
|
|
7
12
|
require_relative "test_helper/style_assertions"
|
|
8
13
|
require_relative "test_helper/test_doubles"
|
|
9
14
|
|
|
10
|
-
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
11
|
-
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
12
|
-
|
|
13
15
|
module RatatuiRuby
|
|
14
16
|
##
|
|
15
17
|
# Helpers for testing RatatuiRuby applications.
|
|
@@ -39,7 +41,7 @@ module RatatuiRuby
|
|
|
39
41
|
# def test_initial_render
|
|
40
42
|
# with_test_terminal(80, 24) do
|
|
41
43
|
# MyApp.new.run_once
|
|
42
|
-
#
|
|
44
|
+
# assert_snapshots("initial")
|
|
43
45
|
# end
|
|
44
46
|
# end
|
|
45
47
|
#
|
data/lib/ratatui_ruby/tui.rb
CHANGED