spec_guardian 0.1.2
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/.DS_Store +0 -0
- data/.gitignore +13 -0
- data/.prettierrc +27 -0
- data/.rspec +3 -0
- data/.rubocop.yml +21 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +305 -0
- data/LICENSE.md +21 -0
- data/README.md +84 -0
- data/Rakefile +12 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/bin/spec_guardian +25 -0
- data/lib/generators/spec_guardian/install_generator.rb +13 -0
- data/lib/generators/spec_guardian/templates/config/initializers/spec_guardian.rb +7 -0
- data/lib/spec_guardian/ai_client.rb +74 -0
- data/lib/spec_guardian/configuration.rb +12 -0
- data/lib/spec_guardian/file_path_resolver.rb +33 -0
- data/lib/spec_guardian/railtie.rb +9 -0
- data/lib/spec_guardian/test_framework_detector.rb +21 -0
- data/lib/spec_guardian/version.rb +5 -0
- data/lib/spec_guardian.rb +44 -0
- data/lib/tasks/generate_tests.rake +13 -0
- data/sig/spec_guardian.rbs +4 -0
- data/spec_guardian.gemspec +44 -0
- metadata +256 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 48673c89d4e9875932318e835524bf63b4dc03eb779dc1f6a603b3cca2ac2eef
|
4
|
+
data.tar.gz: 78200eb6a421aec33340e58ae22674068b5ab7d05aaac03f5d2b83f5eb176af1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6ab6111033bbfe79842df12c1a526ea93785080e627d2bfda161e295b9e24b7d618899bdbdbfbb273b05f47f4efa975e038affa83e1002d276a442126b660c12
|
7
|
+
data.tar.gz: af439dc047b822ecf3ce303114ed7405923eda8bfa4e6b9ccf8b3b07af5c0cf7a42ae0fd718f84583c8f0efb285221647bb35850a06c0e059598acd46057b26a
|
data/.DS_Store
ADDED
Binary file
|
data/.gitignore
ADDED
data/.prettierrc
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
{
|
2
|
+
"tabWidth": 2,
|
3
|
+
"useTabs": false,
|
4
|
+
"semi": true,
|
5
|
+
"singleQuote": true,
|
6
|
+
"jsxSingleQuote": false,
|
7
|
+
"trailingComma": "all",
|
8
|
+
"bracketSpacing": true,
|
9
|
+
"bracketSameLine": false,
|
10
|
+
"arrowParens": "avoid",
|
11
|
+
"printWidth": 120,
|
12
|
+
"rubyPlugins": "plugin/trailing_comma",
|
13
|
+
"overrides": [
|
14
|
+
{
|
15
|
+
"files": ["babel.config.js"],
|
16
|
+
"options": {
|
17
|
+
"trailingComma": "es5"
|
18
|
+
}
|
19
|
+
},
|
20
|
+
{
|
21
|
+
"files": ["*.css", "*.scss"],
|
22
|
+
"options": {
|
23
|
+
"singleQuote": false
|
24
|
+
}
|
25
|
+
}
|
26
|
+
]
|
27
|
+
}
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Overwrite or add rules to create your own house style
|
2
|
+
#
|
3
|
+
# # Use `[a, [b, c]]` not `[ a, [ b, c ] ]`
|
4
|
+
# Layout/SpaceInsideArrayLiteralBrackets:
|
5
|
+
# Enabled: false
|
6
|
+
Style/StringLiterals:
|
7
|
+
Enabled: true
|
8
|
+
EnforcedStyle: single_quotes
|
9
|
+
Style/TrailingCommaInHashLiteral:
|
10
|
+
Enabled: true
|
11
|
+
EnforcedStyle: no_comma
|
12
|
+
Style/EmptyMethod:
|
13
|
+
Enabled: true
|
14
|
+
EnforcedStyle: expanded
|
15
|
+
Style/Documentation:
|
16
|
+
Enabled: false
|
17
|
+
Style/FrozenStringLiteralComment:
|
18
|
+
Enabled: false
|
19
|
+
Metrics/MethodLength:
|
20
|
+
Enabled: true
|
21
|
+
Max: 25
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.3.6
|
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,305 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
spec_guardian (0.1.2)
|
5
|
+
anthropic (>= 0.3.2)
|
6
|
+
rails (>= 6.0)
|
7
|
+
rake (>= 12.0)
|
8
|
+
thor (>= 1.2)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
actioncable (8.0.1)
|
14
|
+
actionpack (= 8.0.1)
|
15
|
+
activesupport (= 8.0.1)
|
16
|
+
nio4r (~> 2.0)
|
17
|
+
websocket-driver (>= 0.6.1)
|
18
|
+
zeitwerk (~> 2.6)
|
19
|
+
actionmailbox (8.0.1)
|
20
|
+
actionpack (= 8.0.1)
|
21
|
+
activejob (= 8.0.1)
|
22
|
+
activerecord (= 8.0.1)
|
23
|
+
activestorage (= 8.0.1)
|
24
|
+
activesupport (= 8.0.1)
|
25
|
+
mail (>= 2.8.0)
|
26
|
+
actionmailer (8.0.1)
|
27
|
+
actionpack (= 8.0.1)
|
28
|
+
actionview (= 8.0.1)
|
29
|
+
activejob (= 8.0.1)
|
30
|
+
activesupport (= 8.0.1)
|
31
|
+
mail (>= 2.8.0)
|
32
|
+
rails-dom-testing (~> 2.2)
|
33
|
+
actionpack (8.0.1)
|
34
|
+
actionview (= 8.0.1)
|
35
|
+
activesupport (= 8.0.1)
|
36
|
+
nokogiri (>= 1.8.5)
|
37
|
+
rack (>= 2.2.4)
|
38
|
+
rack-session (>= 1.0.1)
|
39
|
+
rack-test (>= 0.6.3)
|
40
|
+
rails-dom-testing (~> 2.2)
|
41
|
+
rails-html-sanitizer (~> 1.6)
|
42
|
+
useragent (~> 0.16)
|
43
|
+
actiontext (8.0.1)
|
44
|
+
actionpack (= 8.0.1)
|
45
|
+
activerecord (= 8.0.1)
|
46
|
+
activestorage (= 8.0.1)
|
47
|
+
activesupport (= 8.0.1)
|
48
|
+
globalid (>= 0.6.0)
|
49
|
+
nokogiri (>= 1.8.5)
|
50
|
+
actionview (8.0.1)
|
51
|
+
activesupport (= 8.0.1)
|
52
|
+
builder (~> 3.1)
|
53
|
+
erubi (~> 1.11)
|
54
|
+
rails-dom-testing (~> 2.2)
|
55
|
+
rails-html-sanitizer (~> 1.6)
|
56
|
+
activejob (8.0.1)
|
57
|
+
activesupport (= 8.0.1)
|
58
|
+
globalid (>= 0.3.6)
|
59
|
+
activemodel (8.0.1)
|
60
|
+
activesupport (= 8.0.1)
|
61
|
+
activerecord (8.0.1)
|
62
|
+
activemodel (= 8.0.1)
|
63
|
+
activesupport (= 8.0.1)
|
64
|
+
timeout (>= 0.4.0)
|
65
|
+
activestorage (8.0.1)
|
66
|
+
actionpack (= 8.0.1)
|
67
|
+
activejob (= 8.0.1)
|
68
|
+
activerecord (= 8.0.1)
|
69
|
+
activesupport (= 8.0.1)
|
70
|
+
marcel (~> 1.0)
|
71
|
+
activesupport (8.0.1)
|
72
|
+
base64
|
73
|
+
benchmark (>= 0.3)
|
74
|
+
bigdecimal
|
75
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
76
|
+
connection_pool (>= 2.2.5)
|
77
|
+
drb
|
78
|
+
i18n (>= 1.6, < 2)
|
79
|
+
logger (>= 1.4.2)
|
80
|
+
minitest (>= 5.1)
|
81
|
+
securerandom (>= 0.3)
|
82
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
83
|
+
uri (>= 0.13.1)
|
84
|
+
anthropic (0.3.2)
|
85
|
+
event_stream_parser (>= 0.3.0, < 2.0.0)
|
86
|
+
faraday (>= 1)
|
87
|
+
faraday-multipart (>= 1)
|
88
|
+
ast (2.4.2)
|
89
|
+
base64 (0.2.0)
|
90
|
+
benchmark (0.4.0)
|
91
|
+
bigdecimal (3.1.9)
|
92
|
+
builder (3.3.0)
|
93
|
+
coderay (1.1.3)
|
94
|
+
concurrent-ruby (1.3.5)
|
95
|
+
connection_pool (2.5.0)
|
96
|
+
crass (1.0.6)
|
97
|
+
date (3.4.1)
|
98
|
+
diff-lcs (1.6.0)
|
99
|
+
drb (2.2.1)
|
100
|
+
erubi (1.13.1)
|
101
|
+
event_stream_parser (1.0.0)
|
102
|
+
faraday (2.12.2)
|
103
|
+
faraday-net_http (>= 2.0, < 3.5)
|
104
|
+
json
|
105
|
+
logger
|
106
|
+
faraday-multipart (1.1.0)
|
107
|
+
multipart-post (~> 2.0)
|
108
|
+
faraday-net_http (3.4.0)
|
109
|
+
net-http (>= 0.5.0)
|
110
|
+
globalid (1.2.1)
|
111
|
+
activesupport (>= 6.1)
|
112
|
+
i18n (1.14.7)
|
113
|
+
concurrent-ruby (~> 1.0)
|
114
|
+
io-console (0.8.0)
|
115
|
+
irb (1.15.1)
|
116
|
+
pp (>= 0.6.0)
|
117
|
+
rdoc (>= 4.0.0)
|
118
|
+
reline (>= 0.4.2)
|
119
|
+
json (2.10.1)
|
120
|
+
language_server-protocol (3.17.0.4)
|
121
|
+
lint_roller (1.1.0)
|
122
|
+
logger (1.6.6)
|
123
|
+
loofah (2.24.0)
|
124
|
+
crass (~> 1.0.2)
|
125
|
+
nokogiri (>= 1.12.0)
|
126
|
+
mail (2.8.1)
|
127
|
+
mini_mime (>= 0.1.1)
|
128
|
+
net-imap
|
129
|
+
net-pop
|
130
|
+
net-smtp
|
131
|
+
marcel (1.0.4)
|
132
|
+
method_source (1.1.0)
|
133
|
+
mini_mime (1.1.5)
|
134
|
+
minitest (5.25.4)
|
135
|
+
multipart-post (2.4.1)
|
136
|
+
net-http (0.6.0)
|
137
|
+
uri
|
138
|
+
net-imap (0.5.6)
|
139
|
+
date
|
140
|
+
net-protocol
|
141
|
+
net-pop (0.1.2)
|
142
|
+
net-protocol
|
143
|
+
net-protocol (0.2.2)
|
144
|
+
timeout
|
145
|
+
net-smtp (0.5.1)
|
146
|
+
net-protocol
|
147
|
+
nio4r (2.7.4)
|
148
|
+
nokogiri (1.18.3-aarch64-linux-gnu)
|
149
|
+
racc (~> 1.4)
|
150
|
+
nokogiri (1.18.3-aarch64-linux-musl)
|
151
|
+
racc (~> 1.4)
|
152
|
+
nokogiri (1.18.3-arm-linux-gnu)
|
153
|
+
racc (~> 1.4)
|
154
|
+
nokogiri (1.18.3-arm-linux-musl)
|
155
|
+
racc (~> 1.4)
|
156
|
+
nokogiri (1.18.3-arm64-darwin)
|
157
|
+
racc (~> 1.4)
|
158
|
+
nokogiri (1.18.3-x86_64-darwin)
|
159
|
+
racc (~> 1.4)
|
160
|
+
nokogiri (1.18.3-x86_64-linux-gnu)
|
161
|
+
racc (~> 1.4)
|
162
|
+
nokogiri (1.18.3-x86_64-linux-musl)
|
163
|
+
racc (~> 1.4)
|
164
|
+
parallel (1.26.3)
|
165
|
+
parser (3.3.7.1)
|
166
|
+
ast (~> 2.4.1)
|
167
|
+
racc
|
168
|
+
pp (0.6.2)
|
169
|
+
prettyprint
|
170
|
+
prettyprint (0.2.0)
|
171
|
+
pry (0.15.2)
|
172
|
+
coderay (~> 1.1)
|
173
|
+
method_source (~> 1.0)
|
174
|
+
psych (5.2.3)
|
175
|
+
date
|
176
|
+
stringio
|
177
|
+
racc (1.8.1)
|
178
|
+
rack (3.1.10)
|
179
|
+
rack-session (2.1.0)
|
180
|
+
base64 (>= 0.1.0)
|
181
|
+
rack (>= 3.0.0)
|
182
|
+
rack-test (2.2.0)
|
183
|
+
rack (>= 1.3)
|
184
|
+
rackup (2.2.1)
|
185
|
+
rack (>= 3)
|
186
|
+
rails (8.0.1)
|
187
|
+
actioncable (= 8.0.1)
|
188
|
+
actionmailbox (= 8.0.1)
|
189
|
+
actionmailer (= 8.0.1)
|
190
|
+
actionpack (= 8.0.1)
|
191
|
+
actiontext (= 8.0.1)
|
192
|
+
actionview (= 8.0.1)
|
193
|
+
activejob (= 8.0.1)
|
194
|
+
activemodel (= 8.0.1)
|
195
|
+
activerecord (= 8.0.1)
|
196
|
+
activestorage (= 8.0.1)
|
197
|
+
activesupport (= 8.0.1)
|
198
|
+
bundler (>= 1.15.0)
|
199
|
+
railties (= 8.0.1)
|
200
|
+
rails-dom-testing (2.2.0)
|
201
|
+
activesupport (>= 5.0.0)
|
202
|
+
minitest
|
203
|
+
nokogiri (>= 1.6)
|
204
|
+
rails-html-sanitizer (1.6.2)
|
205
|
+
loofah (~> 2.21)
|
206
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
207
|
+
railties (8.0.1)
|
208
|
+
actionpack (= 8.0.1)
|
209
|
+
activesupport (= 8.0.1)
|
210
|
+
irb (~> 1.13)
|
211
|
+
rackup (>= 1.0.0)
|
212
|
+
rake (>= 12.2)
|
213
|
+
thor (~> 1.0, >= 1.2.2)
|
214
|
+
zeitwerk (~> 2.6)
|
215
|
+
rainbow (3.1.1)
|
216
|
+
rake (13.2.1)
|
217
|
+
rdoc (6.12.0)
|
218
|
+
psych (>= 4.0.0)
|
219
|
+
regexp_parser (2.10.0)
|
220
|
+
reline (0.6.0)
|
221
|
+
io-console (~> 0.5)
|
222
|
+
rspec (3.13.0)
|
223
|
+
rspec-core (~> 3.13.0)
|
224
|
+
rspec-expectations (~> 3.13.0)
|
225
|
+
rspec-mocks (~> 3.13.0)
|
226
|
+
rspec-core (3.13.3)
|
227
|
+
rspec-support (~> 3.13.0)
|
228
|
+
rspec-expectations (3.13.3)
|
229
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
230
|
+
rspec-support (~> 3.13.0)
|
231
|
+
rspec-mocks (3.13.2)
|
232
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
233
|
+
rspec-support (~> 3.13.0)
|
234
|
+
rspec-support (3.13.2)
|
235
|
+
rubocop (1.73.1)
|
236
|
+
json (~> 2.3)
|
237
|
+
language_server-protocol (~> 3.17.0.2)
|
238
|
+
lint_roller (~> 1.1.0)
|
239
|
+
parallel (~> 1.10)
|
240
|
+
parser (>= 3.3.0.2)
|
241
|
+
rainbow (>= 2.2.2, < 4.0)
|
242
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
243
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
244
|
+
ruby-progressbar (~> 1.7)
|
245
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
246
|
+
rubocop-ast (1.38.1)
|
247
|
+
parser (>= 3.3.1.0)
|
248
|
+
rubocop-packaging (0.5.2)
|
249
|
+
rubocop (>= 1.33, < 2.0)
|
250
|
+
rubocop-performance (1.24.0)
|
251
|
+
lint_roller (~> 1.1)
|
252
|
+
rubocop (>= 1.72.1, < 2.0)
|
253
|
+
rubocop-ast (>= 1.38.0, < 2.0)
|
254
|
+
rubocop-rspec (3.5.0)
|
255
|
+
lint_roller (~> 1.1)
|
256
|
+
rubocop (~> 1.72, >= 1.72.1)
|
257
|
+
rubocop-shopify (2.15.1)
|
258
|
+
rubocop (~> 1.51)
|
259
|
+
rubocop-thread_safety (0.7.0)
|
260
|
+
lint_roller (~> 1.1)
|
261
|
+
rubocop (~> 1.72, >= 1.72.1)
|
262
|
+
ruby-progressbar (1.13.0)
|
263
|
+
securerandom (0.4.1)
|
264
|
+
stringio (3.1.5)
|
265
|
+
thor (1.3.2)
|
266
|
+
timeout (0.4.3)
|
267
|
+
tzinfo (2.0.6)
|
268
|
+
concurrent-ruby (~> 1.0)
|
269
|
+
unicode-display_width (3.1.4)
|
270
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
271
|
+
unicode-emoji (4.0.4)
|
272
|
+
uri (1.0.3)
|
273
|
+
useragent (0.16.11)
|
274
|
+
websocket-driver (0.7.7)
|
275
|
+
base64
|
276
|
+
websocket-extensions (>= 0.1.0)
|
277
|
+
websocket-extensions (0.1.5)
|
278
|
+
zeitwerk (2.7.2)
|
279
|
+
|
280
|
+
PLATFORMS
|
281
|
+
aarch64-linux-gnu
|
282
|
+
aarch64-linux-musl
|
283
|
+
arm-linux-gnu
|
284
|
+
arm-linux-musl
|
285
|
+
arm64-darwin
|
286
|
+
x86_64-darwin
|
287
|
+
x86_64-linux-gnu
|
288
|
+
x86_64-linux-musl
|
289
|
+
|
290
|
+
DEPENDENCIES
|
291
|
+
pry (~> 0.15.2)
|
292
|
+
rspec (~> 3.0)
|
293
|
+
rubocop (~> 1.73, >= 1.73.1)
|
294
|
+
rubocop-packaging (~> 0.5.2)
|
295
|
+
rubocop-performance (~> 1.24)
|
296
|
+
rubocop-rspec (~> 3.5)
|
297
|
+
rubocop-shopify (~> 2.15, >= 2.15.1)
|
298
|
+
rubocop-thread_safety (~> 0.7.0)
|
299
|
+
spec_guardian!
|
300
|
+
|
301
|
+
RUBY VERSION
|
302
|
+
ruby 3.3.6p108
|
303
|
+
|
304
|
+
BUNDLED WITH
|
305
|
+
2.6.3
|
data/LICENSE.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Darren Terhune
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# SpecGuardian
|
2
|
+
|
3
|
+
A Ruby gem that uses AI (Claude) to automatically generate test files for your Rails application code.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'spec_guardian'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
gem install spec_guardian
|
23
|
+
```
|
24
|
+
|
25
|
+
## Configuration
|
26
|
+
|
27
|
+
Create an initializer file at `config/initializers/spec_guardian.rb` by running the install command to create this file `rails g spec_guardian:install`
|
28
|
+
|
29
|
+
```ruby
|
30
|
+
SpecGuardian.configure do |config|
|
31
|
+
config.api_key = ENV['ANTHROPIC_API_KEY'] # Your Anthropic API key
|
32
|
+
config.ai_model = "claude-3-7-sonnet-20250219" # The Claude model to use
|
33
|
+
config.max_tokens = 20_000 # The max tokens to use per request defaults to 20_000
|
34
|
+
config.test_style = "thorough" # Options: minimal, thorough, edge_cases
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
NOTE: The `max_tokens` determines the length of the response. If you are seeing files cut off, then you need to increase this value.
|
39
|
+
|
40
|
+
Ensure you have your Anthropic API key set as an environment variable or directly in the configuration. You can signup here https://console.anthropic.com to generate an account and get an API key.
|
41
|
+
|
42
|
+
## Usage
|
43
|
+
|
44
|
+
### Command Line
|
45
|
+
|
46
|
+
You can use the executable to generate a test for any file in your Rails application:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
bundle exec spec_guardian app/models/user.rb
|
50
|
+
```
|
51
|
+
|
52
|
+
During testing, models files with around 200-300 lines of code cost around $0.02. This will vary of course depending on how complex your code is. If you have rubocop installed you may need to adjust specs. It also isn't 100% accurate with generating perfect code so expect to look over the files it generates and be ready to fix things.
|
53
|
+
|
54
|
+
### Rake Task
|
55
|
+
|
56
|
+
Alternatively, you can use the provided Rake task:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
bundle exec rake spec_guardian:generate[app/models/user.rb]
|
60
|
+
```
|
61
|
+
|
62
|
+
If you are using zsh you may need to quote your input:
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
bundle exec rake spec_guardian:generate['app/models/user.rb']
|
66
|
+
```
|
67
|
+
|
68
|
+
## Features
|
69
|
+
|
70
|
+
1. Automatically detects whether your application uses RSpec or Minitest
|
71
|
+
2. Places generated test files in the appropriate location (spec/ or test/ directory)
|
72
|
+
3. Customizes test generation based on file type (model, controller, etc.)
|
73
|
+
4. Supports different test styles (minimal, thorough, or edge_cases)
|
74
|
+
|
75
|
+
## How It Works
|
76
|
+
|
77
|
+
1. The gem detects your project's test framework (RSpec, Minitest, or Rails default)
|
78
|
+
2. It analyzes the source file to determine its type (model, controller, etc.)
|
79
|
+
3. It sends the source code to Claude's API with a specialized prompt
|
80
|
+
4. It creates the test file in the correct location with the AI-generated test code
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/darrenterhune/spec_guardian.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'bundler/setup'
|
5
|
+
require 'spec_guardian'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
require 'irb'
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/bin/spec_guardian
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'spec_guardian'
|
5
|
+
|
6
|
+
# Parse command line arguments
|
7
|
+
if ARGV.empty? || ARGV[0] == '--help' || ARGV[0] == '-h'
|
8
|
+
puts 'Usage: spec_guardian PATH_TO_FILE'
|
9
|
+
puts 'Generates a test file for the given source file using AI.'
|
10
|
+
exit 0
|
11
|
+
end
|
12
|
+
|
13
|
+
begin
|
14
|
+
# Initialize Rails environment
|
15
|
+
require File.expand_path('config/environment', Dir.pwd)
|
16
|
+
|
17
|
+
# Generate the test
|
18
|
+
SpecGuardian.generate_test(ARGV[0])
|
19
|
+
rescue LoadError => e
|
20
|
+
puts 'Error: This command must be run from a Rails application root directory.'
|
21
|
+
exit 1
|
22
|
+
rescue SpecGuardian::Error => e
|
23
|
+
puts "Error: #{e.message}"
|
24
|
+
exit 1
|
25
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module SpecGuardian
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
8
|
+
def copy_config
|
9
|
+
template('config/initializers/spec_guardian.rb')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,7 @@
|
|
1
|
+
# config/initializers/spec_guardian.rb
|
2
|
+
SpecGuardian.configure do |config|
|
3
|
+
config.api_key = ENV['ANTHROPIC_API_KEY'] # Your Anthropic API key
|
4
|
+
config.ai_model = 'claude-3-7-sonnet-20250219' # The Claude model to use
|
5
|
+
config.max_tokens = 20_000 # The max tokens to use per request defaults to 20_000
|
6
|
+
config.test_style = 'thorough' # Options: minimal, thorough, edge_cases
|
7
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'anthropic'
|
2
|
+
|
3
|
+
module SpecGuardian
|
4
|
+
class AiClient
|
5
|
+
def self.generate_test(source_code, framework, file_path)
|
6
|
+
client = Anthropic::Client.new(
|
7
|
+
access_token: SpecGuardian.configuration.api_key
|
8
|
+
)
|
9
|
+
|
10
|
+
# File type detection
|
11
|
+
file_type = detect_file_type(file_path)
|
12
|
+
|
13
|
+
# Create the prompt
|
14
|
+
prompt = create_prompt(source_code, framework, file_type)
|
15
|
+
model = SpecGuardian.configuration.ai_model
|
16
|
+
max_tokens = SpecGuardian.configuration.max_tokens || 20_000
|
17
|
+
|
18
|
+
# Make API call
|
19
|
+
response = client.messages(
|
20
|
+
parameters: {
|
21
|
+
model: model,
|
22
|
+
max_tokens: max_tokens,
|
23
|
+
messages: [
|
24
|
+
{
|
25
|
+
role: 'user',
|
26
|
+
content: prompt
|
27
|
+
}
|
28
|
+
]
|
29
|
+
}
|
30
|
+
)
|
31
|
+
|
32
|
+
# Extract and return the test code
|
33
|
+
response['content'][0]['text']
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.detect_file_type(file_path)
|
37
|
+
if file_path.include?('/models/')
|
38
|
+
:model
|
39
|
+
elsif file_path.include?('/controllers/')
|
40
|
+
:controller
|
41
|
+
elsif file_path.include?('/views/')
|
42
|
+
:view
|
43
|
+
elsif file_path.include?('/helpers/')
|
44
|
+
:helper
|
45
|
+
elsif file_path.include?('/mailers/')
|
46
|
+
:mailer
|
47
|
+
elsif file_path.include?('/jobs/')
|
48
|
+
:job
|
49
|
+
else
|
50
|
+
:other
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.create_prompt(source_code, framework, file_type)
|
55
|
+
framework_name = framework == :rspec ? 'RSpec' : 'Minitest'
|
56
|
+
style = SpecGuardian.configuration.test_style
|
57
|
+
|
58
|
+
<<~PROMPT
|
59
|
+
Generate a comprehensive Rails #{framework_name} test for the following #{file_type} code.
|
60
|
+
The test should follow best practices for Rails testing with #{framework_name}.
|
61
|
+
|
62
|
+
Test style preference: #{style}
|
63
|
+
|
64
|
+
Here's the source code to test:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
#{source_code}
|
68
|
+
```
|
69
|
+
|
70
|
+
Please generate only the test code without any explanations. The output should be valid Ruby that can be saved directly to a test file. Remove comments. Do not include code formatting markdown like '```ruby'. Do not test rails internals like associations, scopes or table columns.
|
71
|
+
PROMPT
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module SpecGuardian
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :api_key, :ai_model, :test_style, :max_tokens
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@api_key = ENV['ANTHROPIC_API_KEY']
|
7
|
+
@ai_model = 'claude-3-7-sonnet-20250219'
|
8
|
+
@max_tokens = 20_000
|
9
|
+
@test_style = 'thorough' # Options: minimal, thorough, edge_cases
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module SpecGuardian
|
4
|
+
class FilePathResolver
|
5
|
+
def self.resolve(file_path, framework)
|
6
|
+
# Remove leading ./ if present
|
7
|
+
file_path = file_path.sub(%r{^\./}, '')
|
8
|
+
|
9
|
+
# Extract the relative path from app/
|
10
|
+
relative_path = if file_path.start_with?('app/')
|
11
|
+
file_path.sub(%r{^app/}, '')
|
12
|
+
else
|
13
|
+
file_path
|
14
|
+
end
|
15
|
+
|
16
|
+
# Determine test directory based on framework
|
17
|
+
test_dir = framework == :rspec ? 'spec' : 'test'
|
18
|
+
|
19
|
+
# Handle different file types
|
20
|
+
if relative_path.start_with?('models/')
|
21
|
+
"#{test_dir}/#{relative_path.sub(/\.rb$/, '_spec.rb')}"
|
22
|
+
elsif relative_path.start_with?('controllers/')
|
23
|
+
"#{test_dir}/#{relative_path.sub(/\.rb$/, '_spec.rb')}"
|
24
|
+
elsif relative_path.start_with?('views/')
|
25
|
+
view_path = relative_path.sub(%r{^views/}, '')
|
26
|
+
"#{test_dir}/views/#{view_path.sub(/\.\w+\.erb$/, '.html_spec.rb')}"
|
27
|
+
else
|
28
|
+
# For other files, maintain the same structure
|
29
|
+
"#{test_dir}/#{relative_path.sub(/\.rb$/, '_spec.rb')}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module SpecGuardian
|
2
|
+
class TestFrameworkDetector
|
3
|
+
def self.detect
|
4
|
+
return :rspec if File.exist?('spec') && gemfile_includes?('rspec')
|
5
|
+
|
6
|
+
return :minitest if File.exist?('test') && gemfile_includes?('minitest')
|
7
|
+
|
8
|
+
if Rails.version.to_i >= 5
|
9
|
+
:minitest
|
10
|
+
else
|
11
|
+
:test_unit
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.gemfile_includes?(gem_name)
|
16
|
+
return false unless File.exist?('Gemfile')
|
17
|
+
|
18
|
+
File.read('Gemfile').include?(gem_name)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'spec_guardian/version'
|
4
|
+
require_relative 'spec_guardian/configuration'
|
5
|
+
require_relative 'spec_guardian/test_framework_detector'
|
6
|
+
require_relative 'spec_guardian/file_path_resolver'
|
7
|
+
require_relative 'spec_guardian/ai_client'
|
8
|
+
|
9
|
+
module SpecGuardian
|
10
|
+
class Error < StandardError; end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
attr_accessor :configuration
|
14
|
+
|
15
|
+
def configure
|
16
|
+
self.configuration ||= Configuration.new
|
17
|
+
yield(configuration) if block_given?
|
18
|
+
end
|
19
|
+
|
20
|
+
def generate_test(file_path)
|
21
|
+
# Validate the file exists
|
22
|
+
raise Error, "File not found: #{file_path}" unless File.exist?(file_path)
|
23
|
+
|
24
|
+
# Detect the test framework
|
25
|
+
framework = TestFrameworkDetector.detect
|
26
|
+
|
27
|
+
# Resolve the test file path
|
28
|
+
test_file_path = FilePathResolver.resolve(file_path, framework)
|
29
|
+
|
30
|
+
# Generate the test content
|
31
|
+
source_code = File.read(file_path)
|
32
|
+
test_content = AiClient.generate_test(source_code, framework, file_path)
|
33
|
+
|
34
|
+
# Create the test file
|
35
|
+
FileUtils.mkdir_p(File.dirname(test_file_path))
|
36
|
+
File.write(test_file_path, test_content)
|
37
|
+
|
38
|
+
puts "Test file generated: #{test_file_path}"
|
39
|
+
test_file_path
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
require 'spec_guardian/railtie' if defined?(Rails)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :spec_guardian do
|
2
|
+
desc 'Generate a test file for a given source file using AI'
|
3
|
+
task :generate, [:file_path] => :environment do |t, args|
|
4
|
+
if args[:file_path].nil?
|
5
|
+
puts 'Error: Please provide a file path.'
|
6
|
+
puts 'Usage: rake spec_guardian:generate[app/models/user.rb]'
|
7
|
+
puts "You may need to use quotes if using zsh e.g. ['app/models/user.rb']"
|
8
|
+
exit 1
|
9
|
+
end
|
10
|
+
|
11
|
+
SpecGuardian.generate_test(args[:file_path])
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/spec_guardian/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'spec_guardian'
|
7
|
+
spec.version = SpecGuardian::VERSION
|
8
|
+
spec.platform = Gem::Platform::RUBY
|
9
|
+
spec.authors = ['Darren Terhune']
|
10
|
+
spec.email = ['darrenterhune@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Generate test files for Rails apps using AI'
|
13
|
+
spec.description = 'A gem that uses AI to automatically generate test files for your Rails application code'
|
14
|
+
spec.homepage = 'https://github.com/darrenterhune/spec_guardian'
|
15
|
+
spec.license = 'MIT'
|
16
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 3.1.6')
|
17
|
+
|
18
|
+
spec.metadata = {
|
19
|
+
'bug_tracker_uri' => 'https://github.com/darrenterhune/spec_guardian/issues',
|
20
|
+
'changelog_uri' => "#{spec.homepage}/blob/main/CHANGELOG.md",
|
21
|
+
'homepage_uri' => 'https://github.com/darrenterhune/spec_guardian',
|
22
|
+
'source_code_uri' => 'https://github.com/darrenterhune/spec_guardian'
|
23
|
+
}
|
24
|
+
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = 'bin'
|
29
|
+
spec.executables = ['spec_guardian']
|
30
|
+
spec.require_paths = ['lib']
|
31
|
+
|
32
|
+
spec.add_dependency 'anthropic', '>= 0.3.2'
|
33
|
+
spec.add_dependency 'rails', '>= 6.0'
|
34
|
+
spec.add_dependency 'rake', '>= 12.0'
|
35
|
+
spec.add_dependency 'thor', '>= 1.2'
|
36
|
+
spec.add_development_dependency 'pry', '~> 0.15.2'
|
37
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
38
|
+
spec.add_development_dependency 'rubocop', '~> 1.73', '>= 1.73.1'
|
39
|
+
spec.add_development_dependency 'rubocop-packaging', '~> 0.5.2'
|
40
|
+
spec.add_development_dependency 'rubocop-performance', '~> 1.24'
|
41
|
+
spec.add_development_dependency 'rubocop-rspec', '~> 3.5'
|
42
|
+
spec.add_development_dependency 'rubocop-shopify', '~> 2.15', '>= 2.15.1'
|
43
|
+
spec.add_development_dependency 'rubocop-thread_safety', '~> 0.7.0'
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,256 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: spec_guardian
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Darren Terhune
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2025-03-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: anthropic
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.3.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.3.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rails
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '6.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '6.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '12.0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '12.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: thor
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.2'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.15.2
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.15.2
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '1.73'
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.73.1
|
107
|
+
type: :development
|
108
|
+
prerelease: false
|
109
|
+
version_requirements: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: '1.73'
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 1.73.1
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: rubocop-packaging
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 0.5.2
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - "~>"
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: 0.5.2
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: rubocop-performance
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '1.24'
|
138
|
+
type: :development
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.24'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: rubocop-rspec
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - "~>"
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '3.5'
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - "~>"
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '3.5'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: rubocop-shopify
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '2.15'
|
166
|
+
- - ">="
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: 2.15.1
|
169
|
+
type: :development
|
170
|
+
prerelease: false
|
171
|
+
version_requirements: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - "~>"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '2.15'
|
176
|
+
- - ">="
|
177
|
+
- !ruby/object:Gem::Version
|
178
|
+
version: 2.15.1
|
179
|
+
- !ruby/object:Gem::Dependency
|
180
|
+
name: rubocop-thread_safety
|
181
|
+
requirement: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - "~>"
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: 0.7.0
|
186
|
+
type: :development
|
187
|
+
prerelease: false
|
188
|
+
version_requirements: !ruby/object:Gem::Requirement
|
189
|
+
requirements:
|
190
|
+
- - "~>"
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: 0.7.0
|
193
|
+
description: A gem that uses AI to automatically generate test files for your Rails
|
194
|
+
application code
|
195
|
+
email:
|
196
|
+
- darrenterhune@gmail.com
|
197
|
+
executables:
|
198
|
+
- spec_guardian
|
199
|
+
extensions: []
|
200
|
+
extra_rdoc_files: []
|
201
|
+
files:
|
202
|
+
- ".DS_Store"
|
203
|
+
- ".gitignore"
|
204
|
+
- ".prettierrc"
|
205
|
+
- ".rspec"
|
206
|
+
- ".rubocop.yml"
|
207
|
+
- ".ruby-version"
|
208
|
+
- CHANGELOG.md
|
209
|
+
- Gemfile
|
210
|
+
- Gemfile.lock
|
211
|
+
- LICENSE.md
|
212
|
+
- README.md
|
213
|
+
- Rakefile
|
214
|
+
- bin/console
|
215
|
+
- bin/setup
|
216
|
+
- bin/spec_guardian
|
217
|
+
- lib/generators/spec_guardian/install_generator.rb
|
218
|
+
- lib/generators/spec_guardian/templates/config/initializers/spec_guardian.rb
|
219
|
+
- lib/spec_guardian.rb
|
220
|
+
- lib/spec_guardian/ai_client.rb
|
221
|
+
- lib/spec_guardian/configuration.rb
|
222
|
+
- lib/spec_guardian/file_path_resolver.rb
|
223
|
+
- lib/spec_guardian/railtie.rb
|
224
|
+
- lib/spec_guardian/test_framework_detector.rb
|
225
|
+
- lib/spec_guardian/version.rb
|
226
|
+
- lib/tasks/generate_tests.rake
|
227
|
+
- sig/spec_guardian.rbs
|
228
|
+
- spec_guardian.gemspec
|
229
|
+
homepage: https://github.com/darrenterhune/spec_guardian
|
230
|
+
licenses:
|
231
|
+
- MIT
|
232
|
+
metadata:
|
233
|
+
bug_tracker_uri: https://github.com/darrenterhune/spec_guardian/issues
|
234
|
+
changelog_uri: https://github.com/darrenterhune/spec_guardian/blob/main/CHANGELOG.md
|
235
|
+
homepage_uri: https://github.com/darrenterhune/spec_guardian
|
236
|
+
source_code_uri: https://github.com/darrenterhune/spec_guardian
|
237
|
+
post_install_message:
|
238
|
+
rdoc_options: []
|
239
|
+
require_paths:
|
240
|
+
- lib
|
241
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
242
|
+
requirements:
|
243
|
+
- - ">="
|
244
|
+
- !ruby/object:Gem::Version
|
245
|
+
version: 3.1.6
|
246
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - ">="
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '0'
|
251
|
+
requirements: []
|
252
|
+
rubygems_version: 3.5.22
|
253
|
+
signing_key:
|
254
|
+
specification_version: 4
|
255
|
+
summary: Generate test files for Rails apps using AI
|
256
|
+
test_files: []
|