Skip to content

Commit

Permalink
Merge pull request #17 from bigcommerce/gruf-215-autoloading
Browse files Browse the repository at this point in the history
Gruf 2.15 autoloading support, use zeitwerk in this library
  • Loading branch information
splittingred authored Jul 9, 2022
2 parents be5c88c + 8ea3776 commit 602b904
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 38 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ Changelog for the gruf-rspec gem.

### Pending release

### 0.6.x

- Add better support for Gruf 2.15+ autoloading in a Rails test environment
- Use zeitwerk for autoloading in this library

### 0.5.0

- Add support for Ruby 3.1
Expand All @@ -14,7 +19,7 @@ Changelog for the gruf-rspec gem.

### 0.3.0

- [#7] Fix issue where RPC_SPEC_PATH defaulting is hardcoded
- [#7] Fix issue where RPC_SPEC_PATH defaulting is hardcoded
- Drop support for Ruby < 2.6, add 2.7 tests
- Update rubocop to 1.0

Expand Down
35 changes: 14 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,14 @@

[![CircleCI](https://circleci.com/gh/bigcommerce/gruf-rspec/tree/main.svg?style=svg)](https://circleci.com/gh/bigcommerce/gruf-rspec/tree/main) [![Gem Version](https://badge.fury.io/rb/gruf-rspec.svg)](https://badge.fury.io/rb/gruf-rspec) [![Documentation](https://inch-ci.org/github/bigcommerce/gruf-rspec.svg?branch=main)](https://inch-ci.org/github/bigcommerce/gruf-rspec?branch=main) [![Maintainability](https://api.codeclimate.com/v1/badges/db2d134a7148dde045b7/maintainability)](https://codeclimate.com/github/bigcommerce/gruf-rspec/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/db2d134a7148dde045b7/test_coverage)](https://codeclimate.com/github/bigcommerce/gruf-rspec/test_coverage)

Assistance helpers and custom type for easy testing [Gruf](https://github.com/bigcommerce/gruf) controllers with
Assistance helpers and custom type for easy testing [Gruf](https://github.com/bigcommerce/gruf) controllers with
[RSpec](https://github.com/rspec/rspec).

## Installation

```ruby
gem 'gruf-rspec'
```

Then add the following code to your `spec_helper.rb`:

```ruby
require 'gruf/rspec'
```

Note that this gem requires at least Ruby 2.7+, Gruf 2.5.1+, and RSpec 3.8+.

Expand All @@ -28,13 +22,13 @@ and the active_call_options. The third argument is optional.

## Example

Let's assume you have a gruf controller named `ThingController` that is bound to the gRPC
Let's assume you have a gruf controller named `ThingController` that is bound to the gRPC
service `Rpc::Things::Service`. That has a method `GetThing`:

```ruby
class ThingController < Gruf::Controllers::Base
bind ::Rpc::Things::Service

def get_thing
Rpc::GetThingResponse.new(id: request.message.id)
end
Expand All @@ -45,16 +39,16 @@ To test it, you'd create `spec/rpc/thing_controller_spec.rb`:

```ruby
describe ThingController do
describe '.get_thing' do
describe '#get_thing' do
let(:request_proto) { Rpc::GetThingRequest.new(id: rand(1..100)) }
let(:metadata) {
{ 'user_id' => 'axj42i' }
}

subject { run_rpc(:GetThing, request_proto, active_call_options: { metadata: metadata }) }

it 'will return the thing' do
expect(subject).to be_a(Rpc::GetThingResponse)
it 'returns the thing' do
expect(subject).to be_a_successful_rpc
expect(subject.id).to eq request_proto.id
end
end
Expand All @@ -64,9 +58,9 @@ end
Alternatively, you can pass a block:

```ruby
it 'will return the thing' do
it 'returns the thing' do
run_rpc(:GetThing, request_proto) do |resp|
expect(resp).to be_a(Rpc::GetThingResponse)
expect(resp).to be_a_successful_rpc
expect(resp.id).to eq request_proto.id
end
end
Expand All @@ -80,7 +74,7 @@ Note that you can also access the bound gRPC service class:
it 'binds the service correctly' do
expect(grpc_bound_service).to eq Rpc::Things::Service
end
```
```

### Matching Errors

Expand All @@ -89,9 +83,9 @@ You can match against errors as well:
```ruby
describe 'testing an error' do
let(:request_proto) { Rpc::GetThingRequest.new(id: rand(1..100)) }

subject { run_rpc(:GetThing, request_proto) }

it 'should fail with the appropriate error' do
expect { subject }.to raise_rpc_error(GRPC::InvalidArgument)
end
Expand All @@ -105,19 +99,18 @@ it 'should fail with the appropriate error code' do
expect { subject }.to raise_rpc_error(GRPC::InvalidArgument).with_serialized { |err|
expect(err).to be_a(MyCustomErrorClass)
expect(err.error_code).to eq 'invalid_request'

fe = err.field_errors.first
expect(fe.field_name).to eq 'name'
expect(fe.error_code).to eq 'invalid_name'
expect(fe.error_message).to eq
expect(fe.error_message).to eq 'That name is already taken!'
}
end
```

Note that when using `with_serialized`, you _must_ pass the block with `{ }`, not using
`do` and `end`.


### RSpec Controller Matcher Configuration

By default, the type matcher for Gruf controllers matches in `/spec/rpc`. You can customize this by configuring it
Expand All @@ -129,7 +122,7 @@ Gruf::Rspec.configure do |c|
end
```

Alternatively, you can pass configuration of the path via ENV. For example, where
Alternatively, you can pass configuration of the path via ENV. For example, where
`RPC_SPEC_PATH="/spec/rpc_controllers"` is set in a `.env` file:

```bash
Expand Down
8 changes: 4 additions & 4 deletions gruf-rspec.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'gruf/rspec/version'
require_relative 'lib/gruf/rspec/version'

Gem::Specification.new do |spec|
spec.name = 'gruf-rspec'
Expand All @@ -31,9 +29,10 @@ Gem::Specification.new do |spec|
spec.homepage = 'https://github.com/bigcommerce/gruf-rspec'

spec.required_ruby_version = '>= 2.7'
spec.metadata['rubygems_mfa_required'] = 'true'

spec.files = Dir['README.md', 'CHANGELOG.md', 'CODE_OF_CONDUCT.md', 'lib/**/*', 'gruf-rspec.gemspec']
spec.require_paths = ['lib']
spec.require_paths = %w[lib]

spec.add_development_dependency 'bundler-audit', '>= 0.6'
spec.add_development_dependency 'pry', '>= 0.13'
Expand All @@ -43,4 +42,5 @@ Gem::Specification.new do |spec|

spec.add_runtime_dependency 'gruf', '~> 2.5', '>= 2.5.1'
spec.add_runtime_dependency 'rspec', '>= 3.8'
spec.add_runtime_dependency 'zeitwerk', '>= 2'
end
21 changes: 17 additions & 4 deletions lib/gruf/rspec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,15 @@
GRUF_RSPEC_RUNNER = Spec::Runner
end

require_relative 'rspec/version'
require_relative 'rspec/configuration'
require_relative 'rspec/helpers'
require_relative 'rspec/error_matcher'
# use Zeitwerk to lazily autoload all the files in the lib directory
require 'zeitwerk'
lib_path = File.dirname(__dir__)
loader = ::Zeitwerk::Loader.new
loader.tag = 'gruf-rspec'
loader.inflector = ::Zeitwerk::GemInflector.new(__FILE__)
loader.ignore("#{lib_path}/gruf/rspec/railtie.rb")
loader.push_dir(lib_path)
loader.setup

##
# Base gruf module
Expand All @@ -45,6 +50,14 @@ module Rspec

Gruf::Rspec.reset # initial reset

# Attempt to load railtie if we're in a rails environment. This assists with autoloading in a rails rspec context
begin
require 'rails'
rescue LoadError
nil
end
require_relative 'rspec/railtie' if defined?(::Rails::Railtie)

GRUF_RSPEC_RUNNER.configure do |config|
config.include Gruf::Rspec::Helpers

Expand Down
3 changes: 0 additions & 3 deletions lib/gruf/rspec/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
require_relative 'authentication_hydrators/base'
require_relative 'authentication_hydrators/basic'

module Gruf
module Rspec
##
Expand Down
2 changes: 0 additions & 2 deletions lib/gruf/rspec/helpers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
require_relative 'metadata_factory'

module Gruf
module Rspec
##
Expand Down
31 changes: 31 additions & 0 deletions lib/gruf/rspec/railtie.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# frozen_string_literal: true

# Copyright (c) 2022-present, BigCommerce Pty. Ltd. All rights reserved
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
# documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
# persons to whom the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
# Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
module Gruf
module Rspec
##
# Rails integration for gruf-rspec
#
class Railtie < ::Rails::Railtie
initializer 'gruf-rspec.initializer' do |_app|
config.after_initialize do
::Gruf.autoloaders.load!(controllers_path: ::Gruf.controllers_path) if ::Gruf.respond_to?(:autoloaders)
end
end
end
end
end
2 changes: 1 addition & 1 deletion lib/gruf/rspec/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,6 @@
#
module Gruf
module Rspec
VERSION = '0.5.1.pre'
VERSION = '0.6.0.pre'
end
end
2 changes: 0 additions & 2 deletions spec/spec_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
require 'bundler/setup'
require_relative 'simplecov_helper'
require 'gruf'
require 'gruf/rspec'
Expand Down

0 comments on commit 602b904

Please sign in to comment.