khamusa / rspec-graphql_matchers Goto Github PK
View Code? Open in Web Editor NEWCollection of rspec matchers to test your graphQL api schema.
License: MIT License
Collection of rspec matchers to test your graphQL api schema.
License: MIT License
Hello,
Wouldn't it be revelant to add a chain to the matcher have_field
to check for the method argument used to link a field to a method on the model ?
field :hello, String, null: false, method: :hello_world
The chain could be called :with_method or :linked_to_method
I don't know if it is in the spirit of the gem since it checks a bit more than just the schema definitions but it could be very useful
First, of, thank you for the gem :). It reminds me the joy of Shoulda, which is an excellent little gem.
I have a small request, is it possible to automatically change the casing to camel case?
Instead of
# this already works, but not very rubyish
it { is_expect.to have_field(:isPublished) }
# what if we allow for this
it { is_expect.to have_field(:is_published) }
The graphql gem is currently at version 1.3.0.
However, the gemspec states the graphql dependency has to be '< 1'
https://github.com/khamusa/rspec-graphql_matchers/blob/master/rspec-graphql_matchers.gemspec#L23
I loosened the runtime dependency:
spec.add_runtime_dependency 'graphql', '>= 0.9', '< 2'
Then ran the tests and everything passed. Any reason not to bump the dependency up to support the new version of graphql?
Hi there - just began doing some GraphQL development on Rails this week with the graphql-ruby
gem (1.9x). Noticed that it's version limited to 1.8.
I quickly cloned this repo and removed the version limit in the gemspec file. It seems to be working with the project I am on.
I also ran rspec
from your project root and the tests all passed.
Could we get a version bump?
Hey @khamusa, excellent idea!
I see a one problem with the current approach:
it { is_expected.to have_field(:isPublished).of_type("Boolean") }
The string notation of GQL types has it place, but I'd suggest something different:
it {
is_expected
.to have_field(:isPublished)
.of_type(GraphQL::Types::Boolean)
.exposed_as("Boolean")
}
This way you can do both:
For example, if I changed the graphql_name
of my type, the exposed_as
would fail, but of_type
would not. Giving you a better picture of what's happening.
I know it's a radical change for a gen that has a version 2 already coming, but I love to discuss this.
Maybe to keep the syntax more stable:
it {
is_expected
.to have_field(:isPublished)
.of_type("Boolean")
.implemented_with(GraphQL::Types::Boolean)
}
.Legacy .to_graphql
objects are deprecated and will be removed in GraphQL-Ruby 2.0. Remove .to_graphql
to use a class-based definition instead.
it { is_expected.to have_field(:id).of_type('ID!') }
Backtrace
/spec-graphql_matchers-1.3.1/lib/rspec/graphql_matchers/have_a_field.rb:83:in `actual_field`
Using v0.2.0
Rspec:
it { is_expected.not_to have_field(:some_field) }
If your Type actually includes this field, will result in the following error message:
NoMethodError: undefined method `failure_message_when_negated' for #RSpec::GraphqlMatchers::HaveAField:0x00007fe77a672ed8
Did you mean? failure_message
Hi there! Thanks for creating these helpers. Delightful code to work with. I hope I'm just missing something, but it seems like the last version bump broke support for snake case field testing.
When testing a snake case field name, version 1.2 of this gem assumes the field name to be camelized and camelizes the expected field name even though the field on the schema is snake case.
I'm using 1.8.4
of the graphql
gem and 1.2
of the rspec-graphql_matchers
gem, for context
Type definition:
class ExampleType < GraphQL::Schema::Object
# metadata
field :existing_snake_case_field, String, null: true, camelize: false
def resolve
# logic and things
end
end
RSpec Expectation:
require "rails_helper"
require "rspec/graphql_matchers"
RSpec.describe Types::Objects::ExampleType do
subject { described_class }
it { is_expected.to have_field(:existing_snake_case_field).of_type "String" }
end
Error I'm seeing:
Failure/Error: it { is_expected.to have_field(:existing_snake_case_field).of_type "String" }
expected Example to define field `existingSnakeCaseField` but no field was found with that name
If I dig a little further, I see that the fields hash on the type I'm testing has a snake_case field name key, rather than the camelCase version. The matcher seems to assume that the field key will be camelCase and compares the camelCase @expected_field_name to the snake case hash key, getting nil back, and subsequently failing.
subject.fields
=> {"existing_snake_case_field"=> #<GraphQL::Schema::Field:0x00007f98ca194c80 }
It seems to be related to this change, which added support for snake case arguments, but assumes the camelization of the field name: https://github.com/khamusa/rspec-graphql_matchers/pull/29/files#diff-4820620b0dee82dd3ac38023e704859eR13
I would just bump the version back to v1.1 but that drops support for snake_case arguments which are also inherent in our code base. Seems like we have to leave one or the other untested, which is... not ideal. Again, I hope I'm just missing something. Thanks!
Add an easy way to test the usage of property
: field :public, types.Boolean, property: :is_public
Seems like you can't use this particular style of testing anymore:
describe Types::User do
# avail type definer in our tests
types = GraphQL::Define::TypeDefiner.instance
it 'has an :email field of String type' do
expect(subject).to have_field(:email).that_returns(!types.String)
end
end
That spec now raises the error:
NoMethodError:
protected method `new' called for Types::User:Class
This is due to an upstream change where you can't call .new
anymore and must call .authorized_new
instead. I had some trouble trying to figure out how to actually successfully call that method in subject
so thought I'd give a heads up here in case anyone is trying to use this gem for this type of spec.
Hello guys,
The problem I'm facing is related to this small example:
require "rails_helper"
types = GraphQL::Define::TypeDefiner.instance
describe Types::Data::Permission do
graphql_spec!
# Attributes
context 'attribute fields' do
it { is_expected.to have_field(:id).of_type(types.ID) }
end
end
When I run this teste, I have the following failure:
F
Failures:
1) Types::Data::Permission attribute fields should define field `id`, of type `ID`
Failure/Error: it { is_expected.to have_field(:id).of_type(types.ID) }
expected Types::Data::Permission to define field `id`, of type `ID`, but the type was `#<GraphQL::Schema::NonNull:0x0000563160c7e718>`.
# ./spec/graphql/types/data/permission_spec.rb:10:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:83:in `block (3 levels) in <top (required)>'
# /bundle/gems/database_cleaner-1.7.0/lib/database_cleaner/generic/base.rb:16:in `cleaning'
# /bundle/gems/database_cleaner-1.7.0/lib/database_cleaner/base.rb:100:in `cleaning'
# /bundle/gems/database_cleaner-1.7.0/lib/database_cleaner/configuration.rb:86:in `block (2 levels) in cleaning'
# /bundle/gems/database_cleaner-1.7.0/lib/database_cleaner/configuration.rb:87:in `cleaning'
# ./spec/rails_helper.rb:83:in `block (2 levels) in <top (required)>'
# /bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:123:in `block in run'
# /bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `loop'
# /bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:110:in `run'
# /bundle/gems/rspec-retry-0.6.1/lib/rspec_ext/rspec_ext.rb:12:in `run_with_retry'
# /bundle/gems/rspec-retry-0.6.1/lib/rspec/retry.rb:37:in `block (2 levels) in setup'
Finished in 11 minutes 29 seconds (files took 2.18 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/graphql/types/data/permission_spec.rb:10 # Types::Data::Permission attribute fields should define field `id`, of type `ID`
So I started digging up our code, rspec-graphql_matchers
and graphql-ruby
source to find any clues to where that object
were being passed and not the actual type.
Digging I found out that .of_type actually gets the type
using #type
on the type object or class
(in our case, we're passing the class
).
But #type
is returning a GraphQL::Schema::NonNull
, not the actual type
๐ค
So I ran to the graphql-source
to look in that, and it really returns that instance.
And now I'm stuck, and I doing something wrong by defining the subject
as the class (in our case, Types::Data::Permission
), or is it a bug?
We are using the class
definitions as suggested by the graphql-ruby
gem.
The graphql_spec!
method definition is as follow:
def graphql_spec!
self.let(:subject) do
self.described_class
end
end
As mentioned on #8, it would be nice to have a with_description. The argument could be optional to test if a field has a description, or with an argument that the description matches. e.g.
it { is_expected.to have_a_field(:id).with_description }
# or with an argument
it { is_expected.to have_a_field(:id).with_description('Database ID of the Post')
I've added the gem in a test block within the Gemfile and rub bundle install.
However when I run the test which is:
require 'rails_helper'
RSpec.describe Types:ClassName, type: :object do
subject { self.described_class }
it { is_expected.to have_a_field(:id) }
end
It errors with:
Failure/Error: it { is_expected.to have_a_field(:id) }
expected Types::Events::EventType to respond to `has_a_field?
Is there some additional config needed that does not appear in the documentation.
I'm running rspec-graphql_matchers (0.7.1) and graphql (1.9.4)
Hi thanks for creating this gem, I'm looking forward to using it. I'm trying to get things set up with:
Ruby: ruby 2.7.0p0
Rails: 6.0.3
Rspec-rails: 4.0.1
Graphql: 1.11.5
I have the following tree type structure for graphql:
app/graphql
โโโ mutations
โย ย โโโ base_mutation.rb
โโโ tfl_graph_schema.rb
โโโ types
โโโ base_argument.rb
โโโ base_enum.rb
โโโ base_field.rb
โโโ base_input_object.rb
โโโ base_interface.rb
โโโ base_object.rb
โโโ base_scalar.rb
โโโ base_union.rb
โโโ journey_search_result_type.rb
โโโ journey_type.rb
โโโ mutation_type.rb
โโโ query_type.rb
And the following for my specs:
spec
โโโ graphql
โย ย โโโ types
โย ย โโโ journey_type_spec.rb
โโโ rails_helper.rb
โโโ spec_helper.rb
โโโ support
โโโ factory_bot.rb
โโโ shoulda_matchers.rb
I've create the following spec:
describe JourneyType do
subject { described_class }
it { is_expected.to have_field(:arrivalDateTime) }
it { is_expected.to have_field(:startDateTime) }
it { is_expected.to have_field(:duration) }
end
But get:
NameError:
uninitialized constant JourneyType
Do I need to add something to spec_helper.rb to make GraphQL types visible to rspec?
I'm using graphql-ruby
1.8 and I have a GameType
defined as well as a GameQueryType
like this
module Types
class GameType < Types::BaseObject
...
end
end
module Types
GameQueryType = GraphQL::ObjectType.define do
name 'GameQueryType'
description 'The games query type'
field :games, types[Types::GameType], 'returns all games' do
resolve ->(_obj, _args, _ctx) { Game.all }
end
end
end
When I write a spec
it "has a :games field that returns a list of games" do
expect(subject).to have_field(:games).that_returns(types[Types::GameType])
end
it fails with
expected Query to define field
games
, of type#<GraphQL::Schema::List:0x00007f83730fdf90>
, but the type was[Game]
.
Only
it "has a :games field that returns a list of games" do
expect(subject).to have_field(:games).that_returns("[Game]")
end
works, but this is not the right way of writing in my opinion.
If I define my GameTypeQuery
like
module Types
class GameQueryType < Types::BaseObject
graphql_name 'GameQueryType'
description 'The games query type'
field :games, [Types::GameType], 'returns all games', null: true
end
end
then
it "has a :games field that returns a list of games" do
expect(subject).to have_field(:games).that_returns(types[Types::GameType])
end
produces
expected Query to define field
games
, of type#<GraphQL::Schema::List:0x00007f836b612d58>
, but the type was#<GraphQL::Schema::List:0x00007f836af9b7e0>
while
it "has a :games field that returns a list of games" do
expect(subject).to have_field(:games).that_returns([Types::GameType])
end
produces
expected Query to define field
games
, of type[Types::GameType]
, but the type was#<GraphQL::Schema::List:0x00007f8373483110>
Maybe I'm doing it wrong but I guess something is broken here.
How to write it correctly?
How to test Enum values?
I didn't find anything about it.
Like Field, anything that includes InstanceDefinable can have metadata.
It would be great to have test like:
it { is_expected.to have_metadata({foo: 'bar'}) }
Sometimes fields on a type are set to deprecated. This is done via the
deprecation_reason
method.
Currently there is no way to test if a field has been deprecated or not.
Would be awesome if we could do
expect(a_type).to have_a_field(:id).with_deprecation_reason('whatever')
to test these cases.
Currently this gem does not support the latest graphql
2.0
.
To fix this would need to be merged to resolve #42 and the gemspec would need to be updated to allow for compatibility with graphql < 3.0 and a release would need to be made.
Can we please get an update so this can be used with graphql 2.0
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.