tng 0.2.8 → 0.2.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 39e06ff3d2ea9fdf295f87ac41e01e3fef4365899a128d7e013d913c568253f4
4
- data.tar.gz: dd42840fd11e8c165b9777e540ae85c5eaa7047fd3b3923299cab3392431d0ee
3
+ metadata.gz: 5f6e0805bc5c9a7dbb6d83b8298fcbc099a14c70e118c02743545a29dfbc8182
4
+ data.tar.gz: 070b0bbc5c54a91b01a2e38113588e7838bb0ff1d8217e0f666695d953a7ea6a
5
5
  SHA512:
6
- metadata.gz: 188224ee7db41585b1f4bf6737a549ba6a2b7830b07b8ba31959a98b930901f07979a1e321d00fc129dd82321c8c35686571462c152534c1f7537f5c2f4f563c
7
- data.tar.gz: 0c5f179a3a833042e48cf06df02bf878e0ab7478975bbe328920831994d1097cd4fbf093bb3e8f6be236a7e172027d704f5746fc2e8272179e475b0132622621
6
+ metadata.gz: f46c75ee3f7fa1cc0e22bdb46687c600184e9f2435f8321be71bc1623c33c7a1494326d0cfcd2030017bbe94244f39869870a16f245d9abc3e2ee8b307dedf98
7
+ data.tar.gz: 1c971f70e79e8cf9d9bd99ce779e3d244bee955908aec4ab679fd7a72c491e68a624b2fa56ee8195ecef2e42ba2b3df2828bb7dcc8278caa5374692c68522807
data/bin/tng CHANGED
@@ -827,7 +827,7 @@ class CLI
827
827
 
828
828
  info_msg = [
829
829
  @pastel.decorate("#{Tng::UI::Theme.icon(:config)} File: #{result[:file_path]}", Tng::UI::Theme.color(:info)),
830
- @pastel.decorate("#{Tng::UI::Theme.icon(:marker)} Run: #{result[:run_command]}", Tng::UI::Theme.color(:warning))
830
+ @pastel.decorate("#{Tng::UI::Theme.icon(:marker)} Run: #{result[:run_command]}", Tng::UI::Theme.color(:secondary))
831
831
  ].join("\n")
832
832
  puts center_text(info_msg)
833
833
  puts
@@ -845,7 +845,7 @@ class CLI
845
845
 
846
846
  info_msg = [
847
847
  @pastel.decorate("#{Tng::UI::Theme.icon(:config)} File: #{result[:file_path]}", Tng::UI::Theme.color(:info)),
848
- @pastel.decorate("#{Tng::UI::Theme.icon(:marker)} Run: #{result[:run_command]}", Tng::UI::Theme.color(:warning))
848
+ @pastel.decorate("#{Tng::UI::Theme.icon(:marker)} Run: #{result[:run_command]}", Tng::UI::Theme.color(:secondary))
849
849
  ].join("\n")
850
850
  puts center_text(info_msg)
851
851
  puts
data/binaries/tng.bundle CHANGED
Binary file
data/binaries/tng.so CHANGED
Binary file
@@ -33,32 +33,50 @@ module Tng
33
33
  instance_methods = model_class.public_instance_methods(false)
34
34
  class_methods = model_class.public_methods(false) - Class.public_methods
35
35
 
36
- model_file = model_class.const_source_location(model_class.name.split("::").last)&.first
36
+ model_file = Object.const_source_location(model_class.name)&.first
37
37
 
38
- model_methods = if model_file && File.exist?(model_file)
39
- source_code = File.read(model_file)
40
- result = Prism.parse(source_code)
38
+ if model_file && File.exist?(model_file)
39
+ source_code = File.read(model_file)
40
+ result = Prism.parse(source_code)
41
41
 
42
- defined_methods = []
43
- extract_method_names(result.value, defined_methods)
42
+ defined_methods = []
43
+ synthetic_methods = []
44
+ scopes = []
45
+ validations = []
46
+ extract_method_names(result.value, defined_methods, synthetic_methods, scopes, validations)
44
47
 
45
- filtered_instance_methods = instance_methods.select do |method_name|
46
- method = model_class.instance_method(method_name)
47
- next false unless method.owner == model_class
48
+ filtered_instance_methods = instance_methods.select do |method_name|
49
+ method = model_class.instance_method(method_name)
50
+ next false unless method.owner == model_class
48
51
 
49
- defined_methods.include?(method_name.to_s)
50
- end
52
+ defined_methods.include?(method_name.to_s)
53
+ end
51
54
 
52
- filtered_class_methods = class_methods.select do |method_name|
53
- defined_methods.include?(method_name.to_s)
54
- end
55
+ filtered_class_methods = class_methods.select do |method_name|
56
+ defined_methods.include?(method_name.to_s)
57
+ end
55
58
 
56
- filtered_instance_methods + filtered_class_methods
57
- else
58
- []
59
- end
59
+ # Return array of hashes with type information
60
+ instance_method_hashes = filtered_instance_methods.map do |name|
61
+ { name: name.to_s, type: "instance_method" }
62
+ end
63
+ class_method_hashes = filtered_class_methods.map do |name|
64
+ { name: name.to_s, type: "class_method" }
65
+ end
66
+ synthetic_method_hashes = synthetic_methods.map do |name|
67
+ { name: name.to_s, type: "synthetic" }
68
+ end
69
+ scope_hashes = scopes.map do |name|
70
+ { name: name.to_s, type: "scope" }
71
+ end
72
+ validation_hashes = validations.map do |name|
73
+ { name: name.to_s, type: "validation" }
74
+ end
60
75
 
