camille 1.5.0 → 1.6.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 901863ce3680f14f101ac00cac0ef9f6b64b84413f483e52e90583149eb54d80
4
- data.tar.gz: 309265868f68ea69fa5b5b3af60d43813ec8f8602abb8fc8f49c089c7c94fea1
3
+ metadata.gz: a6293de3ef709101a5410b308f140bd654e38e81905eefff034eaff831da03d7
4
+ data.tar.gz: d8224fc21dd1c63e7f5a93a65ff6452d841da44c12ef7eccb2a9b713d34211cb
5
5
  SHA512:
6
- metadata.gz: e6f3f740d1bbdd532760262e74594e19853b51950c47c9222bea76264b0bf6b4a6839cc0963a3b70778203f34ee867a5c77aa1685232719490c1a47ec939de39
7
- data.tar.gz: 79655aa7f4adf210cd0884655f445e9d094f218624fd2be62fedea30e6a5a82fc900a222a4337d28c88c46034ef264d8cfdfb0b01f985a25d83068962f4807ae
6
+ metadata.gz: ca46b44d6ee87b156d066e1d9e3736fb74b9c0b1ed2df4634a62bbc879fc23aaa9fb42b4dd6857eda5a47a4968fe8c157b384044da1cda65fd20a45b4071bbc2
7
+ data.tar.gz: 1e52c60928f864586e7361ec0a63419d6763f3f8b6339395157750ffd78a2cd672179aa9028d83db26be79351e68625243c052c6001b1f07f3acac6dc4fbb728
data/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.0
4
+
5
+ ### Added
6
+
7
+ * Added `response.data` test helper (require `'camille/testing'`). Validates the response body against the endpoint's response type and returns the snake_case body as a `HashWithIndifferentAccess`. Works with RSpec and Minitest integration / request tests.
8
+
3
9
  ## 1.5.0
4
10
 
5
11
  ### Fixed
data/CLAUDE.md ADDED
@@ -0,0 +1,3 @@
1
+ # Testing
2
+
3
+ Run the test suite with `bundle exec rake` (not `bundle exec rspec` directly).
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- camille (1.4.0)
4
+ camille (1.6.0)
5
5
  rails (>= 6.1, < 8.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -263,6 +263,25 @@ object:
263
263
 
264
264
  Everything in `config/camille/types` and `config/camille/schemas` will automatically reload after changes in development environment, just like other files in Rails.
265
265
 
266
+ ### Test helper
267
+
268
+ Camille ships an optional `response.data` helper for Rails integration / request tests. It looks up the endpoint from the current request, validates `response.parsed_body` against the endpoint's response type, and returns the snake_case body as a `HashWithIndifferentAccess` so you can use either string or symbol keys in assertions.
269
+
270
+ In your `rails_helper.rb` (RSpec) or `test_helper.rb` (Minitest):
271
+
272
+ ```ruby
273
+ require 'camille/testing'
274
+ ```
275
+
276
+ Then in a test:
277
+
278
+ ```ruby
279
+ get '/products/data'
280
+ expect(response.data[:product][:available_stock]).to eq(1)
281
+ ```
282
+
283
+ If the response body fails the type check the helper raises `Camille::Testing::ResponseTypeError`. If the route has no Camille endpoint it raises `Camille::Testing::MissingEndpointError`.
284
+
266
285
  ## Versioning
267
286
 
268
287
  This project uses [Semantic Versioning](https://semver.org/).
@@ -0,0 +1,51 @@
1
+ require 'action_dispatch'
2
+
3
+ module Camille
4
+ module Testing
5
+ class ResponseTypeError < ::StandardError; end
6
+ class MissingEndpointError < ::StandardError; end
7
+
8
+ module ResponseExtension
9
+ def data
10
+ controller_path = request && request.path_parameters[:controller]
11
+ action = request && request.path_parameters[:action]
12
+
13
+ unless controller_path && action
14
+ raise Camille::Testing::MissingEndpointError,
15
+ "No camille endpoint for this response (request did not match a controller action)."
16
+ end
17
+
18
+ controller_class_name = "#{controller_path.camelize}Controller"
19
+ schema = Camille::Loader.controller_name_to_schema_map[controller_class_name]
20
+ endpoint = schema && schema.endpoints[action.to_sym]
21
+
22
+ unless endpoint
23
+ raise Camille::Testing::MissingEndpointError,
24
+ "No camille endpoint for #{controller_class_name}##{action}."
25
+ end
26
+
27
+ result = endpoint.response_type.check_params(parsed_body)
28
+ if result.type_error?
29
+ io = StringIO.new
30
+ Camille::TypeErrorPrinter.new(result).print(io)
31
+ raise Camille::Testing::ResponseTypeError,
32
+ "\nResponse type check failed.\n#{io.string}"
33
+ end
34
+
35
+ deep_indifferent(result.value)
36
+ end
37
+
38
+ private
39
+
40
+ def deep_indifferent value
41
+ case value
42
+ when Hash then value.with_indifferent_access
43
+ when Array then value.map { |v| deep_indifferent(v) }
44
+ else value
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ ActionDispatch::TestResponse.prepend(Camille::Testing::ResponseExtension)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Camille
4
- VERSION = "1.5.0"
4
+ VERSION = "1.6.0"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: camille
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - merely
@@ -38,6 +38,7 @@ extra_rdoc_files: []
38
38
  files:
39
39
  - ".rspec"
40
40
  - CHANGELOG.md
41
+ - CLAUDE.md
41
42
  - Gemfile
42
43
  - Gemfile.lock
43
44
  - README.md
@@ -79,6 +80,7 @@ files:
79
80
  - lib/camille/schema_literal_generator.rb
80
81
  - lib/camille/schemas.rb
81
82
  - lib/camille/syntax.rb
83
+ - lib/camille/testing.rb
82
84
  - lib/camille/type.rb
83
85
  - lib/camille/type_error.rb
84
86
  - lib/camille/type_error_printer.rb