Skip to content

Commit

Permalink
Merge pull request #31 from khamusa/bugfix/bring-snake-case-names-back
Browse files Browse the repository at this point in the history
Bugfix/bring snake case names back
  • Loading branch information
khamusa authored Mar 31, 2020
2 parents 3f045e8 + ef313d1 commit 051a510
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

### Bug fixes

## 1.2.1 (March 31st, 2020)

- Fixed issue causing the last release to break expectations against snake_cased fields (fixes https://github.com/khamusa/rspec-graphql_matchers/issues/30).

## 1.2 (Feb 6th, 2020)

- Added support to underscored arguments in have_field (https://github.com/khamusa/rspec-graphql_matchers/pull/29 thanks to @makketagg)
Expand Down
43 changes: 41 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ describe PostType do
it { is_expected.to have_field(:id).of_type(!types.ID) }
it { is_expected.to have_field(:comments).of_type("[String!]!") }
it { is_expected.to have_field(:isPublished).of_type("Boolean") }

# The gem automatically converts field names to CamelCase, so this will
# pass even though the field was defined as field :isPublished
it { is_expected.to have_field(:is_published).of_type("Boolean") }
end
```

Expand Down Expand Up @@ -138,10 +142,45 @@ describe PostType do
end
```

### 6) Using camelize: false on field names

By default the graphql gem camelizes field names. This gem deals with it transparently:

```ruby
class ObjectMessingWithCamelsAndSnakesType < GraphQL::Schema::Object
graphql_name 'ObjectMessingWithCamelsAndSnakes'

implements GraphQL::Relay::Node.interface

field :me_gusta_los_camellos, ID, null: false

# note the camelize: false
field :prefiero_serpientes, ID, null: false, camelize: false
end
```

The following specs demonstrate the current behavior of the gem regarding fields:

```ruby
describe ObjectMessingWithCamelsAndSnakesType do
subject { described_class }

# For a field name that was automatically camelized, you can add expectations
# against both versions and we handle it transparently:
it { is_expected.to have_a_field(:meGustaLosCamellos) }
it { is_expected.to have_a_field(:me_gusta_los_camellos) }

# However, when using camelize: false, you have to use the exact case of the field definition:
it { is_expected.to have_a_field(:prefiero_serpientes) }
it { is_expected.not_to have_a_field(:prefieroSerpientes) } # Note we're using `not_to`
end
```

This behaviour is currently active only on field name matching. PRs are welcome to
reproduce it to arguments as well.

## TODO

- Support GraphQL 1.9.x;
- Check the method used for resolving a field;
- New matchers!

## Contributing
Expand Down
22 changes: 16 additions & 6 deletions lib/rspec/graphql_matchers/have_a_field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ module RSpec
module GraphqlMatchers
class HaveAField < BaseMatcher
def initialize(expected_field_name, fields = :fields)
@expected_field_name = GraphQL::Schema::Member::BuildType.camelize(expected_field_name.to_s)
@expected_field_name = expected_field_name.to_s
@expected_camel_field_name = GraphQL::Schema::Member::BuildType.camelize(
@expected_field_name
)
@fields = fields.to_sym
@expectations = []
end

def matches?(graph_object)
@graph_object = graph_object

@actual_field = field_collection[@expected_field_name]
@actual_field = @actual_field.to_graphql if @actual_field.respond_to?(:to_graphql)
return false if @actual_field.nil?
return false if actual_field.nil?

@results = @expectations.reject do |matcher|
matcher.matches?(@actual_field)
matcher.matches?(actual_field)
end

@results.empty?
Expand Down Expand Up @@ -57,7 +58,7 @@ def failure_message
base_msg = "expected #{member_name(@graph_object)} " \
"to define field `#{@expected_field_name}`" \

return "#{base_msg} #{failure_messages.join(', ')}" if @actual_field
return "#{base_msg} #{failure_messages.join(', ')}" if actual_field

"#{base_msg} but no field was found with that name"
end
Expand All @@ -68,6 +69,15 @@ def description

private

def actual_field
@actual_field ||= begin
field = field_collection[@expected_field_name]
field ||= field_collection[@expected_camel_field_name]

field.respond_to?(:to_graphql) ? field.to_graphql : field
end
end

def descriptions
@results.map(&:description)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/rspec/graphql_matchers/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@

module Rspec
module GraphqlMatchers
VERSION = '1.2'
VERSION = '1.2.1'
end
end
8 changes: 8 additions & 0 deletions spec/rspec/have_a_field_matcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ module RSpec::GraphqlMatchers
expect(a_type).to have_a_field(:isTest)
end

it 'matches a non camelized field with the underscored field name' do
expect(a_type).to have_a_field(:not_camelized)
end

it 'fails when the type does not define the expected field' do
expect { expect(a_type).to have_a_field(:ids) }
.to fail_with(
Expand Down Expand Up @@ -110,6 +114,7 @@ module RSpec::GraphqlMatchers
field :id, types.ID, null: false
field :other, types.String, hash_key: :other_on_hash, null: true
field :is_test, types.Boolean, null: true
field :not_camelized, types.String, null: false, camelize: false
end
end

Expand All @@ -123,6 +128,7 @@ module RSpec::GraphqlMatchers

field :other, types.String, hash_key: :other_on_hash, null: true
field :is_test, types.Boolean, null: true
field :not_camelized, types.String, null: false, camelize: false
end

Class.new(GraphQL::Schema::Object) do
Expand Down Expand Up @@ -153,6 +159,8 @@ module RSpec::GraphqlMatchers
hash_key: :other_on_hash

field :isTest, types.Boolean

field :not_camelized, types.String, camelize: false
end
end

Expand Down

0 comments on commit 051a510

Please sign in to comment.