61
- model_methods.map { |method_name| { name: method_name.to_s } }
76
+ instance_method_hashes + class_method_hashes + synthetic_method_hashes + scope_hashes + validation_hashes
77
+ else
78
+ []
79
+ end
62
80
  rescue NameError => e
63
81
  puts "❌ Could not load model class #{model_name}: #{e.message}"
64
82
  []
@@ -68,7 +86,7 @@ module Tng
68
86
  end
69
87
  end
70
88
 
71
- def self.extract_method_names(node, methods)
89
+ def self.extract_method_names(node, methods, synthetic_methods = [], scopes = [], validations = [])
72
90
  return unless node.is_a?(Prism::Node)
73
91
 
74
92
  case node
@@ -81,18 +99,37 @@ module Tng
81
99
  first_arg = node.arguments.arguments.first
82
100
  if first_arg.is_a?(Prism::SymbolNode)
83
101
  scope_name = first_arg.value
84
- methods << scope_name if scope_name
102
+ scopes << scope_name if scope_name
103
+ end
104
+ # Handle validation macros
105
+ elsif node.name.to_s.start_with?("validate") && node.arguments&.arguments&.any?
106
+ if node.name == :validate
107
+ # Custom validation: validate :method_name -> extract actual method
108
+ node.arguments.arguments.each do |arg|
109
+ if arg.is_a?(Prism::SymbolNode)
110
+ validation_method = arg.value
111
+ validations << validation_method if validation_method
112
+ end
113
+ end
114
+ else
115
+ # Built-in validations: validates :attr, :attr2, ... -> add to validations
116
+ node.arguments.arguments.each do |arg|
117
+ if arg.is_a?(Prism::SymbolNode)
118
+ attr_name = arg.value
119
+ validations << attr_name if attr_name
120
+ end
121
+ end
85
122
  end
86
123
  end
87
124
  when Prism::SingletonClassNode
88
125
  # Methods inside class << self blocks
89
126
  node.body&.child_nodes&.each do |child|
90
- extract_method_names(child, methods)
127
+ extract_method_names(child, methods, synthetic_methods, scopes, validations)
91
128
  end
92
129
  end
93
130
 
94
131
  node.child_nodes.each do |child|
95
- extract_method_names(child, methods)
132
+ extract_method_names(child, methods, synthetic_methods, scopes, validations)
96
133
  end
97
134
  end
98
135
  end
@@ -47,7 +47,7 @@ module Tng
47
47
  end
48
48
 
49
49
  # Fallback to const_source_location if no method source found
50
- service_file ||= service_class.const_source_location(service_class.name.split("::").last)&.first
50
+ service_file ||= Object.const_source_location(service_class.name)&.first
51
51
 
52
52
  service_methods = if service_file && File.exist?(service_file)
53
53
  source_code = File.read(service_file)
@@ -87,13 +87,13 @@ module Tng
87
87
 
88
88
  case type
89
89
  when :controller
90
- Tng.send_request_for_controller(name, file_object[:path], method_info[:name], *config)
90
+ Tng.send_request_for_controller(name, file_object[:path], method_info, *config)
91
91
  when :model
92
- Tng.send_request_for_model(name, file_object[:path], method_info[:name], *config)
92
+ Tng.send_request_for_model(name, file_object[:path], method_info, *config)
93
93
  when :service
94
- Tng.send_request_for_service(name, file_object[:path], method_info[:name], *config)
94
+ Tng.send_request_for_service(name, file_object[:path], method_info, *config)
95
95
  when :other
96
- Tng.send_request_for_other(name, file_object[:path], method_info[:name], *config)
96
+ Tng.send_request_for_other(name, file_object[:path], method_info, *config)
97
97
  end
98
98
  end
99
99
 
@@ -34,6 +34,18 @@ module Tng
34
34
  }
35
35
  end
36
36
  Tng.config[:authentication_entry_points_with_source] = auth_entry_points_with_source
37
+
38
+ # Add source content to test examples for API requests
39
+ if Tng.config[:test_examples]&.any?
40
+ Tng.config[:test_examples] = Tng.config[:test_examples].map do |example|
41
+ next example unless example.is_a?(Hash) && example["path"]
42
+
43
+ example.merge("source" => read_test_file_content(example["path"]))
44
+ rescue StandardError
45
+ example
46
+ end
47
+ end
48
+
37
49
  Tng.config
38
50
  end
39
51
 
@@ -71,6 +83,19 @@ module Tng
71
83
  rescue StandardError
72
84
  nil
73
85
  end
86
+
87
+ def self.read_test_file_content(relative_path)
88
+ return nil unless relative_path
89
+
90
+ rails_root = defined?(Rails) && Rails.root ? Rails.root.to_s : Dir.pwd
91
+ full_path = File.join(rails_root, relative_path)
92
+
93
+ return nil unless File.exist?(full_path) && File.readable?(full_path)
94
+
95
+ File.read(full_path)
96
+ rescue StandardError
97
+ nil
98
+ end
74
99
  end
75
100
  end
76
101
  end
data/lib/tng/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Tng
4
- VERSION = "0.2.8"
4
+ VERSION = "0.2.9"
5
5
  end
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.2.8
4
+ version: 0.2.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - ralucab
@@ -287,7 +287,7 @@ post_install_message: "┌ TNG ────────────────
287
287
  \ │\n│ • bundle exec
288
288
  tng --help - Show help information │\n│ │\n│
289
289
  \ \U0001F4A1 Generate tests for individual methods with precision │\n└────────────────────────────────────────────────────────────
290
- v0.2.8 ┘\n"
290
+ v0.2.9 ┘\n"
291
291
  rdoc_options: []
292
292
  require_paths:
293
293
  - lib