diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 624c5d2..7ebb713 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,11 +10,14 @@ jobs: entry: - { ruby: '4.0' } - { ruby: '3.4' } + - { ruby: '3.2', json: '2' } - { ruby: '3.2' } - - { ruby: '2.7' } + - { ruby: '2.7', json: '2' } - { ruby: 'ruby-head', allowed-failure: true } - { ruby: 'jruby-head', allowed-failure: true } - name: test (${{ matrix.entry.ruby }}) + name: test (Ruby ${{ matrix.entry.ruby }}, JSON ${{ matrix.entry.json || '3' }}) + env: + JSON_VERSION: ${{ matrix.entry.json || '3' }} steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cef61a..44ffaaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * [#320](https://github.com/codegram/hyperclient/pull/320): Documented how to handle non-`hal+json` responses via the Faraday response middleware's `content_type` matcher - [@dblock](https://github.com/dblock). * [#321](https://github.com/codegram/hyperclient/pull/321): Added Ruby 4.0 to the CI test matrix - [@dblock](https://github.com/dblock). * [#322](https://github.com/codegram/hyperclient/pull/322): Fixed `Link` caching a mutating request's (`_post`/`_put`/`_patch`/`_delete`) response as its resource, causing subsequent reads (e.g. `#each`, `method_missing`) to return stale data instead of a fresh `_get` - [@dblock](https://github.com/dblock). +* [#325](https://github.com/codegram/hyperclient/pull/325): Added JSON 2.x/3.x to the CI matrix and JSON response parsing regression tests, retaining Ruby 2.7 coverage with JSON 2.x; upgraded RuboCop to 1.91.0 to allow JSON 3.x - [@dblock](https://github.com/dblock). * Your contribution here. ### 2.0.0 (2024/02/01) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a4b627b..2f41faf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,6 +32,16 @@ bundle install bundle exec rake ``` +CI runs the test suites with JSON 2.x on Ruby 2.7, both JSON 2.x and 3.x on Ruby 3.2, and JSON 3.x on Ruby 3.4, Ruby 4.0, and the head builds. +To select a JSON major version locally, resolve the bundle and run the tests with the same `JSON_VERSION`: + +``` +JSON_VERSION=2 bundle update json +JSON_VERSION=2 bundle exec rake test spinach +JSON_VERSION=3 bundle update json +JSON_VERSION=3 bundle exec rake test spinach +``` + #### Write Tests Try to write a test that reproduces the problem you're trying to fix or describes a feature that you want to build. Add to [test/hyperclient](test/hyperclient). diff --git a/Gemfile b/Gemfile index 189bc32..fb072d5 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,8 @@ source 'https://rubygems.org' gemspec +gem 'json', "~> #{ENV['JSON_VERSION']}.0" if ENV['JSON_VERSION'] + group :development do gem 'growl' gem 'guard' @@ -13,7 +15,7 @@ end group :development, :test do gem 'rake' - gem 'rubocop', '~> 1.89.0', require: false + gem 'rubocop', '~> 1.91.0', require: false gem 'rubocop-minitest', require: false gem 'rubocop-rake', require: false gem 'simplecov', require: false diff --git a/README.md b/README.md index 3bb42ff..a6dcd93 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,8 @@ Hyperclient is a Hypermedia API client written in Ruby. It fully supports [JSON The examples in this README use the [Splines Demo API](https://github.com/ruby-grape/grape-with-roar) running [here](https://grape-with-roar.herokuapp.com/api). Use version 1.x with Faraday 1.x, and version 2.x with Faraday 2.x. If you're upgrading from a previous version, please make sure to read [UPGRADING](UPGRADING.md). +Hyperclient is tested with JSON 2.x on Ruby 2.7, both JSON 2.x and 3.x on Ruby 3.2, and JSON 3.x on newer Rubies. JSON 3.x requires a Faraday release with keyword parser options support (2.14.4+). + ## API Client Create an API client. diff --git a/test/hyperclient/link_test.rb b/test/hyperclient/link_test.rb index 2c166b6..d2852e7 100644 --- a/test/hyperclient/link_test.rb +++ b/test/hyperclient/link_test.rb @@ -167,6 +167,37 @@ module Hyperclient end describe 'get' do + %w[application/hal+json application/json].each do |content_type| + it "parses a #{content_type} response into a resource" do + link = Link.new('key', { 'href' => '/productions/1' }, entry_point) + + stub_request(entry_point.connection) do |stub| + stub.get('http://api.example.org/productions/1') do + [200, { 'Content-Type' => content_type }, + '{"title":"Production","_links":{"self":{"href":"/productions/1"}}}'] + end + end + + resource = link._get + + _(resource.title).must_equal 'Production' + _(resource._links.self._url).must_equal '/productions/1' + _(resource._response.body).must_be_kind_of Hash + end + end + + it 'raises a parsing error for an invalid JSON response' do + link = Link.new('key', { 'href' => '/productions/1' }, entry_point) + + stub_request(entry_point.connection) do |stub| + stub.get('http://api.example.org/productions/1') do + [200, { 'Content-Type' => 'application/hal+json' }, '{"title":'] + end + end + + _(-> { link._get }).must_raise Faraday::ParsingError + end + it 'sends a GET request with the link url' do link = Link.new('key', { 'href' => '/productions/1' }, entry_point)