ratatui_ruby 1.3.2 → 1.4.0
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/ext/ratatui_ruby/Cargo.lock +1 -1
- data/ext/ratatui_ruby/Cargo.toml +1 -1
- data/lib/ratatui_ruby/test_helper/snapshot.rb +58 -10
- data/lib/ratatui_ruby/test_helper/subprocess_timeout.rb +35 -0
- data/lib/ratatui_ruby/test_helper.rb +2 -0
- data/lib/ratatui_ruby/version.rb +1 -1
- metadata +17 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3e12c46f758cf25eb436da52bbdcbf46f5cd256b804cb3f67a2d6edeeb8d4062
|
|
4
|
+
data.tar.gz: c4aa2e4c6251a6a75b8ac57e3c7f6133c88066185ee5e9cd1633fbc459edf612
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dca9adc8ecef9e432c163b5b7b9e2488d42f9f1db98212a5c140a70bf21dc6c19fa687a97fb30d52ef9cadf8c5dd34a3aecbe471562ba5d9bfdb8c1ff85b99bf
|
|
7
|
+
data.tar.gz: 5f1e347a863736fae0ea9854a37402bd3115c311a228c23b24848113c23a21beeb97b5a33a9177611cd83c7e9d61ed6b4c4c9cf85c110e89f358e805f456465c
|
data/ext/ratatui_ruby/Cargo.lock
CHANGED
data/ext/ratatui_ruby/Cargo.toml
CHANGED
|
@@ -99,7 +99,62 @@ module RatatuiRuby
|
|
|
99
99
|
#--
|
|
100
100
|
# SPDX-SnippetEnd
|
|
101
101
|
#++
|
|
102
|
+
#
|
|
103
|
+
# === Class-Wide Normalization
|
|
104
|
+
#
|
|
105
|
+
# When every test in a class faces the same dynamic content, override
|
|
106
|
+
# <tt>normalize_snapshots</tt> instead of repeating the block. Return a callable
|
|
107
|
+
# (or Array of callables) that transforms lines. The hook runs before any per-call
|
|
108
|
+
# block, so the two compose naturally. See <tt>normalize_snapshots</tt> for details.
|
|
102
109
|
module Snapshot
|
|
110
|
+
# Override this method to normalize all snapshots in a test class.
|
|
111
|
+
#
|
|
112
|
+
# Snapshot assertions compare screen content against stored files. Dynamic content
|
|
113
|
+
# (timestamps, temp paths, random IDs) breaks those comparisons. Passing a normalization
|
|
114
|
+
# block to each assertion fixes one test but creates duplication when every test in a
|
|
115
|
+
# class faces the same dynamic content.
|
|
116
|
+
#
|
|
117
|
+
# Override <tt>normalize_snapshots</tt> in your test class to define class-wide
|
|
118
|
+
# normalization. Accept an Array of Strings (lines) and return the transformed Array.
|
|
119
|
+
#
|
|
120
|
+
# The hook runs before any per-call normalization block, so the two compose naturally:
|
|
121
|
+
# the hook handles class-wide concerns and the block handles one-off masking.
|
|
122
|
+
#
|
|
123
|
+
# Returns <tt>lines</tt> unchanged by default (no normalization).
|
|
124
|
+
#
|
|
125
|
+
# === Example
|
|
126
|
+
#
|
|
127
|
+
#--
|
|
128
|
+
# SPDX-SnippetBegin
|
|
129
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long
|
|
130
|
+
# SPDX-License-Identifier: MIT-0
|
|
131
|
+
#++
|
|
132
|
+
# class TestFileExplorer < Minitest::Test
|
|
133
|
+
# include RatatuiRuby::TestHelper
|
|
134
|
+
#
|
|
135
|
+
# private def normalize_snapshots(lines)
|
|
136
|
+
# lines.map { |l| l.gsub(Dir.pwd, "STABLE_PATH") }
|
|
137
|
+
# end
|
|
138
|
+
#
|
|
139
|
+
# def test_initial_render
|
|
140
|
+
# # normalize_snapshots runs automatically — no block needed
|
|
141
|
+
# assert_snapshots("initial_render")
|
|
142
|
+
# end
|
|
143
|
+
#
|
|
144
|
+
# def test_after_scroll
|
|
145
|
+
# # Per-call block composes with the hook (hook runs first)
|
|
146
|
+
# assert_snapshots("after_scroll") do |lines|
|
|
147
|
+
# lines.map { |l| l.gsub(/\d{2}:\d{2}/, "XX:XX") }
|
|
148
|
+
# end
|
|
149
|
+
# end
|
|
150
|
+
# end
|
|
151
|
+
#
|
|
152
|
+
#--
|
|
153
|
+
# SPDX-SnippetEnd
|
|
154
|
+
#++
|
|
155
|
+
private def normalize_snapshots(lines)
|
|
156
|
+
lines
|
|
157
|
+
end
|
|
103
158
|
##
|
|
104
159
|
# Asserts that the current screen content matches a stored plain text snapshot.
|
|
105
160
|
#
|
|
@@ -181,7 +236,7 @@ module RatatuiRuby
|
|
|
181
236
|
# Ensure your render logic is deterministic by seeding random number generators and stubbing
|
|
182
237
|
# time where necessary.
|
|
183
238
|
def assert_screen_matches(expected, msg = nil)
|
|
184
|
-
actual_lines = buffer_content
|
|
239
|
+
actual_lines = normalize_snapshots(buffer_content)
|
|
185
240
|
|
|
186
241
|
if block_given?
|
|
187
242
|
actual_lines = yield(actual_lines)
|
|
@@ -203,9 +258,6 @@ module RatatuiRuby
|
|
|
203
258
|
|
|
204
259
|
# Write with explicit mode to ensure clean write
|
|
205
260
|
File.write(snapshot_path, content_to_write, mode: "w")
|
|
206
|
-
|
|
207
|
-
# Flush filesystem buffers to ensure durability
|
|
208
|
-
File.open(snapshot_path, "r", &:fsync) if File.exist?(snapshot_path)
|
|
209
261
|
rescue => e
|
|
210
262
|
warn "Failed to write snapshot #{snapshot_path}: #{e.message}"
|
|
211
263
|
raise
|
|
@@ -269,12 +321,11 @@ module RatatuiRuby
|
|
|
269
321
|
|
|
270
322
|
actual_content = _render_buffer_with_ansi
|
|
271
323
|
|
|
324
|
+
lines = normalize_snapshots(actual_content.split("\n"))
|
|
272
325
|
if block_given?
|
|
273
|
-
lines = actual_content.split("\n")
|
|
274
|
-
# Yield lines to user block for modification (e.g. masking IDs/Times)
|
|
275
326
|
lines = yield(lines)
|
|
276
|
-
actual_content = "#{lines.join("\n")}\n"
|
|
277
327
|
end
|
|
328
|
+
actual_content = "#{lines.join("\n")}\n"
|
|
278
329
|
|
|
279
330
|
update_snapshots = ENV["UPDATE_SNAPSHOTS"] == "1" || ENV["UPDATE_SNAPSHOTS"] == "true"
|
|
280
331
|
|
|
@@ -287,9 +338,6 @@ module RatatuiRuby
|
|
|
287
338
|
|
|
288
339
|
# Write with explicit mode to ensure clean write
|
|
289
340
|
File.write(snapshot_path, actual_content, mode: "w")
|
|
290
|
-
|
|
291
|
-
# Flush filesystem buffers to ensure durability
|
|
292
|
-
File.open(snapshot_path, "r", &:fsync) if File.exist?(snapshot_path)
|
|
293
341
|
rescue => e
|
|
294
342
|
warn "Failed to write rich snapshot #{snapshot_path}: #{e.message}"
|
|
295
343
|
raise
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#--
|
|
4
|
+
# SPDX-FileCopyrightText: 2026 Kerrick Long <me@kerricklong.com>
|
|
5
|
+
# SPDX-License-Identifier: LGPL-3.0-or-later
|
|
6
|
+
#++
|
|
7
|
+
|
|
8
|
+
require "timeout"
|
|
9
|
+
|
|
10
|
+
module RatatuiRuby
|
|
11
|
+
module TestHelper
|
|
12
|
+
##
|
|
13
|
+
# Portable subprocess timeout helper.
|
|
14
|
+
module SubprocessTimeout
|
|
15
|
+
private def popen_with_timeout(env, cmd, timeout: 2)
|
|
16
|
+
output = +""
|
|
17
|
+
IO.popen(env, cmd, err: [:child, :out]) do |io|
|
|
18
|
+
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout
|
|
19
|
+
loop do
|
|
20
|
+
remaining = deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
21
|
+
break if remaining <= 0
|
|
22
|
+
break unless io.wait_readable(remaining)
|
|
23
|
+
|
|
24
|
+
chunk = io.read_nonblock(4096, exception: false)
|
|
25
|
+
break if chunk.nil? || chunk == :wait_readable
|
|
26
|
+
|
|
27
|
+
output << chunk
|
|
28
|
+
end
|
|
29
|
+
Process.kill("KILL", io.pid) rescue nil # rubocop:disable Style/RescueModifier
|
|
30
|
+
end
|
|
31
|
+
output.strip
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -12,6 +12,7 @@ require_relative "test_helper/event_injection"
|
|
|
12
12
|
require_relative "test_helper/style_assertions"
|
|
13
13
|
require_relative "test_helper/test_doubles"
|
|
14
14
|
require_relative "test_helper/global_state"
|
|
15
|
+
require_relative "test_helper/subprocess_timeout"
|
|
15
16
|
|
|
16
17
|
module RatatuiRuby
|
|
17
18
|
##
|
|
@@ -109,5 +110,6 @@ module RatatuiRuby
|
|
|
109
110
|
include StyleAssertions
|
|
110
111
|
include TestDoubles
|
|
111
112
|
include GlobalState
|
|
113
|
+
include SubprocessTimeout
|
|
112
114
|
end
|
|
113
115
|
end
|
data/lib/ratatui_ruby/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ratatui_ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kerrick Long
|
|
@@ -298,7 +298,7 @@ description: |2-
|
|
|
298
298
|
RatatuiRuby renders. For complex applications, add a framework that manages
|
|
299
299
|
state and composition.
|
|
300
300
|
|
|
301
|
-
==== Rooibos[https://
|
|
301
|
+
==== Rooibos[https://www.rooibos.run] (Framework)
|
|
302
302
|
|
|
303
303
|
Model-View-Update architecture. Inspired by Elm, Bubble Tea, and React +
|
|
304
304
|
Redux. Your UI is a pure function of state.
|
|
@@ -371,26 +371,26 @@ description: |2-
|
|
|
371
371
|
{API Reference}[https://www.ratatui-ruby.dev/docs/v0.10/],
|
|
372
372
|
{Guides}[https://www.ratatui-ruby.dev/docs/v0.10/doc/index_md.html]
|
|
373
373
|
[Ecosystem]
|
|
374
|
-
Rooibos[https://
|
|
374
|
+
Rooibos[https://www.rooibos.run],
|
|
375
375
|
{Kit}[https://sr.ht/~kerrick/ratatui_ruby/#chapter-3-the-object-path--kit] (Planned),
|
|
376
376
|
{Framework}[https://sr.ht/~kerrick/ratatui_ruby/#chapter-5-the-framework] (Planned),
|
|
377
377
|
{UI Widgets}[https://sr.ht/~kerrick/ratatui_ruby/#chapter-6-licensing] (Planned)
|
|
378
378
|
[Community]
|
|
379
|
-
{
|
|
380
|
-
{Announcements}[https://
|
|
381
|
-
{
|
|
382
|
-
{Bug Tracker}[https://
|
|
379
|
+
{Forum}[https://forum.setdef.com/c/ratatui-ruby/6],
|
|
380
|
+
{Announcements}[https://forum.setdef.com/tags/c/ratatui-ruby/6/announcement],
|
|
381
|
+
{Discussion}[https://forum.setdef.com/tags/c/ratatui-ruby/6/discussion],
|
|
382
|
+
{Bug Tracker}[https://forum.setdef.com/tags/c/ratatui-ruby/6/bug]
|
|
383
383
|
[Contribute]
|
|
384
384
|
{Contributing Guide}[https://man.sr.ht/~kerrick/ratatui_ruby/contributing.md],
|
|
385
385
|
{Code of Conduct}[https://man.sr.ht/~kerrick/ratatui_ruby/code_of_conduct.md],
|
|
386
386
|
{Project History}[https://man.sr.ht/~kerrick/ratatui_ruby/history/index.md],
|
|
387
|
-
{Pull Requests}[https://
|
|
387
|
+
{Pull Requests}[https://forum.setdef.com/tags/c/ratatui-ruby/6/patch]
|
|
388
388
|
|
|
389
389
|
|
|
390
390
|
---
|
|
391
391
|
|
|
392
392
|
[Website] https://www.ratatui-ruby.dev
|
|
393
|
-
[Source] https://
|
|
393
|
+
[Source] https://github.com/setdef/RatatuiRuby
|
|
394
394
|
[RubyGems] https://rubygems.org/gems/ratatui_ruby
|
|
395
395
|
[Upstream] https://ratatui.rs
|
|
396
396
|
[Build Status] https://builds.sr.ht/~kerrick/ratatui_ruby
|
|
@@ -535,6 +535,7 @@ files:
|
|
|
535
535
|
- lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.ansi
|
|
536
536
|
- lib/ratatui_ruby/test_helper/snapshots/styled_dataset_name.txt
|
|
537
537
|
- lib/ratatui_ruby/test_helper/style_assertions.rb
|
|
538
|
+
- lib/ratatui_ruby/test_helper/subprocess_timeout.rb
|
|
538
539
|
- lib/ratatui_ruby/test_helper/terminal.rb
|
|
539
540
|
- lib/ratatui_ruby/test_helper/test_doubles.rb
|
|
540
541
|
- lib/ratatui_ruby/text.rb
|
|
@@ -692,17 +693,17 @@ files:
|
|
|
692
693
|
- sig/ratatui_ruby/widgets/table.rbs
|
|
693
694
|
- sig/ratatui_ruby/widgets/tabs.rbs
|
|
694
695
|
- vendor/goodcop/base.yml
|
|
695
|
-
homepage: https://
|
|
696
|
+
homepage: https://www.ratatui-ruby.dev
|
|
696
697
|
licenses:
|
|
697
698
|
- LGPL-3.0-or-later
|
|
698
699
|
metadata:
|
|
699
700
|
allowed_push_host: https://rubygems.org
|
|
700
|
-
homepage_uri: https://
|
|
701
|
-
bug_tracker_uri: https://
|
|
702
|
-
changelog_uri: https://
|
|
703
|
-
mailing_list_uri: https://
|
|
704
|
-
source_code_uri: https://
|
|
705
|
-
documentation_uri: https://
|
|
701
|
+
homepage_uri: https://www.ratatui-ruby.dev
|
|
702
|
+
bug_tracker_uri: https://forum.setdef.com/tags/c/ratatui-ruby/6/bug
|
|
703
|
+
changelog_uri: https://github.com/setdef/RatatuiRuby/blob/stable/CHANGELOG.md
|
|
704
|
+
mailing_list_uri: https://forum.setdef.com/c/ratatui-ruby/6
|
|
705
|
+
source_code_uri: https://github.com/setdef/RatatuiRuby
|
|
706
|
+
documentation_uri: https://www.ratatui-ruby.dev/docs/
|
|
706
707
|
wiki_uri: https://man.sr.ht/~kerrick/ratatui_ruby/
|
|
707
708
|
funding_uri: https://opencollective.com/ratatui
|
|
708
709
|
rdoc_options: []
|