tng 0.4.4 → 0.4.5
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/bin/tng +258 -0
- 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-darwin-x86_64.bundle +0 -0
- data/binaries/tng-linux-arm64.so +0 -0
- data/binaries/tng-linux-x86_64.so +0 -0
- data/binaries/tng.bundle +0 -0
- data/lib/tng/services/direct_generation.rb +35 -11
- data/lib/tng/ui/go_ui_session.rb +63 -1
- data/lib/tng/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 70161861ae22db154e31792a86414ad76d14d56d6a5c7ea14de126e26bf2e7a5
|
|
4
|
+
data.tar.gz: ee5bc28ae08666fa789ff0ca21c67735340c01e850b11afcbf34e80fa0d80d3a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ebd0fb7dbcbbb795810ae2da51ef4333c0a3e2d226c0cb5f5c5f3de7a965899ef099f7e0874c12f1a040c6f47a8db220b3658d12d5cae8b86b4827d4ade12691
|
|
7
|
+
data.tar.gz: 87e2aee29fbd86bb25aa2519d1e602b96bfc45a7d9a63ffd3e91697a9dae5eb4503bdf30c0b345b8de7641b91ee947b8c6b2b48a5b3da3f78a03024bcb636e93
|
data/bin/tng
CHANGED
|
@@ -64,6 +64,11 @@ class CLI
|
|
|
64
64
|
desc "Run in audit mode (find issues and behaviours instead of generating tests)"
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
+
flag :trace do
|
|
68
|
+
long "--trace"
|
|
69
|
+
desc "Generate and visualize a symbolic trace"
|
|
70
|
+
end
|
|
71
|
+
|
|
67
72
|
flag :json do
|
|
68
73
|
long "--json"
|
|
69
74
|
desc "Output results in JSON format"
|
|
@@ -116,6 +121,8 @@ class CLI
|
|
|
116
121
|
|
|
117
122
|
if params[:fix]
|
|
118
123
|
handle_fix_command
|
|
124
|
+
elsif params[:trace] && params[:file]
|
|
125
|
+
run_direct_trace
|
|
119
126
|
elsif params[:file]
|
|
120
127
|
run_direct_generation
|
|
121
128
|
else
|
|
@@ -149,6 +156,8 @@ class CLI
|
|
|
149
156
|
normalized << "--method=#{::Regexp.last_match(2)}"
|
|
150
157
|
when /^(?:--)?(audit|a)$/
|
|
151
158
|
normalized << "--audit"
|
|
159
|
+
when /^(?:--)?(trace)$/
|
|
160
|
+
normalized << "--trace"
|
|
152
161
|
when /^(?:--)?(json)$/
|
|
153
162
|
normalized << "--json"
|
|
154
163
|
when /^(?:--)?(fix|x)$/
|
|
@@ -208,6 +217,8 @@ class CLI
|
|
|
208
217
|
handle_test_generation
|
|
209
218
|
when "audit"
|
|
210
219
|
handle_audit_method
|
|
220
|
+
when "trace"
|
|
221
|
+
handle_trace_method
|
|
211
222
|
when "stats"
|
|
212
223
|
user_stats
|
|
213
224
|
when "about"
|
|
@@ -1069,7 +1080,254 @@ class CLI
|
|
|
1069
1080
|
orchestrator = Tng::Services::FixOrchestrator.new(@pastel, @http_client)
|
|
1070
1081
|
orchestrator.run(file_path)
|
|
1071
1082
|
end
|
|
1083
|
+
|
|
1084
|
+
def handle_trace_method
|
|
1085
|
+
choice = @go_ui.show_test_type_menu("trace")
|
|
1086
|
+
|
|
1087
|
+
case choice
|
|
1088
|
+
when "controller"
|
|
1089
|
+
trace_controller_method
|
|
1090
|
+
when "model"
|
|
1091
|
+
trace_model_method
|
|
1092
|
+
when "service"
|
|
1093
|
+
trace_service_method
|
|
1094
|
+
when "other"
|
|
1095
|
+
trace_other_method
|
|
1096
|
+
end
|
|
1097
|
+
end
|
|
1098
|
+
|
|
1099
|
+
def trace_controller_method
|
|
1100
|
+
select_controller_and_method("Trace") do |controller, method_info|
|
|
1101
|
+
run_trace_for_method(controller, method_info)
|
|
1102
|
+
end
|
|
1103
|
+
end
|
|
1104
|
+
|
|
1105
|
+
def trace_model_method
|
|
1106
|
+
select_model_and_method("Trace") do |model, method_info|
|
|
1107
|
+
run_trace_for_method(model, method_info)
|
|
1108
|
+
end
|
|
1109
|
+
end
|
|
1110
|
+
|
|
1111
|
+
def trace_service_method
|
|
1112
|
+
select_service_and_method("Trace") do |service, method_info|
|
|
1113
|
+
run_trace_for_method(service, method_info)
|
|
1114
|
+
end
|
|
1115
|
+
end
|
|
1116
|
+
|
|
1117
|
+
def trace_other_method
|
|
1118
|
+
select_other_and_method("Trace") do |file, method_info|
|
|
1119
|
+
run_trace_for_method(file, method_info)
|
|
1120
|
+
end
|
|
1121
|
+
end
|
|
1122
|
+
|
|
1123
|
+
def run_trace_for_method(file_info, method_info)
|
|
1124
|
+
result_path = nil
|
|
1125
|
+
|
|
1126
|
+
@go_ui.show_spinner("Tracing #{method_info[:name]}...") do
|
|
1127
|
+
begin
|
|
1128
|
+
project_root = Dir.pwd
|
|
1129
|
+
path = File.expand_path(file_info[:path])
|
|
1130
|
+
|
|
1131
|
+
trace_json = Tng::Analyzer::Context.analyze_symbolic_trace(
|
|
1132
|
+
project_root,
|
|
1133
|
+
path,
|
|
1134
|
+
method_info[:name],
|
|
1135
|
+
nil
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
f = Tempfile.new(['trace', '.json'])
|
|
1139
|
+
f.write(JSON.generate(trace_json))
|
|
1140
|
+
f.close
|
|
1141
|
+
result_path = f.path
|
|
1142
|
+
|
|
1143
|
+
{ success: true, message: "Trace generated" }
|
|
1144
|
+
rescue => e
|
|
1145
|
+
{ success: false, message: e.message }
|
|
1146
|
+
end
|
|
1147
|
+
end
|
|
1148
|
+
|
|
1149
|
+
if result_path
|
|
1150
|
+
@go_ui.show_trace_results(result_path)
|
|
1151
|
+
File.unlink(result_path) if File.exist?(result_path)
|
|
1152
|
+
end
|
|
1153
|
+
end
|
|
1154
|
+
|
|
1155
|
+
def run_direct_trace
|
|
1156
|
+
file_path = params[:file]
|
|
1157
|
+
method_name = params[:method]
|
|
1158
|
+
|
|
1159
|
+
unless method_name
|
|
1160
|
+
puts @pastel.decorate("Please specify a method name with --method or -m", Tng::UI::Theme.color(:error))
|
|
1161
|
+
return
|
|
1162
|
+
end
|
|
1163
|
+
|
|
1164
|
+
full_path = File.expand_path(file_path)
|
|
1165
|
+
unless File.exist?(full_path)
|
|
1166
|
+
puts @pastel.decorate("File not found: #{full_path}", Tng::UI::Theme.color(:error))
|
|
1167
|
+
return
|
|
1168
|
+
end
|
|
1169
|
+
|
|
1170
|
+
file_info = { path: full_path, name: File.basename(full_path) }
|
|
1171
|
+
method_info = { name: method_name }
|
|
1172
|
+
|
|
1173
|
+
run_trace_for_method(file_info, method_info)
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
def select_controller_and_method(action_name)
|
|
1177
|
+
controllers = nil
|
|
1178
|
+
@go_ui.show_spinner("Analyzing controllers...") do
|
|
1179
|
+
controllers = Tng::Analyzers::Controller.files_in_dir("app/controllers").map do |file|
|
|
1180
|
+
relative_path = file[:path].gsub(%r{^.*app/controllers/}, "").gsub(".rb", "")
|
|
1181
|
+
namespaced_name = relative_path.split("/").map(&:camelize).join("::")
|
|
1182
|
+
{ name: namespaced_name, path: file[:path] }
|
|
1183
|
+
end
|
|
1184
|
+
{ success: true, message: "Found #{controllers.length} controllers" }
|
|
1185
|
+
end
|
|
1186
|
+
|
|
1187
|
+
if controllers.empty?
|
|
1188
|
+
@go_ui.show_no_items("controllers")
|
|
1189
|
+
return
|
|
1190
|
+
end
|
|
1191
|
+
|
|
1192
|
+
items = controllers.map { |c| { name: c[:name], path: c[:path] } }
|
|
1193
|
+
|
|
1194
|
+
loop do
|
|
1195
|
+
selected = @go_ui.show_list_view("Select Controller to #{action_name}", items)
|
|
1196
|
+
return if selected == "back"
|
|
1197
|
+
|
|
1198
|
+
choice = controllers.find { |c| c[:name] == selected }
|
|
1199
|
+
next unless choice
|
|
1200
|
+
|
|
1201
|
+
methods = extract_controller_methods(choice)
|
|
1202
|
+
if methods.empty?
|
|
1203
|
+
@go_ui.show_no_items("methods in #{choice[:name]}")
|
|
1204
|
+
next
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
m_items = methods.map { |m| { name: m[:name], path: choice[:name] } }
|
|
1208
|
+
m_selected = @go_ui.show_list_view("Select Method to #{action_name}", m_items)
|
|
1209
|
+
next if m_selected == "back"
|
|
1210
|
+
|
|
1211
|
+
m_choice = methods.find { |m| m[:name] == m_selected }
|
|
1212
|
+
next unless m_choice
|
|
1213
|
+
|
|
1214
|
+
yield(choice, m_choice)
|
|
1215
|
+
end
|
|
1216
|
+
end
|
|
1217
|
+
|
|
1218
|
+
def select_model_and_method(action_name)
|
|
1219
|
+
models = nil
|
|
1220
|
+
@go_ui.show_spinner("Analyzing models...") do
|
|
1221
|
+
models = Tng::Analyzers::Model.files_in_dir("app/models").map do |file|
|
|
1222
|
+
relative_path = file[:path].gsub(%r{^.*app/models/}, "").gsub(".rb", "")
|
|
1223
|
+
namespaced_name = relative_path.split("/").map(&:camelize).join("::")
|
|
1224
|
+
{ name: namespaced_name, path: file[:path] }
|
|
1225
|
+
end
|
|
1226
|
+
{ success: true, message: "Found #{models.length} models" }
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
return @go_ui.show_no_items("models") if models.empty?
|
|
1230
|
+
|
|
1231
|
+
items = models.map { |m| { name: m[:name], path: m[:path] } }
|
|
1232
|
+
|
|
1233
|
+
loop do
|
|
1234
|
+
selected = @go_ui.show_list_view("Select Model to #{action_name}", items)
|
|
1235
|
+
return if selected == "back"
|
|
1236
|
+
|
|
1237
|
+
choice = models.find { |m| m[:name] == selected }
|
|
1238
|
+
next unless choice
|
|
1239
|
+
|
|
1240
|
+
methods = extract_model_methods(choice)
|
|
1241
|
+
if methods.empty?
|
|
1242
|
+
@go_ui.show_no_items("methods in #{choice[:name]}")
|
|
1243
|
+
next
|
|
1244
|
+
end
|
|
1245
|
+
|
|
1246
|
+
m_items = methods.map { |m| { name: m[:name], path: choice[:name] } }
|
|
1247
|
+
m_selected = @go_ui.show_list_view("Select Method to #{action_name}", m_items)
|
|
1248
|
+
next if m_selected == "back"
|
|
1249
|
+
|
|
1250
|
+
m_choice = methods.find { |m| m[:name] == m_selected }
|
|
1251
|
+
yield(choice, m_choice)
|
|
1252
|
+
end
|
|
1253
|
+
end
|
|
1254
|
+
|
|
1255
|
+
def select_service_and_method(action_name)
|
|
1256
|
+
services = nil
|
|
1257
|
+
@go_ui.show_spinner("Analyzing services...") do
|
|
1258
|
+
services = Tng::Analyzers::Service.files_in_dir.map do |file|
|
|
1259
|
+
relative_path = file[:path].gsub(%r{^.*app/services?/}, "").gsub(".rb", "")
|
|
1260
|
+
namespaced_name = relative_path.split("/").map(&:camelize).join("::")
|
|
1261
|
+
{ name: namespaced_name, path: file[:path] }
|
|
1262
|
+
end
|
|
1263
|
+
{ success: true, message: "Found #{services.length} services" }
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
return @go_ui.show_no_items("services") if services.empty?
|
|
1267
|
+
|
|
1268
|
+
items = services.map { |s| { name: s[:name], path: s[:path] } }
|
|
1269
|
+
|
|
1270
|
+
loop do
|
|
1271
|
+
selected = @go_ui.show_list_view("Select Service to #{action_name}", items)
|
|
1272
|
+
return if selected == "back"
|
|
1273
|
+
|
|
1274
|
+
choice = services.find { |s| s[:name] == selected }
|
|
1275
|
+
next unless choice
|
|
1276
|
+
|
|
1277
|
+
methods = extract_service_methods(choice)
|
|
1278
|
+
if methods.empty?
|
|
1279
|
+
@go_ui.show_no_items("methods in #{choice[:name]}")
|
|
1280
|
+
next
|
|
1281
|
+
end
|
|
1282
|
+
|
|
1283
|
+
m_items = methods.map { |m| { name: m[:name], path: choice[:name] } }
|
|
1284
|
+
m_selected = @go_ui.show_list_view("Select Method to #{action_name}", m_items)
|
|
1285
|
+
next if m_selected == "back"
|
|
1286
|
+
|
|
1287
|
+
m_choice = methods.find { |m| m[:name] == m_selected }
|
|
1288
|
+
yield(choice, m_choice)
|
|
1289
|
+
end
|
|
1290
|
+
end
|
|
1291
|
+
|
|
1292
|
+
def select_other_and_method(action_name)
|
|
1293
|
+
files = nil
|
|
1294
|
+
@go_ui.show_spinner("Analyzing other files...") do
|
|
1295
|
+
files = Tng::Analyzers::Other.files_in_dir.map do |file|
|
|
1296
|
+
relative_path = file[:relative_path].gsub(".rb", "")
|
|
1297
|
+
namespaced_name = relative_path.split("/").map(&:camelize).join("::")
|
|
1298
|
+
{ name: namespaced_name, path: file[:path], type: file[:type] }
|
|
1299
|
+
end
|
|
1300
|
+
{ success: true, message: "Found #{files.length} other files" }
|
|
1301
|
+
end
|
|
1302
|
+
|
|
1303
|
+
return @go_ui.show_no_items("other files") if files.empty?
|
|
1304
|
+
|
|
1305
|
+
items = files.map { |f| { name: f[:name], path: f[:path] } }
|
|
1306
|
+
|
|
1307
|
+
loop do
|
|
1308
|
+
selected = @go_ui.show_list_view("Select File to #{action_name}", items)
|
|
1309
|
+
return if selected == "back"
|
|
1310
|
+
|
|
1311
|
+
choice = files.find { |f| f[:name] == selected }
|
|
1312
|
+
next unless choice
|
|
1313
|
+
|
|
1314
|
+
methods = extract_other_methods(choice)
|
|
1315
|
+
if methods.empty?
|
|
1316
|
+
@go_ui.show_no_items("methods in #{choice[:name]}")
|
|
1317
|
+
next
|
|
1318
|
+
end
|
|
1319
|
+
|
|
1320
|
+
m_items = methods.map { |m| { name: m[:name], path: choice[:name] } }
|
|
1321
|
+
m_selected = @go_ui.show_list_view("Select Method to #{action_name}", m_items)
|
|
1322
|
+
next if m_selected == "back"
|
|
1323
|
+
|
|
1324
|
+
m_choice = methods.find { |m| m[:name] == m_selected }
|
|
1325
|
+
yield(choice, m_choice)
|
|
1326
|
+
end
|
|
1327
|
+
end
|
|
1072
1328
|
end
|
|
1073
1329
|
|
|
1330
|
+
|
|
1331
|
+
|
|
1074
1332
|
cli = CLI.new
|
|
1075
1333
|
cli.start
|
data/binaries/go-ui-darwin-amd64
CHANGED
|
Binary file
|
data/binaries/go-ui-darwin-arm64
CHANGED
|
Binary file
|
data/binaries/go-ui-linux-amd64
CHANGED
|
Binary file
|
data/binaries/go-ui-linux-arm64
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
data/binaries/tng-linux-arm64.so
CHANGED
|
Binary file
|
|
Binary file
|
data/binaries/tng.bundle
CHANGED
|
Binary file
|
|
@@ -17,14 +17,10 @@ module Tng
|
|
|
17
17
|
@go_ui = go_ui
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# ... (rest of methods)
|
|
21
|
-
|
|
22
20
|
def display_audit_results(result)
|
|
23
21
|
audit_results = result[:audit_results]
|
|
24
22
|
return unless audit_results
|
|
25
23
|
|
|
26
|
-
# Use Go UI to display rich audit results
|
|
27
|
-
# "issues" type handles both issues and behaviours in the unified view
|
|
28
24
|
@go_ui.show_audit_results(audit_results, "issues")
|
|
29
25
|
end
|
|
30
26
|
|
|
@@ -52,8 +48,6 @@ module Tng
|
|
|
52
48
|
generate_test_for_file(resolved_path, method_name, type)
|
|
53
49
|
end
|
|
54
50
|
|
|
55
|
-
private
|
|
56
|
-
|
|
57
51
|
def suggest_similar_files(file_path)
|
|
58
52
|
base_name = File.basename(file_path, ".rb")
|
|
59
53
|
|
|
@@ -106,11 +100,14 @@ module Tng
|
|
|
106
100
|
|
|
107
101
|
if result&.dig(:error)
|
|
108
102
|
@go_ui.display_error(@pastel.red("❌ #{@params[:audit] ? "Audit" : "Test generation"} failed: #{result[:message]}"))
|
|
103
|
+
elsif result&.dig(:trace_generated)
|
|
104
|
+
if result[:file_path]
|
|
105
|
+
@go_ui.show_trace_results(result[:file_path])
|
|
106
|
+
File.unlink(result[:file_path]) if File.exist?(result[:file_path])
|
|
107
|
+
end
|
|
109
108
|
elsif @params[:audit]
|
|
110
|
-
# Audit mode - display results inline
|
|
111
109
|
display_audit_results(result)
|
|
112
110
|
elsif result && result[:file_path]
|
|
113
|
-
# Test generation mode - show post-generation menu
|
|
114
111
|
@show_post_generation_menu.call(result)
|
|
115
112
|
else
|
|
116
113
|
@go_ui.display_error(@pastel.red("❌ Failed to generate test"))
|
|
@@ -129,8 +126,9 @@ module Tng
|
|
|
129
126
|
def generate_test_result(file_object, method_info, type, progress)
|
|
130
127
|
generator = Tng::Services::TestGenerator.new(@http_client)
|
|
131
128
|
|
|
132
|
-
if @params[:
|
|
133
|
-
|
|
129
|
+
if @params[:trace]
|
|
130
|
+
perform_trace_analysis(file_object, method_info, progress)
|
|
131
|
+
elsif @params[:audit]
|
|
134
132
|
case type
|
|
135
133
|
when "controller" then generator.run_audit_for_controller_method(file_object, method_info, progress: progress)
|
|
136
134
|
when "model" then generator.run_audit_for_model_method(file_object, method_info, progress: progress)
|
|
@@ -138,7 +136,6 @@ module Tng
|
|
|
138
136
|
else generator.run_audit_for_other_method(file_object, method_info, progress: progress)
|
|
139
137
|
end
|
|
140
138
|
else
|
|
141
|
-
# Test generation mode
|
|
142
139
|
case type
|
|
143
140
|
when "controller" then generator.run_for_controller_method(file_object, method_info, progress: progress)
|
|
144
141
|
when "model" then generator.run_for_model_method(file_object, method_info, progress: progress)
|
|
@@ -147,6 +144,33 @@ module Tng
|
|
|
147
144
|
end
|
|
148
145
|
end
|
|
149
146
|
end
|
|
147
|
+
|
|
148
|
+
def perform_trace_analysis(file_object, method_info, progress)
|
|
149
|
+
progress.update("Tracing method execution...", 50)
|
|
150
|
+
|
|
151
|
+
project_root = Dir.pwd
|
|
152
|
+
path = File.expand_path(file_object[:path])
|
|
153
|
+
|
|
154
|
+
begin
|
|
155
|
+
trace_json = Tng::Analyzer::Context.analyze_symbolic_trace(
|
|
156
|
+
project_root,
|
|
157
|
+
path,
|
|
158
|
+
method_info[:name],
|
|
159
|
+
nil
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
f = Tempfile.new(['trace', '.json'])
|
|
163
|
+
f.write(JSON.generate(trace_json))
|
|
164
|
+
f.close
|
|
165
|
+
result_path = f.path
|
|
166
|
+
|
|
167
|
+
progress.update("Trace generated!", 100)
|
|
168
|
+
|
|
169
|
+
{ trace_generated: true, file_path: result_path }
|
|
170
|
+
rescue => e
|
|
171
|
+
{ error: true, message: e.message }
|
|
172
|
+
end
|
|
173
|
+
end
|
|
150
174
|
end
|
|
151
175
|
end
|
|
152
176
|
end
|
data/lib/tng/ui/go_ui_session.rb
CHANGED
|
@@ -253,6 +253,14 @@ module Tng
|
|
|
253
253
|
File.unlink(input_path) if input_path && File.exist?(input_path)
|
|
254
254
|
end
|
|
255
255
|
|
|
256
|
+
# Show symbolic trace results
|
|
257
|
+
# @param trace_file_path [String] Path to JSON trace file
|
|
258
|
+
def show_trace_results(trace_file_path)
|
|
259
|
+
system(@binary_path, "trace-results", "--file", trace_file_path)
|
|
260
|
+
rescue StandardError => e
|
|
261
|
+
puts "Trace results error: #{e.message}"
|
|
262
|
+
end
|
|
263
|
+
|
|
256
264
|
# Show authentication error
|
|
257
265
|
# @param message [String] Error message to display
|
|
258
266
|
def show_auth_error(message = "Authentication failed")
|
|
@@ -320,11 +328,65 @@ module Tng
|
|
|
320
328
|
# Show help
|
|
321
329
|
# @param version [String] Version to display
|
|
322
330
|
def show_help(version)
|
|
323
|
-
|
|
331
|
+
help_data = {
|
|
332
|
+
title: "TNG - LLM-Powered Rails Test Generator",
|
|
333
|
+
usages: [
|
|
334
|
+
{ cmd: "bundle exec tng", desc: "Interactive mode" },
|
|
335
|
+
{ cmd: "bundle exec tng --file=FILE --method=METHOD", desc: "Direct test generation" },
|
|
336
|
+
{ cmd: "bundle exec tng --file=FILE --method=METHOD --audit", desc: "Direct audit mode" },
|
|
337
|
+
{ cmd: "bundle exec tng --file=FILE --method=METHOD --trace", desc: "Symbolic trace mode" }
|
|
338
|
+
],
|
|
339
|
+
features: [
|
|
340
|
+
"Controllers, Models, Services",
|
|
341
|
+
"17+ other file types (Jobs, Helpers, Lib, Policies, etc.)",
|
|
342
|
+
"Per-method test generation",
|
|
343
|
+
"Code audit for issues & behaviors",
|
|
344
|
+
"Symbolic execution traces",
|
|
345
|
+
"Searchable method lists"
|
|
346
|
+
],
|
|
347
|
+
options: [
|
|
348
|
+
{ flag: "-h, --help", desc: "Show this help message" },
|
|
349
|
+
{ flag: "--file=PATH", desc: "Target file path (enables direct CLI mode)" },
|
|
350
|
+
{ flag: "--method=NAME", desc: "Method name to generate test for" },
|
|
351
|
+
{ flag: "--audit", desc: "Run audit mode instead of test generation" },
|
|
352
|
+
{ flag: "--trace", desc: "Run symbolic trace mode" }
|
|
353
|
+
],
|
|
354
|
+
how_to: [
|
|
355
|
+
"Run 'bundle exec tng' to start the interactive interface",
|
|
356
|
+
"Select Controller, Model, Service, or Other to test",
|
|
357
|
+
"Choose a specific method from the list",
|
|
358
|
+
"Use search/filter to find methods quickly"
|
|
359
|
+
],
|
|
360
|
+
footer: "Happy testing! "
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
system(@binary_path, "help-box", "--version", version, "--data", JSON.generate(help_data))
|
|
324
364
|
rescue StandardError => e
|
|
325
365
|
puts "Help error: #{e.message}"
|
|
326
366
|
end
|
|
327
367
|
|
|
368
|
+
# Display error message using standard output (fallback for simple messages)
|
|
369
|
+
def display_error(message)
|
|
370
|
+
system(@binary_path, "auth-error", "--message", message, "--title", "Error")
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# Display warning message
|
|
374
|
+
def display_warning(message)
|
|
375
|
+
# Re-using auth-error for now but with different color/prefix if possible, or just puts if binary doesn't support generic warning
|
|
376
|
+
puts message
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
# Display info message
|
|
380
|
+
def display_info(message)
|
|
381
|
+
puts message
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# Display list of items
|
|
385
|
+
def display_list(title, items)
|
|
386
|
+
puts title
|
|
387
|
+
items.each { |item| puts " - #{item}" }
|
|
388
|
+
end
|
|
389
|
+
|
|
328
390
|
# Show system status
|
|
329
391
|
# @param status [Hash] Status data from testng
|
|
330
392
|
def show_system_status(status)
|
data/lib/tng/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: tng
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ralucab
|
|
@@ -222,7 +222,7 @@ post_install_message: "┌ TNG ────────────────
|
|
|
222
222
|
\ │\n│ • bundle exec
|
|
223
223
|
tng --help - Show help information │\n│ │\n│
|
|
224
224
|
\ \U0001F4A1 Generate tests for individual methods with precision │\n└────────────────────────────────────────────────────────────
|
|
225
|
-
v0.4.
|
|
225
|
+
v0.4.5 ┘\n"
|
|
226
226
|
rdoc_options: []
|
|
227
227
|
require_paths:
|
|
228
228
|
- lib
|