tng 0.3.0 → 0.3.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/Rakefile +20 -43
- data/bin/tng +264 -558
- data/binaries/go-ui-darwin-amd64 +0 -0
- data/binaries/go-ui-darwin-arm64 +0 -0
- data/binaries/go-ui-linux-amd64 +0 -0
- data/binaries/go-ui-linux-arm64 +0 -0
- data/binaries/tng-darwin-arm64.bundle +0 -0
- data/binaries/tng-linux-arm64.so +0 -0
- data/binaries/tng-linux-x86_64.so +0 -0
- data/lib/tng/api/http_client.rb +19 -0
- data/lib/tng/services/test_generator.rb +114 -81
- data/lib/tng/services/testng.rb +2 -8
- data/lib/tng/ui/go_ui_session.rb +406 -0
- data/lib/tng/utils.rb +3 -30
- data/lib/tng/version.rb +1 -1
- data/lib/tng.rb +24 -11
- data/tng.gemspec +4 -9
- metadata +55 -126
- data/binaries/tng.bundle +0 -0
- data/binaries/tng.so +0 -0
- data/lib/tng/ui/about_display.rb +0 -66
- data/lib/tng/ui/authentication_warning_display.rb +0 -122
- data/lib/tng/ui/configuration_display.rb +0 -52
- data/lib/tng/ui/controller_test_flow_display.rb +0 -79
- data/lib/tng/ui/display_banner.rb +0 -44
- data/lib/tng/ui/goodbye_display.rb +0 -41
- data/lib/tng/ui/model_test_flow_display.rb +0 -80
- data/lib/tng/ui/other_test_flow_display.rb +0 -78
- data/lib/tng/ui/service_test_flow_display.rb +0 -78
- data/lib/tng/ui/show_help.rb +0 -78
- data/lib/tng/ui/system_status_display.rb +0 -128
- data/lib/tng/ui/user_stats_display.rb +0 -160
|
@@ -1,80 +0,0 @@
|
|
|
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 show_no_models_message
|
|
40
|
-
puts
|
|
41
|
-
puts Tng::UI::Theme.center_text(
|
|
42
|
-
@pastel.public_send(Tng::UI::Theme.color(:warning),
|
|
43
|
-
"#{Tng::UI::Theme.icon(:warning)} No models found in app/models"), @terminal_width
|
|
44
|
-
)
|
|
45
|
-
puts Tng::UI::Theme.center_text(
|
|
46
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
47
|
-
"Make sure you're in a Rails project with models"), @terminal_width
|
|
48
|
-
)
|
|
49
|
-
puts
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def select_model_method(model, methods)
|
|
53
|
-
header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test in #{model[:name]}")
|
|
54
|
-
puts Tng::UI::Theme.center_text(header, @terminal_width)
|
|
55
|
-
|
|
56
|
-
@prompt.select(
|
|
57
|
-
"",
|
|
58
|
-
cycle: true,
|
|
59
|
-
per_page: 10,
|
|
60
|
-
filter: true,
|
|
61
|
-
symbols: { marker: Tng::UI::Theme.icon(:marker) }
|
|
62
|
-
) do |menu|
|
|
63
|
-
methods.each do |method|
|
|
64
|
-
menu.choice method[:name], method
|
|
65
|
-
end
|
|
66
|
-
menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def show_no_methods_message(model)
|
|
71
|
-
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(
|
|
72
|
-
Tng::UI::Theme.color(:muted), "Model may be empty or have syntax errors"
|
|
73
|
-
)}"
|
|
74
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
75
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
76
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
77
|
-
"Press any key to continue..."), @terminal_width
|
|
78
|
-
))
|
|
79
|
-
end
|
|
80
|
-
end
|
|
@@ -1,78 +0,0 @@
|
|
|
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 OtherTestFlowDisplay
|
|
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_other_file(other_files)
|
|
21
|
-
header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:config)} Select file 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
|
-
other_files.each do |file|
|
|
32
|
-
display_name = "#{file[:name]} #{@pastel.public_send(Tng::UI::Theme.color(:muted), "(#{file[:path]})")}"
|
|
33
|
-
menu.choice display_name, file
|
|
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 show_no_other_files_message
|
|
40
|
-
error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No other files found in your application")}\n#{@pastel.public_send(
|
|
41
|
-
Tng::UI::Theme.color(:muted), "Make sure you have files in supported directories (app/jobs, app/helpers, lib/, app/policies, app/presenters, app/mailers, app/graphql, etc.)"
|
|
42
|
-
)}"
|
|
43
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
44
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
45
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
46
|
-
"Press any key to continue..."), @terminal_width
|
|
47
|
-
))
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def select_other_method(other_file, methods)
|
|
51
|
-
header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test in #{other_file[:name]}")
|
|
52
|
-
puts Tng::UI::Theme.center_text(header, @terminal_width)
|
|
53
|
-
|
|
54
|
-
@prompt.select(
|
|
55
|
-
"",
|
|
56
|
-
cycle: true,
|
|
57
|
-
per_page: 10,
|
|
58
|
-
filter: true,
|
|
59
|
-
symbols: { marker: Tng::UI::Theme.icon(:marker) }
|
|
60
|
-
) do |menu|
|
|
61
|
-
methods.each do |method|
|
|
62
|
-
menu.choice method[:name], method
|
|
63
|
-
end
|
|
64
|
-
menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def show_no_methods_message(other_file)
|
|
69
|
-
error_msg = "#{@pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} No methods found in #{other_file[:name]}")}\n#{@pastel.public_send(
|
|
70
|
-
Tng::UI::Theme.color(:muted), "File may be empty or have syntax errors"
|
|
71
|
-
)}"
|
|
72
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
73
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
74
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
75
|
-
"Press any key to continue..."), @terminal_width
|
|
76
|
-
))
|
|
77
|
-
end
|
|
78
|
-
end
|
|
@@ -1,78 +0,0 @@
|
|
|
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 show_no_services_message
|
|
40
|
-
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(
|
|
41
|
-
Tng::UI::Theme.color(:muted), "Make sure you have services in app/services/ or app/service/"
|
|
42
|
-
)}"
|
|
43
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
44
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
45
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
46
|
-
"Press any key to continue..."), @terminal_width
|
|
47
|
-
))
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def select_service_method(service, methods)
|
|
51
|
-
header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:rocket)} Select method to test for #{service[:name]}")
|
|
52
|
-
puts Tng::UI::Theme.center_text(header, @terminal_width)
|
|
53
|
-
|
|
54
|
-
@prompt.select(
|
|
55
|
-
"",
|
|
56
|
-
cycle: true,
|
|
57
|
-
per_page: 12,
|
|
58
|
-
filter: true,
|
|
59
|
-
symbols: { marker: Tng::UI::Theme.icon(:marker) }
|
|
60
|
-
) do |menu|
|
|
61
|
-
methods.each do |method|
|
|
62
|
-
menu.choice "#{method[:name]}", method
|
|
63
|
-
end
|
|
64
|
-
menu.choice @pastel.public_send(Tng::UI::Theme.color(:secondary), "#{Tng::UI::Theme.icon(:back)} Back"), :back
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def show_no_methods_message(service)
|
|
69
|
-
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(
|
|
70
|
-
Tng::UI::Theme.color(:muted), "The service might not have any public methods or could not be analyzed."
|
|
71
|
-
)}"
|
|
72
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
73
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
74
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
75
|
-
"Press any key to continue..."), @terminal_width
|
|
76
|
-
))
|
|
77
|
-
end
|
|
78
|
-
end
|
data/lib/tng/ui/show_help.rb
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
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 only"),
|
|
28
|
-
"",
|
|
29
|
-
@pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Features:"),
|
|
30
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
31
|
-
" #{Tng::UI::Theme.icon(:bullet)} Controllers, Models, Services"),
|
|
32
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
33
|
-
" #{Tng::UI::Theme.icon(:bullet)} 17+ other file types (Jobs, Helpers, Lib, Policies, Presenters, Mailers, GraphQL, etc.)"),
|
|
34
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
35
|
-
" #{Tng::UI::Theme.icon(:bullet)} Per-method test generation"),
|
|
36
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
37
|
-
" #{Tng::UI::Theme.icon(:bullet)} Searchable method lists"),
|
|
38
|
-
"",
|
|
39
|
-
@pastel.public_send(Tng::UI::Theme.color(:accent)).bold("Options:"),
|
|
40
|
-
@pastel.public_send(Tng::UI::Theme.color(:primary),
|
|
41
|
-
" -h, --help") + @pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
42
|
-
" Show this help message"),
|
|
43
|
-
"",
|
|
44
|
-
@pastel.public_send(Tng::UI::Theme.color(:accent)).bold("How to Use:"),
|
|
45
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
46
|
-
" #{Tng::UI::Theme.icon(:bullet)} Run 'bundle exec tng' to start the interactive interface"),
|
|
47
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
48
|
-
" #{Tng::UI::Theme.icon(:bullet)} Select Controller, Model, Service, or Other to test"),
|
|
49
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
50
|
-
" #{Tng::UI::Theme.icon(:bullet)} Choose a specific method from the list"),
|
|
51
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
52
|
-
" #{Tng::UI::Theme.icon(:bullet)} Use search/filter to find methods quickly"),
|
|
53
|
-
"",
|
|
54
|
-
@pastel.public_send(Tng::UI::Theme.color(:secondary)).bold("Happy testing! ") + @pastel.public_send(
|
|
55
|
-
Tng::UI::Theme.color(:accent), "★"
|
|
56
|
-
)
|
|
57
|
-
].join("\n")
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def render
|
|
61
|
-
# Use a reasonable width that matches other UI components
|
|
62
|
-
box_width = Tng::UI::Theme.calculate_box_width(@terminal_width)
|
|
63
|
-
box_width = [box_width, 80].min # Allow wider for help content
|
|
64
|
-
style = Tng::UI::Theme.box_style(:default)
|
|
65
|
-
|
|
66
|
-
box = TTY::Box.frame(
|
|
67
|
-
title: { top_left: " TNG Help ", bottom_right: " v#{@version} " },
|
|
68
|
-
style: style[:style],
|
|
69
|
-
padding: style[:padding],
|
|
70
|
-
align: :left,
|
|
71
|
-
width: box_width
|
|
72
|
-
) do
|
|
73
|
-
content
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
Tng::UI::Theme.center_box(box, box_width, @terminal_width)
|
|
77
|
-
end
|
|
78
|
-
end
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "pastel"
|
|
4
|
-
require_relative "theme"
|
|
5
|
-
|
|
6
|
-
class SystemStatusDisplay
|
|
7
|
-
def initialize(pastel, args)
|
|
8
|
-
@pastel = pastel
|
|
9
|
-
@args = args
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def display(status)
|
|
13
|
-
case status[:status]
|
|
14
|
-
when :ok
|
|
15
|
-
unless @args[:type] && @args[:file]
|
|
16
|
-
puts @pastel.public_send(Tng::UI::Theme.color(:success),
|
|
17
|
-
"#{Tng::UI::Theme.icon(:success)} System operational")
|
|
18
|
-
end
|
|
19
|
-
true
|
|
20
|
-
when :version_mismatch
|
|
21
|
-
display_status_message(
|
|
22
|
-
title: "Version Mismatch",
|
|
23
|
-
icon: Tng::UI::Theme.icon(:error),
|
|
24
|
-
color: Tng::UI::Theme.color(:error),
|
|
25
|
-
content: [
|
|
26
|
-
"Your gem version: #{status[:gem_version]}",
|
|
27
|
-
"Required version: #{status[:current_version]}",
|
|
28
|
-
"",
|
|
29
|
-
"Quick fix:",
|
|
30
|
-
"• gem update tng",
|
|
31
|
-
"• bundle update tng"
|
|
32
|
-
]
|
|
33
|
-
)
|
|
34
|
-
false
|
|
35
|
-
when :base_url_mismatch
|
|
36
|
-
display_status_message(
|
|
37
|
-
title: "URL Mismatch",
|
|
38
|
-
icon: Tng::UI::Theme.icon(:error),
|
|
39
|
-
color: Tng::UI::Theme.color(:error),
|
|
40
|
-
content: [
|
|
41
|
-
"Your URL: #{status[:user_base_url]}",
|
|
42
|
-
"Server URL: #{status[:server_base_url]}",
|
|
43
|
-
"",
|
|
44
|
-
"Quick fix:",
|
|
45
|
-
"• Edit config/initializers/tng.rb",
|
|
46
|
-
"• Set: config.base_url = '#{status[:server_base_url]}'"
|
|
47
|
-
]
|
|
48
|
-
)
|
|
49
|
-
false
|
|
50
|
-
when :service_down
|
|
51
|
-
display_status_message(
|
|
52
|
-
title: "Service Unavailable",
|
|
53
|
-
icon: Tng::UI::Theme.icon(:error),
|
|
54
|
-
color: Tng::UI::Theme.color(:error),
|
|
55
|
-
content: [
|
|
56
|
-
status[:message] || "TNG service is currently down",
|
|
57
|
-
"",
|
|
58
|
-
"Please try again later or contact support"
|
|
59
|
-
]
|
|
60
|
-
)
|
|
61
|
-
false
|
|
62
|
-
when :error
|
|
63
|
-
display_status_message(
|
|
64
|
-
title: "Connection Error",
|
|
65
|
-
icon: Tng::UI::Theme.icon(:error),
|
|
66
|
-
color: Tng::UI::Theme.color(:error),
|
|
67
|
-
content: [
|
|
68
|
-
status[:message] || "Unable to connect to TNG service",
|
|
69
|
-
"",
|
|
70
|
-
"Please check your internet connection and try again"
|
|
71
|
-
]
|
|
72
|
-
)
|
|
73
|
-
false
|
|
74
|
-
else
|
|
75
|
-
display_status_message(
|
|
76
|
-
title: "Unknown Error",
|
|
77
|
-
icon: Tng::UI::Theme.icon(:error),
|
|
78
|
-
color: Tng::UI::Theme.color(:error),
|
|
79
|
-
content: [status[:message] || "An unknown error occurred"]
|
|
80
|
-
)
|
|
81
|
-
false
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
private
|
|
86
|
-
|
|
87
|
-
def display_status_message(title:, icon:, color:, content:)
|
|
88
|
-
require "tty-box"
|
|
89
|
-
require "tty-screen"
|
|
90
|
-
|
|
91
|
-
terminal_width = begin
|
|
92
|
-
TTY::Screen.width
|
|
93
|
-
rescue StandardError
|
|
94
|
-
80
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
formatted_content = content.map do |line|
|
|
98
|
-
case line
|
|
99
|
-
when /^•/
|
|
100
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted), line)
|
|
101
|
-
when /^Quick fix:/
|
|
102
|
-
@pastel.public_send(Tng::UI::Theme.color(:secondary), line)
|
|
103
|
-
when ""
|
|
104
|
-
line
|
|
105
|
-
else
|
|
106
|
-
@pastel.public_send(Tng::UI::Theme.color(:warning), line)
|
|
107
|
-
end
|
|
108
|
-
end.join("\n")
|
|
109
|
-
|
|
110
|
-
box_width = Tng::UI::Theme.calculate_box_width(terminal_width)
|
|
111
|
-
|
|
112
|
-
status_box = TTY::Box.frame(
|
|
113
|
-
title: { top_left: " #{title} " },
|
|
114
|
-
style: {
|
|
115
|
-
fg: :bright_white,
|
|
116
|
-
border: { fg: color },
|
|
117
|
-
title: { fg: color == Tng::UI::Theme.color(:error) ? :bright_red : color }
|
|
118
|
-
},
|
|
119
|
-
padding: [1, 2],
|
|
120
|
-
width: box_width
|
|
121
|
-
) do
|
|
122
|
-
formatted_content
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
puts Tng::UI::Theme.center_box(status_box, box_width, terminal_width)
|
|
126
|
-
puts
|
|
127
|
-
end
|
|
128
|
-
end
|
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "tty-box"
|
|
4
|
-
require "tty-progressbar"
|
|
5
|
-
require "pastel"
|
|
6
|
-
require "tty-screen"
|
|
7
|
-
require_relative "theme"
|
|
8
|
-
|
|
9
|
-
class UserStatsDisplay
|
|
10
|
-
def initialize(pastel, prompt)
|
|
11
|
-
@pastel = pastel
|
|
12
|
-
@prompt = prompt
|
|
13
|
-
@terminal_width = begin
|
|
14
|
-
TTY::Screen.width
|
|
15
|
-
rescue StandardError
|
|
16
|
-
80
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def display(stats_data)
|
|
21
|
-
header = @pastel.public_send(Tng::UI::Theme.color(:primary)).bold("#{Tng::UI::Theme.icon(:stats)} User Statistics")
|
|
22
|
-
puts Tng::UI::Theme.center_text(header, @terminal_width)
|
|
23
|
-
|
|
24
|
-
if stats_data
|
|
25
|
-
display_stats_box(stats_data)
|
|
26
|
-
display_usage_progress(stats_data)
|
|
27
|
-
display_usage_info(stats_data)
|
|
28
|
-
else
|
|
29
|
-
display_error
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
puts
|
|
33
|
-
tip_msg = @pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
34
|
-
"#{Tng::UI::Theme.icon(:lightbulb)} Tip: Contact support if you need more test generations")
|
|
35
|
-
puts Tng::UI::Theme.center_text(tip_msg, @terminal_width)
|
|
36
|
-
@prompt.keypress(Tng::UI::Theme.center_text(
|
|
37
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
38
|
-
"Press any key to continue..."), @terminal_width
|
|
39
|
-
))
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def display_stats_box(stats_data)
|
|
43
|
-
stats_content = [
|
|
44
|
-
@pastel.public_send(Tng::UI::Theme.color(:secondary)).bold("Account Information"),
|
|
45
|
-
"",
|
|
46
|
-
@pastel.public_send(Tng::UI::Theme.color(:primary), "Test Runs: ") + @pastel.public_send(Tng::UI::Theme.color(:success)).bold(stats_data["runs"].to_s),
|
|
47
|
-
@pastel.public_send(Tng::UI::Theme.color(:primary), "Max Runs: ") + @pastel.public_send(Tng::UI::Theme.color(:warning)).bold(stats_data["max_runs"].to_s),
|
|
48
|
-
@pastel.public_send(Tng::UI::Theme.color(:primary),
|
|
49
|
-
"Gem Version: ") + @pastel.public_send(Tng::UI::Theme.color(:accent),
|
|
50
|
-
stats_data["gem_version"] || "N/A"),
|
|
51
|
-
"",
|
|
52
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted), "Request ID: #{stats_data["request_id"]}")
|
|
53
|
-
].join("\n")
|
|
54
|
-
|
|
55
|
-
box_width = Tng::UI::Theme.calculate_box_width(@terminal_width)
|
|
56
|
-
style = Tng::UI::Theme.box_style(:success)
|
|
57
|
-
|
|
58
|
-
box = TTY::Box.frame(
|
|
59
|
-
title: { top_left: " Your TNG Stats " },
|
|
60
|
-
style: style[:style],
|
|
61
|
-
padding: style[:padding],
|
|
62
|
-
align: :left,
|
|
63
|
-
width: box_width
|
|
64
|
-
) { stats_content }
|
|
65
|
-
|
|
66
|
-
puts Tng::UI::Theme.center_box(box, box_width, @terminal_width)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def display_usage_progress(stats_data)
|
|
70
|
-
runs = stats_data["runs"]
|
|
71
|
-
max_runs = stats_data["max_runs"]
|
|
72
|
-
|
|
73
|
-
usage_percent = max_runs > 0 ? (runs.to_f / max_runs * 100).round(1) : 0
|
|
74
|
-
|
|
75
|
-
bar_color = determine_bar_color(usage_percent)
|
|
76
|
-
|
|
77
|
-
puts
|
|
78
|
-
puts Tng::UI::Theme.center_text(@pastel.public_send(Tng::UI::Theme.color(:primary)).bold("Usage Overview"),
|
|
79
|
-
@terminal_width)
|
|
80
|
-
puts
|
|
81
|
-
|
|
82
|
-
progress_width = 40
|
|
83
|
-
padding = (@terminal_width - progress_width - 20) / 2
|
|
84
|
-
padding = 0 if padding.negative?
|
|
85
|
-
|
|
86
|
-
bar_format = "#{" " * padding}Usage: [:bar] :percent (:current/:total)"
|
|
87
|
-
|
|
88
|
-
bar = TTY::ProgressBar.new(bar_format,
|
|
89
|
-
total: max_runs,
|
|
90
|
-
width: progress_width,
|
|
91
|
-
complete: bar_color,
|
|
92
|
-
incomplete: @pastel.public_send(Tng::UI::Theme.color(:muted), "░"),
|
|
93
|
-
head: bar_color)
|
|
94
|
-
|
|
95
|
-
current_progress = 0
|
|
96
|
-
while current_progress < runs
|
|
97
|
-
step = [runs / 10, 1].max
|
|
98
|
-
current_progress = [current_progress + step, runs].min
|
|
99
|
-
bar.current = current_progress
|
|
100
|
-
bar.render
|
|
101
|
-
sleep(0.05) if runs > 10
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
bar.current = runs
|
|
105
|
-
bar.render
|
|
106
|
-
|
|
107
|
-
puts
|
|
108
|
-
|
|
109
|
-
status_msg = case usage_percent
|
|
110
|
-
when 0..50
|
|
111
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
112
|
-
"#{Tng::UI::Theme.icon(:success)} Good usage - plenty of runs remaining")
|
|
113
|
-
when 51..80
|
|
114
|
-
@pastel.public_send(Tng::UI::Theme.color(:warning),
|
|
115
|
-
"#{Tng::UI::Theme.icon(:warning)} Moderate usage - consider monitoring")
|
|
116
|
-
when 81..95
|
|
117
|
-
@pastel.public_send(Tng::UI::Theme.color(:info),
|
|
118
|
-
"#{Tng::UI::Theme.icon(:warning)} High usage - approaching limit")
|
|
119
|
-
else
|
|
120
|
-
@pastel.public_send(Tng::UI::Theme.color(:error),
|
|
121
|
-
"#{Tng::UI::Theme.icon(:error)} Limit reached - contact support for more runs")
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
puts Tng::UI::Theme.center_text(status_msg, @terminal_width)
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
def determine_bar_color(usage_percent)
|
|
128
|
-
case usage_percent
|
|
129
|
-
when 0..50
|
|
130
|
-
@pastel.public_send(Tng::UI::Theme.color(:success), "█")
|
|
131
|
-
when 51..80
|
|
132
|
-
@pastel.public_send(Tng::UI::Theme.color(:warning), "█")
|
|
133
|
-
when 81..95
|
|
134
|
-
@pastel.public_send(Tng::UI::Theme.color(:info), "█")
|
|
135
|
-
else
|
|
136
|
-
@pastel.public_send(Tng::UI::Theme.color(:error), "█")
|
|
137
|
-
end
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
def display_usage_info(stats_data)
|
|
141
|
-
usage_remaining = stats_data["max_runs"] - stats_data["runs"]
|
|
142
|
-
usage_msg = if usage_remaining.positive?
|
|
143
|
-
@pastel.public_send(Tng::UI::Theme.color(:success),
|
|
144
|
-
"#{Tng::UI::Theme.icon(:success)} You have #{usage_remaining} test generations remaining")
|
|
145
|
-
else
|
|
146
|
-
@pastel.public_send(Tng::UI::Theme.color(:error),
|
|
147
|
-
"#{Tng::UI::Theme.icon(:warning)} You have reached your test generation limit")
|
|
148
|
-
end
|
|
149
|
-
puts Tng::UI::Theme.center_text(usage_msg, @terminal_width)
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def display_error
|
|
153
|
-
error_msg = @pastel.public_send(Tng::UI::Theme.color(:error)).bold("#{Tng::UI::Theme.icon(:error)} Failed to fetch user statistics")
|
|
154
|
-
puts Tng::UI::Theme.center_text(error_msg, @terminal_width)
|
|
155
|
-
puts Tng::UI::Theme.center_text(
|
|
156
|
-
@pastel.public_send(Tng::UI::Theme.color(:muted),
|
|
157
|
-
"Please check your API key and internet connection"), @terminal_width
|
|
158
|
-
)
|
|
159
|
-
end
|
|
160
|
-
end
|