tng 0.1.4

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.

Potentially problematic release.


This version of tng might be problematic. Click here for more details.

@@ -0,0 +1,52 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-box"
4
+ require "pastel"
5
+ require "tty-screen"
6
+ require_relative "theme"
7
+
8
+ class ConfigurationDisplay
9
+ def initialize(pastel)
10
+ @pastel = pastel
11
+ @terminal_width = begin
12
+ TTY::Screen.width
13
+ rescue StandardError
14
+ 80
15
+ end
16
+ end
17
+
18
+ def display_missing_config(missing_config)
19
+ config_content = [
20
+ @pastel.public_send(Tng::UI::Theme.color(:error)).bold("Configuration Required"),
21
+ "",
22
+ @pastel.public_send(Tng::UI::Theme.color(:accent), "Missing required configuration:"),
23
+ missing_config.map do |key|
24
+ @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:bullet)} #{key}")
25
+ end.join("\n"),
26
+ "",
27
+ @pastel.public_send(Tng::UI::Theme.color(:secondary), "Quick fix:"),
28
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
29
+ "#{Tng::UI::Theme.icon(:bullet)} Edit config/initializers/tng.rb"),
30
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
31
+ "#{Tng::UI::Theme.icon(:bullet)} Set your API key and other required values"),
32
+ "",
33
+ @pastel.public_send(Tng::UI::Theme.color(:success), "Press Enter to continue after fixing"),
34
+ @pastel.public_send(Tng::UI::Theme.color(:error), "Press Ctrl+C to exit")
35
+ ].join("\n")
36
+
37
+ box_width = Tng::UI::Theme.calculate_box_width(@terminal_width)
38
+ style = Tng::UI::Theme.box_style(:error)
39
+
40
+ config_box = TTY::Box.frame(
41
+ title: { top_left: " Config Required " },
42
+ style: style[:style],
43
+ padding: style[:padding],
44
+ width: box_width
45
+ ) do
46
+ config_content
47
+ end
48
+
49
+ puts Tng::UI::Theme.center_box(config_box, box_width, @terminal_width)
50
+ puts
51
+ end
52
+ end
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+ require "tty-spinner"
5
+ require "pastel"
6
+ require "tty-screen"
7
+ require_relative "theme"
8
+
9
+ class ControllerTestFlowDisplay
10
+ def initialize(prompt, pastel)
11
+ @prompt = prompt
12
+ @pastel = pastel
13
+ @terminal_width = begin
14
+ TTY::Screen.width
15
+ rescue StandardError
16
+ 80
17
+ end
18
+ end
19
+
20
+ def select_controller(controllers)
21
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:config)} Select controller to test:")
22
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
23
+
24
+ @prompt.select(
25
+ "",
26
+ cycle: true,
27
+ per_page: 12,
28
+ filter: true,
29
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
30
+ ) do |menu|
31
+ controllers.each do |controller|
32
+ display_name = "#{controller[:name]} #{@pastel.public_send(Tng::UI::Theme.color(:muted),
33
+ "(#{controller[:path]})")}"
34
+ menu.choice display_name, controller
35
+ end
36
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
37
+ end
38
+ end
39
+
40
+ def select_test_option(controller_choice)
41
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Test Generation Options for #{controller_choice[:name]}")
42
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
43
+ puts
44
+
45
+ @prompt.select(
46
+ @pastel.public_send(Tng::UI::Theme.color(:primary), "Choose test generation type:"),
47
+ cycle: true,
48
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
49
+ ) do |menu|
50
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:success), "Generate all possible tests"),
51
+ :all_possible_tests
52
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:info), "Generate per method"), :per_method
53
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
54
+ end
55
+ end
56
+
57
+ def show_no_controllers_message
58
+ error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No controllers found in your application")}\n#{@pastel.public_send(
59
+ Tng::UI::Theme.color(:muted), "Make sure you have controllers in app/controllers/"
60
+ )}"
61
+ puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
62
+ @prompt.keypress(Tng::UI::Theme.center_text(
63
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
64
+ "Press any key to continue..."), @terminal_width
65
+ ))
66
+ end
67
+
68
+ def select_controller_method(controller, methods)
69
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test in #{controller[:name]}")
70
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
71
+
72
+ @prompt.select(
73
+ "",
74
+ cycle: true,
75
+ per_page: 10,
76
+ filter: true,
77
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
78
+ ) do |menu|
79
+ methods.each do |method|
80
+ menu.choice method[:name], method
81
+ end
82
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
83
+ end
84
+ end
85
+
86
+ def show_no_methods_message(controller)
87
+ error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No methods found in #{controller[:name]}")}\n#{@pastel.public_send(
88
+ Tng::UI::Theme.color(:muted), "Controller may be empty or have syntax errors"
89
+ )}"
90
+ puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
91
+ @prompt.keypress(Tng::UI::Theme.center_text(
92
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
93
+ "Press any key to continue..."), @terminal_width
94
+ ))
95
+ end
96
+ end
@@ -0,0 +1,44 @@
1
+ require "tty-box"
2
+ require "pastel"
3
+ require "tty-screen"
4
+ require_relative "theme"
5
+
6
+ class DisplayBanner
7
+ attr_reader :pastel, :version, :terminal_width
8
+
9
+ def initialize(pastel, version)
10
+ @pastel = pastel
11
+ @version = version
12
+ @terminal_width = begin
13
+ TTY::Screen.width
14
+ rescue StandardError
15
+ 80
16
+ end
17
+ end
18
+
19
+ def render
20
+ banner_content = [
21
+ pastel.public_send(Tng::UI::Theme.color(:secondary)).bold("Tng - LLM-Powered Rails Test Generator"),
22
+ pastel.public_send(Tng::UI::Theme.color(:muted), "Version: #{version}"),
23
+ "",
24
+ pastel.public_send(Tng::UI::Theme.color(:accent), "Generate comprehensive tests for your Rails application"),
25
+ pastel.public_send(Tng::UI::Theme.color(:muted), "Powered by LLM and static analysis")
26
+ ].join("\n")
27
+
28
+ box_width = 64
29
+ box_width = terminal_width if box_width > terminal_width
30
+ style = Tng::UI::Theme.box_style(:default)
31
+
32
+ box = TTY::Box.frame(
33
+ title: { top_left: " Tng ", bottom_right: " Ready " },
34
+ style: style[:style],
35
+ padding: style[:padding],
36
+ align: :center,
37
+ width: box_width
38
+ ) do
39
+ banner_content
40
+ end
41
+
42
+ "#{Tng::UI::Theme.center_box(box, box_width, terminal_width)}\n"
43
+ end
44
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-box"
4
+ require "pastel"
5
+ require "tty-screen"
6
+ require_relative "theme"
7
+
8
+ class GoodbyeDisplay
9
+ def initialize(pastel)
10
+ @pastel = pastel
11
+ @terminal_width = begin
12
+ TTY::Screen.width
13
+ rescue StandardError
14
+ 80
15
+ end
16
+ end
17
+
18
+ def display
19
+ box_width = Tng::UI::Theme.calculate_box_width(@terminal_width)
20
+ style = Tng::UI::Theme.box_style(:success)
21
+
22
+ goodbye_box = TTY::Box.frame(
23
+ title: { top_left: " Thank You " },
24
+ style: style[:style],
25
+ padding: style[:padding],
26
+ align: :center,
27
+ width: box_width
28
+ ) do
29
+ [
30
+ @pastel.public_send(Tng::UI::Theme.color(:success)).bold("Thanks for using Tng!"),
31
+ "",
32
+ @pastel.public_send(Tng::UI::Theme.color(:secondary), "Happy testing!"),
33
+ "",
34
+ @pastel.public_send(Tng::UI::Theme.color(:muted), "Your Rails tests are now supercharged with LLM")
35
+ ].join("\n")
36
+ end
37
+
38
+ puts Tng::UI::Theme.center_box(goodbye_box, box_width, @terminal_width)
39
+ puts
40
+ end
41
+ end
@@ -0,0 +1,97 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+ require "tty-spinner"
5
+ require "pastel"
6
+ require "tty-screen"
7
+ require_relative "theme"
8
+
9
+ class ModelTestFlowDisplay
10
+ def initialize(prompt, pastel)
11
+ @prompt = prompt
12
+ @pastel = pastel
13
+ @terminal_width = begin
14
+ TTY::Screen.width
15
+ rescue StandardError
16
+ 80
17
+ end
18
+ end
19
+
20
+ def select_model(models)
21
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:config)} Select model to test:")
22
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
23
+
24
+ @prompt.select(
25
+ "",
26
+ cycle: true,
27
+ per_page: 12,
28
+ filter: true,
29
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
30
+ ) do |menu|
31
+ models.each do |model|
32
+ display_name = "#{model[:name]} #{@pastel.public_send(Tng::UI::Theme.color(:muted), "(#{model[:path]})")}"
33
+ menu.choice display_name, model
34
+ end
35
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
36
+ end
37
+ end
38
+
39
+ def select_test_option(model_choice)
40
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Test Generation Options for #{model_choice[:name]}")
41
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
42
+ puts
43
+
44
+ @prompt.select(
45
+ @pastel.public_send(Tng::UI::Theme.color(:primary), "Choose test generation type:"),
46
+ cycle: true,
47
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
48
+ ) do |menu|
49
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:success), "Generate all possible tests"),
50
+ :all_possible_tests
51
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:info), "Generate per method"), :per_method
52
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
53
+ end
54
+ end
55
+
56
+ def show_no_models_message
57
+ puts
58
+ puts Tng::UI::Theme.center_text(
59
+ @pastel.public_send(Tng::UI::Theme.color(:warning),
60
+ "#{Tng::UI::Theme.icon(:warning)} No models found in app/models"), @terminal_width
61
+ )
62
+ puts Tng::UI::Theme.center_text(
63
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
64
+ "Make sure you're in a Rails project with models"), @terminal_width
65
+ )
66
+ puts
67
+ end
68
+
69
+ def select_model_method(model, methods)
70
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test in #{model[:name]}")
71
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
72
+
73
+ @prompt.select(
74
+ "",
75
+ cycle: true,
76
+ per_page: 10,
77
+ filter: true,
78
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
79
+ ) do |menu|
80
+ methods.each do |method|
81
+ menu.choice method[:name], method
82
+ end
83
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
84
+ end
85
+ end
86
+
87
+ def show_no_methods_message(model)
88
+ error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No methods found in #{model[:name]}")}\n#{@pastel.public_send(
89
+ Tng::UI::Theme.color(:muted), "Model may be empty or have syntax errors"
90
+ )}"
91
+ puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
92
+ @prompt.keypress(Tng::UI::Theme.center_text(
93
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
94
+ "Press any key to continue..."), @terminal_width
95
+ ))
96
+ end
97
+ end
@@ -0,0 +1,82 @@
1
+ require "tty-box"
2
+ require "pastel"
3
+ require_relative "theme"
4
+
5
+ class PostInstallBox
6
+ attr_reader :version, :pastel
7
+
8
+ def initialize(version)
9
+ @version = version
10
+ @pastel = Pastel.new
11
+ @terminal_width = begin
12
+ TTY::Screen.width
13
+ rescue StandardError
14
+ 80
15
+ end
16
+ end
17
+
18
+ def content
19
+ [
20
+ pastel.public_send(Tng::UI::Theme.color(:success)).bold("#{Tng::UI::Theme.icon(:success)} Tng installed successfully!"),
21
+ "",
22
+ pastel.public_send(Tng::UI::Theme.color(:warning)).bold("#{Tng::UI::Theme.icon(:config)} SETUP REQUIRED"),
23
+ "",
24
+ pastel.public_send(Tng::UI::Theme.color(:primary), "1. Generate configuration:"),
25
+ pastel.public_send(Tng::UI::Theme.color(:secondary), " rails g tng:install"),
26
+ "",
27
+ pastel.public_send(Tng::UI::Theme.color(:primary), "2. Edit configuration file:"),
28
+ pastel.public_send(Tng::UI::Theme.color(:secondary), " config/initializers/tng.rb"),
29
+ "",
30
+ pastel.public_send(Tng::UI::Theme.color(:primary), "3. Add your license key:"),
31
+ pastel.public_send(Tng::UI::Theme.color(:secondary), " config.api_key = 'your-license-key-here'"),
32
+ "",
33
+ pastel.public_send(Tng::UI::Theme.color(:primary),
34
+ "#{Tng::UI::Theme.icon(:config)} Check documentation for the correct authentication setup"),
35
+ "",
36
+ pastel.public_send(Tng::UI::Theme.color(:accent)).bold("#{Tng::UI::Theme.icon(:rocket)} Usage:"),
37
+ "",
38
+ pastel.public_send(Tng::UI::Theme.color(:primary), "Interactive mode:"),
39
+ pastel.public_send(Tng::UI::Theme.color(:success),
40
+ "#{Tng::UI::Theme.icon(:bullet)} bundle exec tng") + pastel.public_send(Tng::UI::Theme.color(:muted),
41
+ " - Full interactive CLI"),
42
+ "",
43
+ pastel.public_send(Tng::UI::Theme.color(:primary), "Direct generation:"),
44
+ pastel.public_send(Tng::UI::Theme.color(:success),
45
+ "#{Tng::UI::Theme.icon(:bullet)} bundle exec tng -t c -f ping") + pastel.public_send(Tng::UI::Theme.color(:muted),
46
+ " - Short"),
47
+ pastel.public_send(Tng::UI::Theme.color(:success),
48
+ "#{Tng::UI::Theme.icon(:bullet)} bundle exec tng -t=c f=ping") + pastel.public_send(Tng::UI::Theme.color(:muted),
49
+ " - Mixed"),
50
+ pastel.public_send(Tng::UI::Theme.color(:success),
51
+ "#{Tng::UI::Theme.icon(:bullet)} bundle exec tng --type=controller --file=ping"),
52
+ "",
53
+ pastel.public_send(Tng::UI::Theme.color(:primary), "Help:"),
54
+ pastel.public_send(Tng::UI::Theme.color(:success),
55
+ "#{Tng::UI::Theme.icon(:bullet)} bundle exec tng --help") + pastel.public_send(Tng::UI::Theme.color(:muted),
56
+ " - Show all options"),
57
+ "",
58
+ pastel.public_send(Tng::UI::Theme.color(:muted),
59
+ "#{Tng::UI::Theme.icon(:lightbulb)} Use -t c for controller, -t m for model")
60
+ ].join("\n")
61
+ end
62
+
63
+ def render
64
+ # Use a reasonable width that won't cause issues
65
+ box_width = [@terminal_width, 70].min
66
+
67
+ style = Tng::UI::Theme.box_style(:default)
68
+ TTY::Box.frame(
69
+ title: { top_left: " TNG ", bottom_right: " v#{@version} " },
70
+ style: style[:style],
71
+ padding: style[:padding],
72
+ align: :left,
73
+ width: box_width
74
+ ) do
75
+ content
76
+ end
77
+ rescue StandardError
78
+ "TNG v#{@version} installed successfully!\n" +
79
+ "Run 'rails g tng:install' to get started.\n" +
80
+ "Use 'bundle exec tng --help' for usage information."
81
+ end
82
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+ require "tty-spinner"
5
+ require "pastel"
6
+ require "tty-screen"
7
+ require_relative "theme"
8
+
9
+ class ServiceTestFlowDisplay
10
+ def initialize(prompt, pastel)
11
+ @prompt = prompt
12
+ @pastel = pastel
13
+ @terminal_width = begin
14
+ TTY::Screen.width
15
+ rescue StandardError
16
+ 80
17
+ end
18
+ end
19
+
20
+ def select_service(services)
21
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:config)} Select service to test:")
22
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
23
+
24
+ @prompt.select(
25
+ "",
26
+ cycle: true,
27
+ per_page: 12,
28
+ filter: true,
29
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
30
+ ) do |menu|
31
+ services.each do |service|
32
+ display_name = "#{service[:name]} #{@pastel.public_send(Tng::UI::Theme.color(:muted), "(#{service[:path]})")}"
33
+ menu.choice display_name, service
34
+ end
35
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
36
+ end
37
+ end
38
+
39
+ def select_test_option(service_choice)
40
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Test Generation Options for #{service_choice[:name]}")
41
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
42
+ puts
43
+
44
+ @prompt.select(
45
+ @pastel.public_send(Tng::UI::Theme.color(:primary), "Choose test generation type:"),
46
+ cycle: true,
47
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
48
+ ) do |menu|
49
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:success), "Generate all possible tests"),
50
+ :all_possible_tests
51
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:info), "Generate per method"), :per_method
52
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
53
+ end
54
+ end
55
+
56
+ def show_no_services_message
57
+ error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No services found in your application")}\n#{@pastel.public_send(
58
+ Tng::UI::Theme.color(:muted), "Make sure you have services in app/services/ or app/service/"
59
+ )}"
60
+ puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
61
+ @prompt.keypress(Tng::UI::Theme.center_text(
62
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
63
+ "Press any key to continue..."), @terminal_width
64
+ ))
65
+ end
66
+
67
+ def select_service_method(service, methods)
68
+ header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test for #{service[:name]}")
69
+ puts Tng::UI::Theme.center_text(header, @terminal_width)
70
+
71
+ @prompt.select(
72
+ "",
73
+ cycle: true,
74
+ per_page: 12,
75
+ filter: true,
76
+ symbols: { marker: Tng::UI::Theme.icon(:marker) }
77
+ ) do |menu|
78
+ methods.each do |method|
79
+ menu.choice "#{method[:name]}", method
80
+ end
81
+ menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
82
+ end
83
+ end
84
+
85
+ def show_no_methods_message(service)
86
+ error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No methods found in #{service[:name]}")}\n#{@pastel.public_send(
87
+ Tng::UI::Theme.color(:muted), "The service might not have any public methods or could not be analyzed."
88
+ )}"
89
+ puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
90
+ @prompt.keypress(Tng::UI::Theme.center_text(
91
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
92
+ "Press any key to continue..."), @terminal_width
93
+ ))
94
+ end
95
+ end
@@ -0,0 +1,124 @@
1
+ require "tty-box"
2
+ require "pastel"
3
+ require "tty-screen"
4
+ require_relative "theme"
5
+
6
+ class ShowHelp
7
+ attr_reader :pastel
8
+
9
+ def initialize(pastel, version)
10
+ @pastel = pastel
11
+ @version = version
12
+ @terminal_width = begin
13
+ TTY::Screen.width
14
+ rescue StandardError
15
+ 80
16
+ end
17
+ end
18
+
19
+ def content
20
+ [
21
+ @pastel.public_send(Tng::UI::Theme.color(:secondary)).bold("TNG - LLM-Powered Rails Test Generator"),
22
+ @pastel.public_send(Tng::UI::Theme.color(:muted), "Version: #{@version}"),
23
+ "",
24
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Usage:"),
25
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
26
+ " bundle exec tng") + @pastel.public_send(Tng::UI::Theme.color(:muted),
27
+ " # Interactive mode"),
28
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
29
+ " bundle exec tng --type=TYPE --file=FILE") + @pastel.public_send(
30
+ Tng::UI::Theme.color(:muted), " # Direct mode"
31
+ ),
32
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
33
+ " bundle exec tng -t TYPE -f FILE") + @pastel.public_send(Tng::UI::Theme.color(:muted),
34
+ " # Short aliases"),
35
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
36
+ " bundle exec tng -t=TYPE f=FILE") + @pastel.public_send(Tng::UI::Theme.color(:muted),
37
+ " # Mixed format"),
38
+ "",
39
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Examples:"),
40
+ @pastel.public_send(Tng::UI::Theme.color(:success),
41
+ " bundle exec tng -t c -f ping") + @pastel.public_send(Tng::UI::Theme.color(:muted),
42
+ " # Controller test"),
43
+ @pastel.public_send(Tng::UI::Theme.color(:success),
44
+ " bundle exec tng -t=c f=ping") + @pastel.public_send(Tng::UI::Theme.color(:muted),
45
+ " # Mixed format"),
46
+ @pastel.public_send(Tng::UI::Theme.color(:success),
47
+ " bundle exec tng -t m -f user") + @pastel.public_send(Tng::UI::Theme.color(:muted),
48
+ " # Model test"),
49
+ @pastel.public_send(Tng::UI::Theme.color(:success),
50
+ " bundle exec tng --type=controller --file=users_controller"),
51
+ @pastel.public_send(Tng::UI::Theme.color(:success),
52
+ " bundle exec tng -t c -f \"admin/users_controller\"") + @pastel.public_send(Tng::UI::Theme.color(:muted),
53
+ " # Namespaced"),
54
+ "",
55
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Options:"),
56
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
57
+ " -t, --type=TYPE") + @pastel.public_send(Tng::UI::Theme.color(:muted),
58
+ " Test type (controller, model)"),
59
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
60
+ " -f, --file=FILE") + @pastel.public_send(Tng::UI::Theme.color(:muted),
61
+ " File name (without .rb extension)"),
62
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
63
+ " -m, --method=METHOD") + @pastel.public_send(Tng::UI::Theme.color(:muted),
64
+ " Method name (for per-method tests)"),
65
+ @pastel.public_send(Tng::UI::Theme.color(:primary),
66
+ " -h, --help") + @pastel.public_send(Tng::UI::Theme.color(:muted),
67
+ " Show this help message"),
68
+ "",
69
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Type Aliases:"),
70
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
71
+ " #{Tng::UI::Theme.icon(:bullet)} Controllers: ") + @pastel.public_send(Tng::UI::Theme.color(:secondary),
72
+ "c, controller"),
73
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
74
+ " #{Tng::UI::Theme.icon(:bullet)} Models: ") + @pastel.public_send(
75
+ Tng::UI::Theme.color(:secondary), "m, mo, model"
76
+ ),
77
+ "",
78
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("File Format:"),
79
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
80
+ " #{Tng::UI::Theme.icon(:bullet)} Controllers: ") + @pastel.public_send(Tng::UI::Theme.color(:success),
81
+ "users_controller, api/v1/posts_controller"),
82
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
83
+ " #{Tng::UI::Theme.icon(:bullet)} Models: ") + @pastel.public_send(
84
+ Tng::UI::Theme.color(:success), "user, blog/post"
85
+ ),
86
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
87
+ " #{Tng::UI::Theme.icon(:bullet)} Don't include .rb extension"),
88
+ "",
89
+ @pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Pro Tips:"),
90
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
91
+ " #{Tng::UI::Theme.icon(:bullet)} Mix formats: ") + @pastel.public_send(Tng::UI::Theme.color(:secondary),
92
+ "-t=c f=ping") + @pastel.public_send(
93
+ Tng::UI::Theme.color(:muted), " works perfectly"
94
+ ),
95
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
96
+ " #{Tng::UI::Theme.icon(:bullet)} Use filtering in interactive mode for large projects"),
97
+ @pastel.public_send(Tng::UI::Theme.color(:muted),
98
+ " #{Tng::UI::Theme.icon(:bullet)} All formats are equivalent - use what feels natural"),
99
+ "",
100
+ @pastel.public_send(Tng::UI::Theme.color(:secondary)).bold("Happy testing! ") + @pastel.public_send(
101
+ Tng::UI::Theme.color(:accent), "★"
102
+ )
103
+ ].join("\n")
104
+ end
105
+
106
+ def render
107
+ # Use a reasonable width that matches other UI components
108
+ box_width = Tng::UI::Theme.calculate_box_width(@terminal_width)
109
+ box_width = [box_width, 80].min # Allow wider for help content
110
+ style = Tng::UI::Theme.box_style(:default)
111
+
112
+ box = TTY::Box.frame(
113
+ title: { top_left: " TNG Help ", bottom_right: " v#{@version} " },
114
+ style: style[:style],
115
+ padding: style[:padding],
116
+ align: :left,
117
+ width: box_width
118
+ ) do
119
+ content
120
+ end
121
+
122
+ Tng::UI::Theme.center_box(box, box_width, @terminal_width)
123
+ end
124
+ end