jsonrpc-middleware 0.2.0 → 0.4.0
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/.aiexclude +1 -0
- data/.claude/commands/test.md +561 -0
- data/.claude/settings.local.json +2 -1
- data/.rubocop.yml +3 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +22 -2
- data/README.md +47 -18
- data/Rakefile +1 -3
- data/examples/README.md +2 -1
- data/examples/rack/Gemfile.lock +6 -6
- data/examples/rack/app.rb +1 -4
- data/examples/rack-echo/Gemfile.lock +6 -6
- data/examples/rack-echo/app.rb +1 -4
- data/examples/rack-single-file/config.ru +1 -4
- data/examples/rails/Gemfile.lock +4 -4
- data/examples/rails/app/controllers/jsonrpc_controller.rb +1 -4
- data/examples/rails-single-file/README.md +23 -0
- data/examples/rails-single-file/config.ru +1 -4
- data/examples/rails-single-file-routing/README.md +53 -0
- data/examples/rails-single-file-routing/config.ru +62 -0
- data/examples/sinatra-classic/Gemfile.lock +8 -8
- data/examples/sinatra-classic/app.rb +1 -6
- data/examples/sinatra-modular/Gemfile.lock +8 -8
- data/examples/sinatra-modular/app.rb +1 -4
- data/lib/jsonrpc/batch_request.rb +32 -0
- data/lib/jsonrpc/railtie/method_constraint.rb +35 -0
- data/lib/jsonrpc/railtie.rb +1 -0
- data/lib/jsonrpc/version.rb +1 -1
- data/lib/jsonrpc.rb +7 -4
- metadata +10 -6
- data/examples/rails/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a45b1d353d7fd1547e7e984edba9c9ed1e02669914c00294d08f259cb5bb76e6
|
4
|
+
data.tar.gz: 25d2b7802a03378c90e181d5e5b580489299d41a3070817d762b43063a9d68b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3a417f6096c195940c782cb313f9b4e7a5e6ef2c1c6ed994a4d23e226e7a70ba7df4b635b03c56f392983b45b1d0239f0a121c2b2982101c5ad5c47680bd7f8
|
7
|
+
data.tar.gz: 601bc95a7d965e6721af683765881d73ac34fc5ced0791c398b1ddc4acff054b586d0c74ab0107bf139bb177afcebc760460d96cb86896afec1394972b98b6d9
|
data/.aiexclude
CHANGED
@@ -0,0 +1,561 @@
|
|
1
|
+
# Test
|
2
|
+
|
3
|
+
Write RSpec tests for a given file, module, class or method. Ensure it meets the guidelines. If the file already has
|
4
|
+
tests, simply review the test guidelines.
|
5
|
+
|
6
|
+
## Best Practices
|
7
|
+
|
8
|
+
### Describe Your Methods
|
9
|
+
|
10
|
+
Be clear about what method you are describing. For instance, use the Ruby documentation convention of `.` when
|
11
|
+
referring to a class method's name and `#` when referring to an instance method's name.
|
12
|
+
|
13
|
+
**bad**
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
describe 'the authenticate method for User' do
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'if the user is an admin' do
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
**good**
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
describe '.authenticate' do
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#admin?' do
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
### Use contexts
|
34
|
+
|
35
|
+
Contexts are a powerful method to make your tests clear and well organized (they keep tests easy to read).
|
36
|
+
When describing a context, start its description with 'when', 'with' or 'without'.
|
37
|
+
|
38
|
+
**bad**
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
it 'has 200 status code if logged in' do
|
42
|
+
expect(response).to respond_with 200
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'has 401 status code if not logged in' do
|
46
|
+
expect(response).to respond_with 401
|
47
|
+
end
|
48
|
+
```
|
49
|
+
|
50
|
+
**good**
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
context 'when logged in' do
|
54
|
+
it { is_expected.to respond_with 200 }
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when logged out' do
|
58
|
+
it { is_expected.to respond_with 401 }
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
### Keep your description short
|
63
|
+
|
64
|
+
A spec description should never be longer than 40 characters. If this happens you should split it using a context.
|
65
|
+
In the example below, we removed the description related to the status code, which has been replaced by the
|
66
|
+
expectation `is_expected`. If you run this test typing `rspec filename` you will obtain a readable output.
|
67
|
+
|
68
|
+
**bad**
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
it 'has 422 status code if an unexpected params will be added' do
|
72
|
+
```
|
73
|
+
|
74
|
+
**good**
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
context 'when not valid' do
|
78
|
+
it { is_expected.to respond_with 422 }
|
79
|
+
end
|
80
|
+
```
|
81
|
+
|
82
|
+
**Formatted output**
|
83
|
+
|
84
|
+
```
|
85
|
+
when not valid
|
86
|
+
it should respond with 422
|
87
|
+
```
|
88
|
+
|
89
|
+
### Single expectation test
|
90
|
+
|
91
|
+
The 'one expectation' tip is more broadly expressed as 'each test should make only one assertion'. This helps you on
|
92
|
+
finding possible errors, going directly to the failing test, and to make your code readable. In isolated unit specs,
|
93
|
+
you want each example to specify one (and only one) behavior. Multiple expectations in the same example are a signal
|
94
|
+
that you may be specifying multiple behaviors.
|
95
|
+
|
96
|
+
**good (isolated)**
|
97
|
+
|
98
|
+
```ruby
|
99
|
+
it { is_expected.to respond_with_content_type(:json) }
|
100
|
+
it { is_expected.to assign_to(:resource) }
|
101
|
+
```
|
102
|
+
|
103
|
+
Anyway, in tests that are not isolated (e.g. ones that integrate with a DB, an external webservice, or
|
104
|
+
end-to-end-tests), you take a massive performance hit to do the same setup over and over again, just to set a different
|
105
|
+
expectation in each test. In these sorts of slower tests, I think it's fine to specify more than one isolated behavior.
|
106
|
+
|
107
|
+
**good (not isolated)**
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
it 'creates a resource' do
|
111
|
+
expect(response).to respond_with_content_type(:json)
|
112
|
+
expect(response).to assign_to(:resource)
|
113
|
+
end
|
114
|
+
```
|
115
|
+
|
116
|
+
### Test all possible cases
|
117
|
+
|
118
|
+
Testing is a good practice, but if you do not test the edge cases, it will not be useful. Test valid, edge and invalid
|
119
|
+
case. For example, consider the following action.
|
120
|
+
|
121
|
+
**Destroy Action**
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
before_action :find_owned_resources
|
125
|
+
before_action :find_resource
|
126
|
+
|
127
|
+
def destroy
|
128
|
+
render 'show'
|
129
|
+
@consumption.destroy
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
The error I usually see lies in testing only whether the resource has been removed. But there are at least two edge
|
134
|
+
cases: when the resource is not found and when it's not owned. As a rule of thumb think of all the possible inputs
|
135
|
+
and test them.
|
136
|
+
|
137
|
+
**bad**
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
it 'shows the resource'
|
141
|
+
```
|
142
|
+
|
143
|
+
**good**
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
describe '#destroy' do
|
147
|
+
context 'when resource is found' do
|
148
|
+
it 'responds with 200'
|
149
|
+
it 'shows the resource'
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'when resource is not found' do
|
153
|
+
it 'responds with 404'
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'when resource is not owned' do
|
157
|
+
it 'responds with 404'
|
158
|
+
end
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
### Expect vs Should syntax
|
163
|
+
|
164
|
+
On new projects always use the `expect` syntax.
|
165
|
+
|
166
|
+
**bad**
|
167
|
+
|
168
|
+
```ruby
|
169
|
+
it 'creates a resource' do
|
170
|
+
response.should respond_with_content_type(:json)
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
**good**
|
175
|
+
|
176
|
+
```ruby
|
177
|
+
it 'creates a resource' do
|
178
|
+
expect(response).to respond_with_content_type(:json)
|
179
|
+
end
|
180
|
+
```
|
181
|
+
|
182
|
+
Configure the RSpec to only accept the new syntax on new projects, to avoid having the 2 syntax all over the place.
|
183
|
+
|
184
|
+
**good**
|
185
|
+
|
186
|
+
```ruby
|
187
|
+
# spec_helper.rb
|
188
|
+
RSpec.configure do |config|
|
189
|
+
# ...
|
190
|
+
config.expect_with :rspec do |c|
|
191
|
+
c.syntax = :expect
|
192
|
+
end
|
193
|
+
end
|
194
|
+
```
|
195
|
+
|
196
|
+
On one line expectations or with implicit subject we should use `is_expected.to`.
|
197
|
+
|
198
|
+
**bad**
|
199
|
+
|
200
|
+
```ruby
|
201
|
+
context 'when not valid' do
|
202
|
+
it { should respond_with 422 }
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
**good**
|
207
|
+
|
208
|
+
```ruby
|
209
|
+
context 'when not valid' do
|
210
|
+
it { is_expected.to respond_with 422 }
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
### Use subject
|
215
|
+
|
216
|
+
If you have several tests related to the same subject use `subject{}` to DRY them up.
|
217
|
+
|
218
|
+
**bad**
|
219
|
+
|
220
|
+
```ruby
|
221
|
+
it { expect(assigns('message')).to match /it was born in Bellville/ }
|
222
|
+
```
|
223
|
+
|
224
|
+
**good**
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
subject { assigns('message') }
|
228
|
+
|
229
|
+
it { is_expected.to match /it was born in Billville/ }
|
230
|
+
```
|
231
|
+
|
232
|
+
RSpec has also the ability to use a named subject (learn more about [rspec subject](https://rspec.info/features/3-12/rspec-core/subject/)).
|
233
|
+
|
234
|
+
**good**
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
subject(:hero) { Hero.first }
|
238
|
+
|
239
|
+
it 'carries a sword' do
|
240
|
+
expect(hero.equipment).to include 'sword'
|
241
|
+
end
|
242
|
+
```
|
243
|
+
|
244
|
+
### Use let and let!
|
245
|
+
|
246
|
+
When you have to assign a variable instead of using a `before` block to create an instance variable, use `let`. Using
|
247
|
+
`let` the variable lazy loads only when it is used the first time in the test and get cached until that specific test
|
248
|
+
is finished. A really good and deep description of what `let` does can be found in this
|
249
|
+
[stackoverflow answer](http://stackoverflow.com/questions/5359558/when-to-use-rspec-let/5359979#5359979).
|
250
|
+
|
251
|
+
**bad**
|
252
|
+
|
253
|
+
```ruby
|
254
|
+
describe '#type_id' do
|
255
|
+
before { @resource = FactoryBot.create :device }
|
256
|
+
before { @type = Type.find @resource.type_id }
|
257
|
+
|
258
|
+
it 'sets the type_id field' do
|
259
|
+
expect(@resource.type_id).to eq(@type.id)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
```
|
263
|
+
|
264
|
+
**good**
|
265
|
+
|
266
|
+
```ruby
|
267
|
+
describe '#type_id' do
|
268
|
+
let(:resource) { FactoryBot.create :device }
|
269
|
+
let(:type) { Type.find resource.type_id }
|
270
|
+
|
271
|
+
it 'sets the type_id field' do
|
272
|
+
expect(resource.type_id).to eq(type.id)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
```
|
276
|
+
|
277
|
+
Use `let` to initialize actions that are lazy loaded to test your specs.
|
278
|
+
|
279
|
+
**good**
|
280
|
+
|
281
|
+
```ruby
|
282
|
+
context 'when updates a not existing property value' do
|
283
|
+
let(:properties) { { id: Settings.resource_id, value: 'on' } }
|
284
|
+
|
285
|
+
def update
|
286
|
+
resource.properties = properties
|
287
|
+
end
|
288
|
+
|
289
|
+
it 'raises a not found error' do
|
290
|
+
expect { update }.to raise_error Mongoid::Errors::DocumentNotFound
|
291
|
+
end
|
292
|
+
end
|
293
|
+
```
|
294
|
+
|
295
|
+
Use `let!` if you want to define the variable when the block is defined. This can be useful to populate your database
|
296
|
+
to test queries or scopes. Here an example of what let actually is (learn more about
|
297
|
+
[rspec let](https://rspec.info/features/3-12/rspec-core/helper-methods/let/)).
|
298
|
+
|
299
|
+
**Explanation**
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
# this use of let
|
303
|
+
let(:foo) { Foo.new }
|
304
|
+
|
305
|
+
# is very nearly equivalent to this:
|
306
|
+
def foo
|
307
|
+
@foo ||= Foo.new
|
308
|
+
end
|
309
|
+
```
|
310
|
+
|
311
|
+
### Mock or not to mock
|
312
|
+
|
313
|
+
As general rule do not (over)use mocks and test real behavior when possible, as testing real cases is useful when
|
314
|
+
validating your application flow.
|
315
|
+
|
316
|
+
**good**
|
317
|
+
|
318
|
+
```ruby
|
319
|
+
# simulate a not found resource
|
320
|
+
context 'when not found' do
|
321
|
+
before do
|
322
|
+
allow(Resource).to receive(:where).with(created_from: params[:id]).and_return(false)
|
323
|
+
end
|
324
|
+
|
325
|
+
it { is_expected.to respond_with 404 }
|
326
|
+
end
|
327
|
+
```
|
328
|
+
|
329
|
+
Mocking makes your specs faster but they are difficult to use. You need to understand them well to use them well. Read
|
330
|
+
[this article](https://web.archive.org/web/20220612005103/http://myronmars.to/n/dev-blog/2012/06/thoughts-on-mocking)
|
331
|
+
to learn more about mocks.
|
332
|
+
|
333
|
+
### Create only the data you need
|
334
|
+
|
335
|
+
If you have ever worked in a medium size project (but also in small ones), test suites can be heavy to run. To solve
|
336
|
+
this problem, it's important not to load more data than needed. Also, if you think you need dozens of records, you are
|
337
|
+
probably wrong.
|
338
|
+
|
339
|
+
**good**
|
340
|
+
|
341
|
+
```ruby
|
342
|
+
describe 'User' do
|
343
|
+
describe '.top' do
|
344
|
+
before { FactoryBot.create_list(:user, 3) }
|
345
|
+
|
346
|
+
it { expect(User.top(2)).to have(2).items }
|
347
|
+
end
|
348
|
+
end
|
349
|
+
```
|
350
|
+
|
351
|
+
### Use factories and not fixtures
|
352
|
+
|
353
|
+
This is an old topic, but it's still good to remember it. Do not use fixtures because they are difficult to control,
|
354
|
+
use factories instead. Use them to reduce the verbosity on creating new data (learn about
|
355
|
+
[Factory Bot](https://github.com/thoughtbot/factory_bot)).
|
356
|
+
|
357
|
+
**bad**
|
358
|
+
|
359
|
+
```ruby
|
360
|
+
user = User.create(
|
361
|
+
name: 'Genoveffa',
|
362
|
+
surname: 'Piccolina',
|
363
|
+
city: 'Billyville',
|
364
|
+
birth: '17 August 1982',
|
365
|
+
active: true
|
366
|
+
)
|
367
|
+
```
|
368
|
+
|
369
|
+
**good**
|
370
|
+
|
371
|
+
```ruby
|
372
|
+
user = FactoryBot.create :user
|
373
|
+
```
|
374
|
+
|
375
|
+
One important note. When talking about unit tests the best practice would be to use neither fixtures or factories. Put
|
376
|
+
as much of your domain logic in libraries that can be tested without needing complex, time consuming setup with either
|
377
|
+
factories or fixtures. Read more in
|
378
|
+
[this article](http://blog.steveklabnik.com/posts/2012-07-14-why-i-don-t-like-factory_girl).
|
379
|
+
|
380
|
+
### Easy to read matchers
|
381
|
+
|
382
|
+
Use readable matchers and double check the available
|
383
|
+
[rspec matchers](https://rspec.info/features/3-12/rspec-expectations/built-in-matchers/).
|
384
|
+
|
385
|
+
**bad**
|
386
|
+
|
387
|
+
```ruby
|
388
|
+
lambda { model.save! }.to raise_error Mongoid::Errors::DocumentNotFound
|
389
|
+
```
|
390
|
+
|
391
|
+
**good**
|
392
|
+
|
393
|
+
```ruby
|
394
|
+
expect { model.save! }.to raise_error Mongoid::Errors::DocumentNotFound
|
395
|
+
```
|
396
|
+
|
397
|
+
### Shared examples
|
398
|
+
|
399
|
+
Avoid shared examples.
|
400
|
+
|
401
|
+
### Test what you see
|
402
|
+
|
403
|
+
Deeply test your models and your application behaviour (integration tests). Do not add useless complexity testing
|
404
|
+
controllers.
|
405
|
+
|
406
|
+
When I first started testing my apps I was testing controllers, now I don't. Now I only create integration tests using
|
407
|
+
RSpec and Capybara. Why? Because I believe that you should test what you see and because testing controllers is an
|
408
|
+
extra step you wont usually need. You'll find out that most of your tests go into the models and that integration
|
409
|
+
tests can be easily grouped into shared examples, building a clear and readable test suite.
|
410
|
+
|
411
|
+
This is an open debate in the Ruby community and both sides have good arguments supporting their idea. People
|
412
|
+
supporting the need of testing controllers will tell you that your integration tests don't cover all use cases and that
|
413
|
+
they are slow. Both are wrong. You can easily cover all use cases (why shouldn't you?) and you can run single file specs
|
414
|
+
using automated tools like Guard. In this way you will run only the specs you need to test blazing fast without stopping
|
415
|
+
your flow.
|
416
|
+
|
417
|
+
### Don't use should
|
418
|
+
|
419
|
+
Do not use should when describing your tests. Use the third person in the present tense. Even better start using the
|
420
|
+
new [expectation](http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/) syntax.
|
421
|
+
|
422
|
+
**bad**
|
423
|
+
|
424
|
+
```ruby
|
425
|
+
it 'should not change timings' do
|
426
|
+
consumption.occur_at.should == valid.occur_at
|
427
|
+
end
|
428
|
+
```
|
429
|
+
|
430
|
+
**good**
|
431
|
+
|
432
|
+
```ruby
|
433
|
+
it 'does not change timings' do
|
434
|
+
expect(consumption.occur_at).to eq(valid.occur_at)
|
435
|
+
end
|
436
|
+
```
|
437
|
+
|
438
|
+
See [the should_not gem](https://github.com/should-not/should_not) for a way to enforce this in RSpec and
|
439
|
+
[the should_clean](https://github.com/siyelo/should_clean) gem for a way to clean up existing RSpec examples that begin
|
440
|
+
with 'should.'
|
441
|
+
|
442
|
+
### Stubbing HTTP requests
|
443
|
+
|
444
|
+
Sometimes you need to access external services. In these cases you can't rely on the real service but you should stub
|
445
|
+
it with solutions like webmock.
|
446
|
+
|
447
|
+
**good**
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
context 'with unauthorized access' do
|
451
|
+
let(:uri) { 'http://api.lelylan.com/types' }
|
452
|
+
|
453
|
+
before { stub_request(:get, uri).to_return(status: 401, body: fixture('401.json')) }
|
454
|
+
|
455
|
+
it 'gets a not authorized notification' do
|
456
|
+
page.driver.get uri
|
457
|
+
expect(page).to have_content 'Access denied'
|
458
|
+
end
|
459
|
+
end
|
460
|
+
```
|
461
|
+
|
462
|
+
Learn more about [webmock](https://github.com/bblimke/webmock) and [VCR](https://github.com/vcr/vcr). Here a
|
463
|
+
[nice presentation](http://marnen.github.io/webmock-presentation/webmock.html) explaining how to mix them together.
|
464
|
+
|
465
|
+
### Test Structure
|
466
|
+
|
467
|
+
Use the context-driven approach instead of inline conditions:
|
468
|
+
|
469
|
+
**Good:**
|
470
|
+
```ruby
|
471
|
+
describe '#method' do
|
472
|
+
context 'when a condition is met' do
|
473
|
+
it 'does something' do
|
474
|
+
# test implementation
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'when another condition is met' do
|
479
|
+
it 'does something else' do
|
480
|
+
# test implementation
|
481
|
+
end
|
482
|
+
end
|
483
|
+
end
|
484
|
+
```
|
485
|
+
|
486
|
+
**Avoid:**
|
487
|
+
```ruby
|
488
|
+
describe '#method' do
|
489
|
+
it 'does something when condition is met' do
|
490
|
+
# test implementation
|
491
|
+
end
|
492
|
+
|
493
|
+
it 'does something else when another condition is met' do
|
494
|
+
# test implementation
|
495
|
+
end
|
496
|
+
end
|
497
|
+
```
|
498
|
+
|
499
|
+
### AAA Pattern (Arrange, Act, Assert)
|
500
|
+
|
501
|
+
Structure each test using the AAA pattern with RSpec's `describe`, `context`, `let`, and `before` hooks:
|
502
|
+
|
503
|
+
```ruby
|
504
|
+
describe Calculator do
|
505
|
+
# Arrange - Set up test data using let and/or before blocks
|
506
|
+
let(:calculator) { described_class.new }
|
507
|
+
|
508
|
+
describe '#add' do
|
509
|
+
context 'when given positive numbers' do
|
510
|
+
it 'returns the sum' do
|
511
|
+
# Act - Execute the method being tested
|
512
|
+
result = calculator.add(2, 3)
|
513
|
+
|
514
|
+
# Assert - Verify the expected outcome
|
515
|
+
expect(result).to eq(5)
|
516
|
+
end
|
517
|
+
end
|
518
|
+
|
519
|
+
context 'when calculator is in debug mode' do
|
520
|
+
before do
|
521
|
+
# Arrange - Additional setup using before hook
|
522
|
+
calculator.enable_debug_mode
|
523
|
+
allow(calculator).to receive(:log).and_return(true)
|
524
|
+
end
|
525
|
+
|
526
|
+
it 'logs the operation' do
|
527
|
+
# Act
|
528
|
+
calculator.add(2, 3)
|
529
|
+
|
530
|
+
# Assert
|
531
|
+
expect(calculator).to have_received(:log).with('Adding 2 + 3')
|
532
|
+
end
|
533
|
+
|
534
|
+
it 'returns the sum' do
|
535
|
+
# Act
|
536
|
+
result = calculator.add(2, 3)
|
537
|
+
|
538
|
+
# Assert
|
539
|
+
expect(result).to eq(5)
|
540
|
+
end
|
541
|
+
end
|
542
|
+
end
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
## Guidelines
|
547
|
+
|
548
|
+
1. **Use descriptive context names** that describe the condition being tested
|
549
|
+
3. **Use blank lines** to separate Arrange, Act, and Assert sections
|
550
|
+
4. **Use let blocks** for shared setup data
|
551
|
+
5. **Use before blocks** for imperative setup (method calls, mocks, state changes)
|
552
|
+
6. **Use described_class** instead of the class name directly
|
553
|
+
7. **Describe one method per describe block** using Ruby documentation conventions (`#method` for instance methods, `.method` for class methods)
|
554
|
+
8. **Follow the existing codebase patterns** for consistency
|
555
|
+
|
556
|
+
## Running Tests
|
557
|
+
|
558
|
+
- Run all tests: `bundle exec rspec`
|
559
|
+
- Run specific file: `bundle exec rspec spec/path/to/file_spec.rb`
|
560
|
+
- Run with coverage: `COVERAGE=true bundle exec rspec`
|
561
|
+
|
data/.claude/settings.local.json
CHANGED
data/.rubocop.yml
CHANGED
data/.tool-versions
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby 3.4.
|
1
|
+
ruby 3.4.5
|
data/CHANGELOG.md
CHANGED
@@ -5,7 +5,26 @@ All notable changes to this project will be documented in this file.
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
7
|
|
8
|
-
## [
|
8
|
+
## [0.4.0] - 2025-07-18
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- JSONRPC::BatchRequest#process_each method for simplified batch processing
|
12
|
+
|
13
|
+
## [0.3.0] - 2025-07-17
|
14
|
+
|
15
|
+
### Added
|
16
|
+
- Rails routing support with method constraints for JSON-RPC procedures
|
17
|
+
- Rails single-file routing example application
|
18
|
+
- Method constraint helper for Rails routing integration
|
19
|
+
|
20
|
+
### Changed
|
21
|
+
- Updated Ruby to v3.4.5 across all environments
|
22
|
+
- Updated development dependencies (bundler, overcommit, rubocop, rubocop-yard)
|
23
|
+
- Updated examples dependencies to use latest versions
|
24
|
+
- Improved documentation for Rails single-file applications
|
25
|
+
|
26
|
+
### Fixed
|
27
|
+
- Standardized Ruby version usage across the project
|
9
28
|
|
10
29
|
## [0.2.0] - 2025-07-10
|
11
30
|
|
@@ -52,6 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
52
71
|
- Helper methods for request and response processing
|
53
72
|
- Examples for basic and advanced usage scenarios
|
54
73
|
|
55
|
-
[
|
74
|
+
[0.4.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.3.0...v0.4.0
|
75
|
+
[0.3.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.2.0...v0.3.0
|
56
76
|
[0.2.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/v0.1.0...v0.2.0
|
57
77
|
[0.1.0]: https://github.com/wilsonsilva/jsonrpc-middleware/compare/745b5a...v0.1.0
|