ratatui_ruby 0.1.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 +7 -0
- data/.build.yml +34 -0
- data/.pre-commit-config.yaml +9 -0
- data/.rubocop.yml +8 -0
- data/.ruby-version +1 -0
- data/AGENTS.md +119 -0
- data/CHANGELOG.md +15 -0
- data/CODE_OF_CONDUCT.md +30 -0
- data/CONTRIBUTING.md +40 -0
- data/LICENSE +15 -0
- data/LICENSES/AGPL-3.0-or-later.txt +661 -0
- data/LICENSES/BSD-2-Clause.txt +9 -0
- data/LICENSES/CC-BY-SA-4.0.txt +427 -0
- data/LICENSES/CC0-1.0.txt +121 -0
- data/LICENSES/MIT.txt +21 -0
- data/README.md +86 -0
- data/REUSE.toml +17 -0
- data/Rakefile +108 -0
- data/docs/application_testing.md +96 -0
- data/docs/contributors/design/ruby_frontend.md +100 -0
- data/docs/contributors/design/rust_backend.md +61 -0
- data/docs/contributors/design.md +11 -0
- data/docs/contributors/index.md +16 -0
- data/docs/images/examples-analytics.rb.png +0 -0
- data/docs/images/examples-box_demo.rb.png +0 -0
- data/docs/images/examples-dashboard.rb.png +0 -0
- data/docs/images/examples-login_form.rb.png +0 -0
- data/docs/images/examples-map_demo.rb.png +0 -0
- data/docs/images/examples-mouse_events.rb.png +0 -0
- data/docs/images/examples-scrollbar_demo.rb.png +0 -0
- data/docs/images/examples-stock_ticker.rb.png +0 -0
- data/docs/images/examples-system_monitor.rb.png +0 -0
- data/docs/index.md +18 -0
- data/docs/quickstart.md +126 -0
- data/examples/analytics.rb +87 -0
- data/examples/box_demo.rb +71 -0
- data/examples/dashboard.rb +72 -0
- data/examples/login_form.rb +114 -0
- data/examples/map_demo.rb +58 -0
- data/examples/mouse_events.rb +95 -0
- data/examples/scrollbar_demo.rb +75 -0
- data/examples/stock_ticker.rb +85 -0
- data/examples/system_monitor.rb +93 -0
- data/examples/test_analytics.rb +65 -0
- data/examples/test_box_demo.rb +38 -0
- data/examples/test_dashboard.rb +38 -0
- data/examples/test_login_form.rb +63 -0
- data/examples/test_map_demo.rb +100 -0
- data/examples/test_stock_ticker.rb +39 -0
- data/examples/test_system_monitor.rb +40 -0
- data/ext/ratatui_ruby/.cargo/config.toml +8 -0
- data/ext/ratatui_ruby/.gitignore +4 -0
- data/ext/ratatui_ruby/Cargo.lock +698 -0
- data/ext/ratatui_ruby/Cargo.toml +16 -0
- data/ext/ratatui_ruby/extconf.rb +12 -0
- data/ext/ratatui_ruby/src/events.rs +279 -0
- data/ext/ratatui_ruby/src/lib.rs +105 -0
- data/ext/ratatui_ruby/src/rendering.rs +31 -0
- data/ext/ratatui_ruby/src/style.rs +149 -0
- data/ext/ratatui_ruby/src/terminal.rs +131 -0
- data/ext/ratatui_ruby/src/widgets/barchart.rs +73 -0
- data/ext/ratatui_ruby/src/widgets/block.rs +12 -0
- data/ext/ratatui_ruby/src/widgets/canvas.rs +146 -0
- data/ext/ratatui_ruby/src/widgets/center.rs +81 -0
- data/ext/ratatui_ruby/src/widgets/cursor.rs +29 -0
- data/ext/ratatui_ruby/src/widgets/gauge.rs +50 -0
- data/ext/ratatui_ruby/src/widgets/layout.rs +82 -0
- data/ext/ratatui_ruby/src/widgets/linechart.rs +154 -0
- data/ext/ratatui_ruby/src/widgets/list.rs +62 -0
- data/ext/ratatui_ruby/src/widgets/mod.rs +18 -0
- data/ext/ratatui_ruby/src/widgets/overlay.rs +20 -0
- data/ext/ratatui_ruby/src/widgets/paragraph.rs +56 -0
- data/ext/ratatui_ruby/src/widgets/scrollbar.rs +68 -0
- data/ext/ratatui_ruby/src/widgets/sparkline.rs +59 -0
- data/ext/ratatui_ruby/src/widgets/table.rs +117 -0
- data/ext/ratatui_ruby/src/widgets/tabs.rs +51 -0
- data/lib/ratatui_ruby/output.rb +7 -0
- data/lib/ratatui_ruby/schema/bar_chart.rb +28 -0
- data/lib/ratatui_ruby/schema/block.rb +23 -0
- data/lib/ratatui_ruby/schema/canvas.rb +62 -0
- data/lib/ratatui_ruby/schema/center.rb +19 -0
- data/lib/ratatui_ruby/schema/constraint.rb +33 -0
- data/lib/ratatui_ruby/schema/cursor.rb +17 -0
- data/lib/ratatui_ruby/schema/gauge.rb +24 -0
- data/lib/ratatui_ruby/schema/layout.rb +22 -0
- data/lib/ratatui_ruby/schema/line_chart.rb +41 -0
- data/lib/ratatui_ruby/schema/list.rb +22 -0
- data/lib/ratatui_ruby/schema/overlay.rb +15 -0
- data/lib/ratatui_ruby/schema/paragraph.rb +37 -0
- data/lib/ratatui_ruby/schema/scrollbar.rb +33 -0
- data/lib/ratatui_ruby/schema/sparkline.rb +24 -0
- data/lib/ratatui_ruby/schema/style.rb +31 -0
- data/lib/ratatui_ruby/schema/table.rb +24 -0
- data/lib/ratatui_ruby/schema/tabs.rb +22 -0
- data/lib/ratatui_ruby/test_helper.rb +75 -0
- data/lib/ratatui_ruby/version.rb +10 -0
- data/lib/ratatui_ruby.rb +87 -0
- data/sig/ratatui_ruby/ratatui_ruby.rbs +16 -0
- data/sig/ratatui_ruby/schema/bar_chart.rbs +14 -0
- data/sig/ratatui_ruby/schema/block.rbs +11 -0
- data/sig/ratatui_ruby/schema/canvas.rbs +62 -0
- data/sig/ratatui_ruby/schema/center.rbs +11 -0
- data/sig/ratatui_ruby/schema/constraint.rbs +13 -0
- data/sig/ratatui_ruby/schema/cursor.rbs +10 -0
- data/sig/ratatui_ruby/schema/gauge.rbs +13 -0
- data/sig/ratatui_ruby/schema/layout.rbs +11 -0
- data/sig/ratatui_ruby/schema/line_chart.rbs +20 -0
- data/sig/ratatui_ruby/schema/list.rbs +11 -0
- data/sig/ratatui_ruby/schema/overlay.rbs +9 -0
- data/sig/ratatui_ruby/schema/paragraph.rbs +11 -0
- data/sig/ratatui_ruby/schema/scrollbar.rbs +20 -0
- data/sig/ratatui_ruby/schema/sparkline.rbs +12 -0
- data/sig/ratatui_ruby/schema/style.rbs +13 -0
- data/sig/ratatui_ruby/schema/table.rbs +13 -0
- data/sig/ratatui_ruby/schema/tabs.rbs +11 -0
- data/sig/ratatui_ruby/test_helper.rbs +11 -0
- data/sig/ratatui_ruby/version.rbs +6 -0
- data/vendor/goodcop/base.yml +1047 -0
- metadata +196 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "analytics"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestAnalytics < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = AnalyticsApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render_initial_state
|
|
22
|
+
with_test_terminal(50, 20) do
|
|
23
|
+
@app.render
|
|
24
|
+
|
|
25
|
+
# Check Tabs
|
|
26
|
+
assert buffer_content.any? { |line| line.include?("Revenue") }
|
|
27
|
+
assert buffer_content.any? { |line| line.include?("Traffic") }
|
|
28
|
+
assert buffer_content.any? { |line| line.include?("Errors") }
|
|
29
|
+
|
|
30
|
+
# Check initial selected tab content
|
|
31
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_navigation_right
|
|
36
|
+
inject_event("key", { code: "right" })
|
|
37
|
+
@app.handle_input
|
|
38
|
+
|
|
39
|
+
with_test_terminal(50, 20) do
|
|
40
|
+
@app.render
|
|
41
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Traffic") }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_navigation_left
|
|
46
|
+
# Move right to Traffic
|
|
47
|
+
inject_event("key", { code: "right" })
|
|
48
|
+
@app.handle_input
|
|
49
|
+
|
|
50
|
+
# Move left back to Revenue
|
|
51
|
+
inject_event("key", { code: "left" })
|
|
52
|
+
@app.handle_input
|
|
53
|
+
|
|
54
|
+
with_test_terminal(50, 20) do
|
|
55
|
+
@app.render
|
|
56
|
+
assert buffer_content.any? { |line| line.include?("Analytics: Revenue") }
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_quit
|
|
61
|
+
inject_event("key", { code: "q" })
|
|
62
|
+
status = @app.handle_input
|
|
63
|
+
assert_equal :quit, status
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "box_demo"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestBoxDemo < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = BoxDemoApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render_initial_state
|
|
22
|
+
with_test_terminal(40, 10) do
|
|
23
|
+
@app.render
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Box Demo") }
|
|
25
|
+
assert buffer_content.any? { |line| line.include?("Press Arrow Keys") }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_interaction
|
|
30
|
+
inject_event("key", { code: "up" })
|
|
31
|
+
@app.handle_input
|
|
32
|
+
|
|
33
|
+
with_test_terminal(40, 10) do
|
|
34
|
+
@app.render
|
|
35
|
+
assert buffer_content.any? { |line| line.include?("Up Pressed!") }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "dashboard"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestDashboard < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = DashboardApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render_initial_state
|
|
22
|
+
with_test_terminal(60, 20) do
|
|
23
|
+
@app.render
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Item 1") }
|
|
25
|
+
assert buffer_content.any? { |line| line.include?("You selected: Item 1") }
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_navigation
|
|
30
|
+
inject_event("key", { code: "down" })
|
|
31
|
+
@app.handle_input
|
|
32
|
+
|
|
33
|
+
with_test_terminal(60, 20) do
|
|
34
|
+
@app.render
|
|
35
|
+
assert buffer_content.any? { |line| line.include?("You selected: Item 2") }
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "login_form"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestLoginForm < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = LoginFormApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render_initial_state
|
|
22
|
+
with_test_terminal(60, 20) do
|
|
23
|
+
@app.render
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Enter Username:") }
|
|
25
|
+
# Initial cursor position check could be tricky without inspecting cursor state,
|
|
26
|
+
# but we can rely on visual cursor rendering if we had a way to check attributes,
|
|
27
|
+
# or just assume the widget logic puts it there.
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_input_handling
|
|
32
|
+
# Type 'a'
|
|
33
|
+
inject_event("key", { code: "a" })
|
|
34
|
+
@app.handle_input
|
|
35
|
+
|
|
36
|
+
with_test_terminal(60, 20) do
|
|
37
|
+
@app.render
|
|
38
|
+
assert buffer_content.any? { |line| line.include?("Enter Username: [ a ]") }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def test_popup_flow
|
|
43
|
+
# Enter username 'user'
|
|
44
|
+
%w[u s e r].each do |char|
|
|
45
|
+
inject_event("key", { code: char })
|
|
46
|
+
@app.handle_input
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Press Enter
|
|
50
|
+
inject_event("key", { code: "enter" })
|
|
51
|
+
@app.handle_input
|
|
52
|
+
|
|
53
|
+
with_test_terminal(60, 20) do
|
|
54
|
+
@app.render
|
|
55
|
+
assert buffer_content.any? { |line| line.include?("Successful!") }
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Press 'q' to quit popup/app
|
|
59
|
+
inject_event("key", { code: "q" })
|
|
60
|
+
status = @app.handle_input
|
|
61
|
+
assert_equal :quit, status
|
|
62
|
+
end
|
|
63
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "map_demo"
|
|
11
|
+
|
|
12
|
+
class TestMapDemo < Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
|
|
15
|
+
def test_map_demo_renders
|
|
16
|
+
# Use a specific terminal size to make assertions reliable
|
|
17
|
+
with_test_terminal(20, 10) do
|
|
18
|
+
view = MapDemo.view(0.0)
|
|
19
|
+
RatatuiRuby.draw(view)
|
|
20
|
+
|
|
21
|
+
expected_buffer = [
|
|
22
|
+
"┌World Map Canvas──┐",
|
|
23
|
+
"│⣀⣀⣠⣶⣶⣶⡖⣲⠂⣶⣒⣦⣤⠶⢤⣤⣄⣀│",
|
|
24
|
+
"│⠹⠓⢦ ⠻⣿⡟⠉⣿⡿⣋⡁⠁ ⣴⠿⠋│",
|
|
25
|
+
"│⢀⡀⠘⣆⣴⡏ ⢀⡟⠻⣿⣧⣀⣀⣹⠟ │",
|
|
26
|
+
"│ ⠁ ⠈⢻⠿⣄⠘⢦⡔⢚⡏⠻⣽⣿⣀⡀ │",
|
|
27
|
+
"│⠄ ⠘⡆⣸⠃ ⡇⣼⡆ ⠈⡻⢿⣻⠤│",
|
|
28
|
+
"│ ⣷⠃ ⠙⠃ ⡀ ⠓⢳⢇⡆│",
|
|
29
|
+
"│ ⢀⡀⣻ ⣀⣀⣀⣤⣁⣤⣤⣄⣀⡀│",
|
|
30
|
+
"│⠾⠿⠉⠉⠙⠛⠛⠋⠁ ⠘⠧│",
|
|
31
|
+
"└──────────────────┘",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
expected_buffer.each_with_index do |line, i|
|
|
35
|
+
assert_equal line, buffer_content[i], "Line #{i} should match"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_quit
|
|
41
|
+
# We need to use with_test_terminal because MapDemo.run calls init_terminal and draw
|
|
42
|
+
with_test_terminal(80, 24) do
|
|
43
|
+
# Inject 'q' event
|
|
44
|
+
inject_event("key", { code: "q" })
|
|
45
|
+
|
|
46
|
+
# MapDemo.run should exit immediately after polling the 'q' event
|
|
47
|
+
# We use Timeout to prevent hanging if it's not quittable
|
|
48
|
+
require "timeout"
|
|
49
|
+
Timeout.timeout(1) do
|
|
50
|
+
MapDemo.run
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_map_demo_animation
|
|
56
|
+
# Test that the animation actually happens within the run loop
|
|
57
|
+
with_test_terminal(20, 10) do
|
|
58
|
+
# We want to verify that the radius changes.
|
|
59
|
+
# We'll mock RatatuiRuby.draw to capture the views being drawn.
|
|
60
|
+
draw_calls = []
|
|
61
|
+
|
|
62
|
+
# We need to preserve the original behavior of draw if we want to see it in the test terminal,
|
|
63
|
+
# but for this test, we just want to inspect the view objects.
|
|
64
|
+
|
|
65
|
+
# Using a lambda as a mock for RatatuiRuby.draw
|
|
66
|
+
original_draw = RatatuiRuby.method(:draw)
|
|
67
|
+
RatatuiRuby.define_singleton_method(:draw) do |view|
|
|
68
|
+
draw_calls << view
|
|
69
|
+
original_draw.call(view)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
MapDemo.stub :sleep, nil do
|
|
74
|
+
# Inject some non-quitting events to let it loop
|
|
75
|
+
# radius starts at 0.0
|
|
76
|
+
# 1st loop: radius becomes 0.5, draws, polls 'up', sleeps
|
|
77
|
+
# 2nd loop: radius becomes 1.0, draws, polls 'up', sleeps
|
|
78
|
+
# 3rd loop: radius becomes 1.5, draws, polls 'q', breaks
|
|
79
|
+
inject_event("key", { code: "up" })
|
|
80
|
+
inject_event("key", { code: "up" })
|
|
81
|
+
inject_event("key", { code: "q" })
|
|
82
|
+
|
|
83
|
+
MapDemo.run
|
|
84
|
+
end
|
|
85
|
+
ensure
|
|
86
|
+
# Restore original draw method
|
|
87
|
+
RatatuiRuby.define_singleton_method(:draw, &original_draw)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
assert_operator draw_calls.size, :>=, 3
|
|
91
|
+
|
|
92
|
+
# Check that the radius in each view is increasing
|
|
93
|
+
radii = draw_calls.map { |v| v.shapes.find { |s| s.is_a?(RatatuiRuby::Circle) }.radius }
|
|
94
|
+
|
|
95
|
+
assert_equal 0.5, radii[0]
|
|
96
|
+
assert_equal 1.0, radii[1]
|
|
97
|
+
assert_equal 1.5, radii[2]
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "stock_ticker"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestStockTicker < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = StockTickerApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render
|
|
22
|
+
with_test_terminal(60, 20) do
|
|
23
|
+
@app.render
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Network Activity") }
|
|
25
|
+
assert buffer_content.any? { |line| line.include?("Stock Ticker") }
|
|
26
|
+
# It's a dynamic simulation, so exact content varies,
|
|
27
|
+
# but titles should be stable.
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def test_update
|
|
32
|
+
# Render multiple times to ensure no crash on update
|
|
33
|
+
with_test_terminal(60, 20) do
|
|
34
|
+
@app.render
|
|
35
|
+
@app.render
|
|
36
|
+
assert buffer_content.any? { |line| line.include?("Stock Ticker") }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
4
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
5
|
+
|
|
6
|
+
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
7
|
+
require "ratatui_ruby"
|
|
8
|
+
require "ratatui_ruby/test_helper"
|
|
9
|
+
require "minitest/autorun"
|
|
10
|
+
require_relative "system_monitor"
|
|
11
|
+
|
|
12
|
+
class Minitest::Test
|
|
13
|
+
include RatatuiRuby::TestHelper
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class TestSystemMonitor < Minitest::Test
|
|
17
|
+
def setup
|
|
18
|
+
@app = SystemMonitorApp.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_render_initial_state
|
|
22
|
+
with_test_terminal(60, 20) do
|
|
23
|
+
@app.render
|
|
24
|
+
assert buffer_content.any? { |line| line.include?("Processes") }
|
|
25
|
+
assert buffer_content.any? { |line| line.include?("Memory Usage") }
|
|
26
|
+
assert buffer_content.any? { |line| line.include?("50%") }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_interaction
|
|
31
|
+
# Increase percentage
|
|
32
|
+
inject_event("key", { code: "up" })
|
|
33
|
+
@app.handle_input
|
|
34
|
+
|
|
35
|
+
with_test_terminal(60, 20) do
|
|
36
|
+
@app.render
|
|
37
|
+
assert buffer_content.any? { |line| line.include?("55%") }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# SPDX-FileCopyrightText: 2025 Kerrick Long <me@kerricklong.com>
|
|
2
|
+
# SPDX-License-Identifier: AGPL-3.0-or-later
|
|
3
|
+
|
|
4
|
+
[target.aarch64-apple-darwin]
|
|
5
|
+
rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
|
|
6
|
+
|
|
7
|
+
[target.x86_64-apple-darwin]
|
|
8
|
+
rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
|