Repository: khamusa/rspec-graphql_matchers
Branch: master
Commit: 97324d257f28
Files: 40
Total size: 61.6 KB
Directory structure:
gitextract_0bqch8nx/
├── .codeclimate.yml
├── .editorconfig
├── .github/
│ └── workflows/
│ └── rspec.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin/
│ ├── console
│ └── setup
├── lib/
│ └── rspec/
│ ├── graphql_matchers/
│ │ ├── accept_argument.rb
│ │ ├── accept_arguments.rb
│ │ ├── base_matcher.rb
│ │ ├── be_of_type.rb
│ │ ├── have_a_field.rb
│ │ ├── have_a_field_matchers/
│ │ │ ├── of_type.rb
│ │ │ ├── with_deprecation_reason.rb
│ │ │ ├── with_hash_key.rb
│ │ │ ├── with_metadata.rb
│ │ │ └── with_property.rb
│ │ ├── implement.rb
│ │ ├── matchers.rb
│ │ ├── types_helper.rb
│ │ └── version.rb
│ └── graphql_matchers.rb
├── rspec-graphql_matchers.gemspec
└── spec/
├── rspec/
│ ├── accept_argument_matcher_spec.rb
│ ├── accept_arguments_matcher_spec.rb
│ ├── be_of_type_matcher_spec.rb
│ ├── graphql_matchers_spec.rb
│ ├── have_a_field_matcher_spec.rb
│ ├── have_a_return_field_spec.rb
│ ├── have_an_input_field_matcher_spec.rb
│ ├── implement_matcher_spec.rb
│ └── readme_spec.rb
└── spec_helper.rb
================================================
FILE CONTENTS
================================================
================================================
FILE: .codeclimate.yml
================================================
---
engines:
duplication:
enabled: true
config:
languages:
- ruby
- javascript
- python
- php
fixme:
enabled: true
rubocop:
enabled: true
ratings:
paths:
- "**.inc"
- "**.js"
- "**.jsx"
- "**.module"
- "**.php"
- "**.py"
- "**.rb"
exclude_paths:
- Gemfile.lock
- spec/
- rspec-graphql_matchers.gemspec
- bin/
- Rakefile
================================================
FILE: .editorconfig
================================================
# EditorConfig help us maintain consistent coding style between different editors.
#
# EditorConfig
# http://editorconfig.org
#
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
indent_size = 4
================================================
FILE: .github/workflows/rspec.yml
================================================
name: RSpec
# Controls when the action will run. Triggers the workflow on push or pull request
# events but only for the master branch
on: [push, pull_request]
jobs:
# This workflow contains a single job "rspec"
rspec:
# The type of runner that the job will run on
runs-on: ubuntu-latest
strategy:
matrix:
ruby_version: [2.6, 2.7, '3.0', 3.1, 3.2]
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v3
- name: Set up Ruby ${{ matrix.ruby_version }}
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby_version }}
bundler-cache: true
- name: Run RSpec
run: bundle exec rspec
================================================
FILE: .gitignore
================================================
/.bundle/
/.yardoc
/Gemfile.lock
/_yardoc/
/coverage/
/doc/
/pkg/
/spec/reports/
/tmp/
================================================
FILE: .rspec
================================================
--format documentation
--color
================================================
FILE: .rubocop.yml
================================================
AllCops:
DisplayCopNames: true
DisplayStyleGuide: true
Layout/AlignParameters:
EnforcedStyle: with_fixed_indentation
Metrics/LineLength:
Max: 90
Layout/MultilineMethodCallIndentation:
EnforcedStyle: indented
Layout/SpaceBeforeFirstArg:
Include:
- db/migrate/*.rb
Enabled: false
Style/Documentation:
Enabled: false
Style/ClassAndModuleChildren:
Enabled: true
Style/Lambda:
Enabled: false
Metrics/MethodLength:
Max: 15
Metrics/BlockLength:
Exclude:
- spec/rspec/*.rb
Metrics/ModuleLength:
Exclude:
- spec/rspec/*.rb
================================================
FILE: CHANGELOG.md
================================================
# Changelog
## 2.0.0 (April 16th, 2023)
- Adds compatibility with graphql-ruby 2.0+. If you're still using an earlier version, you should stick to 1.4.x.
### Deprecations
- The usage of the `#types` helper when writing tests (if you're not including `RSpec::GraphqlMatchers::TypesHelper` anywhere, you shoudn't have to change anything). Use `GraphQL::Types::<TYPE_NAME>` instead
- The usage of type instances as expected value for a type comparison is deprecated. Instead,
use the string that represents the type specification. Examples:
```
# Bad - These are deprecated:
expect(a_type).to have_a_field(:lorem).of_type(GraphQL::Types::ID)
expect(a_type).to have_a_field(:lorem).of_type(Types::MyCustomType)
# Good - Use these instead
expect(a_type).to have_a_field(:lorem).of_type('ID')
expect(a_type).to have_a_field(:lorem).of_type('MyCustomType')
```
The reason behind this change relies on the fact that we should have a decoupling between the
internal constants used to define our API and the public names exposed through it. If we test
a published API using the internal constants, it is possible to perform breaking changes by
renaming the graphql names of our types or entities without actually breaking the tests.
If we're performing a breaking change to a public API, we want our tests to fail.
## 1.4.0 (April 16th, 2023)
- Removal of deprecated calls to #to_graphql, replacing them with #to_type_signature that was added in graphql-ruby 1.8.3 (https://github.com/khamusa/rspec-graphql_matchers/pull/43 @RobinDaugherty)
- Dropped support for legacy .define API
- Dropped support to old relay interfaces
- Fixed with_hash_key matcher for newer versions of graphql-ruby
- Fixed errors that occured in some edge cases when generating descriptions for accept_argument and have_a_field matchers
- Documentations improvement and general cleanup
- Dropped support to graphql-ruby versions before 1.10.12.
## 1.3.1 (Aug 2nd, 2021)
- Corrected gem dependencies so it properly requires RSpec when loaded (thanks to @itay-grudev)
## 1.3.0 (May 7th, 2020)
- `accept_argument` matcher accepts underscored argument names and passes even if the actual argument is camel-cased (https://github.com/khamusa/rspec-graphql_matchers/pull/32 thanks to @TonyArra);
- `have_a_field` matcher accepts `.with_deprecation_reason` (https://github.com/khamusa/rspec-graphql_matchers/pull/34 thanks to @TonyArra).
## 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)
## 1.1 (Sep 19th, 2019)
- Added graphql-ruby 1.9.x support (thanks to @severin)
## 1.0.1 (June 22th, 2019)
### Bug fixes
- Fixed issue causing `have_a_field(x).of_type(Y)` to fail on fields defined on implemented interfaces that were defined with legacy syntax.
## 1.0 (June, 2019)
### Breaking changes
- Support to property and hash_key matchers will be dropped on upcoming releases.
### Deprecations
- `.with_metadata` and `.with_property` matchers for fields will be removed on the next release;
- `.accept_arguments` (plural form) will be removed on the next release;
- `.accept_argument` (singular form) receiving a hash with a single or multiple arguments will no longer be supported, use `accept_argument(name).of_type('MyType')` instead.
### New features
- Add support for Class-based type definition api (adds support for graphql-ruby v1.8.x). Please note that `.with_metadata` and `.with_property` support has been kept but will only work on fields defined using the legacy api.
- Implemented `accept_argument(arg_name).of_type('MyType')´ matcher, which returns much clearer error messages when the arguments are not found on the target type.
### Bug fixes
## 0.7.1 (July 27, 2017)
Changelog fixes.
## 0.7.0 (July 27, 2017)
### New features
- (#3, #8) New chainable matchers `with_property`, `with_hash_key` and `with_metadata` (Thanks to @marcgreenstock).
### Improvements
- Default Raketask runs rubocop specs as well (Thanks to @marcgreenstock).
## 0.6.0 (July 25, 2017)
### New features
- (PR #6) New matchers for interfaces: `expect(...).to implement(interface)` (Thanks to @marcgreenstock).
## 0.5.0 (May 10, 2017)
### New features
- (PR #4) New matchers for mutations: `have_an_input_field` and `have_a_return_field` (Thanks to @aaronklaassen).
## 0.4.0 (Feb, 2017)
### New features
- Improvements on error messages of have_a_field(...).of_type(...)
### Bug fixes
- Fixed a bug preventing proper type checking when using matchers in the form have_a_field(fname).of_type(types.X). The bug would not happen when providing the type expectation as a string, only when using the GraphQL constants.
## 0.3.0 (Sep 16, 2016)
### Breaking changes
### Deprecations
### New features
- New matcher have_field(field_name).of_type(type) for testing types and their fields
### Bug fixes
## 0.2.0 Initial public release
### Breaking changes
### Deprecations
### New features
- New matcher be_of_type for testing fields
- New matcher accept_arguments for testing fields
### Bug fixes
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Code of Conduct
As contributors and maintainers of this project, and in the interest of
fostering an open and welcoming community, we pledge to respect all people who
contribute through reporting issues, posting feature requests, updating
documentation, submitting pull requests or patches, and other activities.
We are committed to making participation in this project a harassment-free
experience for everyone, regardless of level of experience, gender, gender
identity and expression, sexual orientation, disability, personal appearance,
body size, race, ethnicity, age, religion, or nationality.
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery
* Personal attacks
* Trolling or insulting/derogatory comments
* Public or private harassment
* Publishing other's private information, such as physical or electronic
addresses, without explicit permission
* Other unethical or unprofessional conduct
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
By adopting this Code of Conduct, project maintainers commit themselves to
fairly and consistently applying these principles to every aspect of managing
this project. Project maintainers who do not follow or enforce the Code of
Conduct may be permanently removed from the project team.
This code of conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting a project maintainer at gb.samuel@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. Maintainers are
obligated to maintain confidentiality with regard to the reporter of an
incident.
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.3.0, available at
[http://contributor-covenant.org/version/1/3/0/][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/3/0/
================================================
FILE: Gemfile
================================================
# frozen_string_literal: true
source 'https://rubygems.org'
# Specify your gem's dependencies in rspec-graphql_matchers.gemspec
gemspec
================================================
FILE: LICENSE.txt
================================================
The MIT License (MIT)
Copyright (c) 2016 Samuel Brandão
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.
================================================
FILE: README.md
================================================

# Rspec::GraphqlMatchers
Convenient rspec matchers for testing your [graphql-ruby](https://github.com/rmosolgo/graphql-ruby) API/Schema.
## Installation
```
gem 'rspec-graphql_matchers'
```
## Usage
The matchers currently supported are:
- `expect(a_graphql_object).to have_a_field(field_name).of_type(valid_type)`
- `expect(a_graphql_object).to implement(interface_name, ...)`
- `expect(a_mutation_type).to have_a_return_field(field_name).returning(valid_type)`
- `expect(a_mutation_type).to have_an_input_field(field_name).of_type(valid_type)`
- `expect(a_field).to be_of_type(valid_type)`
- `expect(an_input).to accept_argument(argument_name).of_type(valid_type)`
Where `valid_type` is a your type signature as a String: `"String!"`, `"Int!"`, `"[String]!"` (note the exclamation mark at the end, as required by the [GraphQL specifications](http://graphql.org/).
Please note that using references to type instances is deprecated and will be removed in a future release.
## Examples
Given a GraphQL object defined as
```ruby
class PostType < GraphQL::Schema::Object
graphql_name "Post"
description "A blog post"
implements GraphQL::Types::Relay::Node
field :id, ID, null: false
field :comments, [String], null: false
field :isPublished, Boolean, null: true
field :published, Boolean, null: false, deprecation_reason: 'Use isPublished instead'
field :subposts, PostType, null: true do
argument :filter, String, required: false
argument :id, ID, required: false
argument :isPublished, Boolean, required: false
end
end
```
### 1) Test your type defines the correct fields:
```ruby
describe PostType do
subject { described_class }
it { is_expected.to have_field(:id).of_type("ID!") }
it { is_expected.to have_field(:comments).of_type("[String!]!") }
it { is_expected.to have_field(:isPublished).of_type("Boolean") }
# Check a field is deprecated
it { is_expected.to have_field(:published).with_deprecation_reason }
it { is_expected.to have_field(:published).with_deprecation_reason('Use isPublished instead') }
it { is_expected.not_to have_field(:published).with_deprecation_reason('Wrong reason') }
it { is_expected.not_to have_field(:isPublished).with_deprecation_reason }
# 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
```
### 2) Test a specific field type with `be_of_type` matcher:
```ruby
describe PostType do
describe 'id' do
subject { PostType.fields['id'] }
it { is_expected.to be_of_type('ID!') }
it { is_expected.not_to be_of_type('Float!') }
end
describe 'subposts' do
subject { PostType.fields['subposts'] }
it { is_expected.to be_of_type('Post') }
end
end
```
### 3) Test the arguments accepted by a field with `accept_argument` matcher:
```ruby
describe PostType do
describe 'subposts' do
subject { PostType.fields['subposts'] }
it 'accepts a filter and an id argument, of types String and ID' do
expect(subject).to accept_argument(:filter).of_type('String')
expect(subject).to accept_argument(:id).of_type('ID')
end
it { is_expected.not_to accept_argument(:weirdo) }
# The gem automatically converts argument names to CamelCase, so this will
# pass even though the argument was defined as :isPublished
it { is_expected.to accept_argument(:is_published).of_type("Boolean") }
end
end
```
### 4) Test an object's interface implementations:
```ruby
describe PostType do
subject { described_class }
it 'implements interface Node' do
expect(subject).to implement('Node')
end
it { is_expected.not_to implement('OtherInterface') }
end
```
### 5) 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::Types::Relay::Node
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
- New matchers!
## Contributing
- Send Bug reports, suggestions or any general
question through the [Issue tracker](https://github.com/khamusa/rspec-graphql_matchers/issues).
Think of another matcher that could be useful? This is the place to ask, or...
- Pull requests are welcome through the usual procedure: fork the project,
commit your changes and open the [PR](https://github.com/khamusa/rspec-graphql_matchers/pulls).
This project is intended to be a safe, welcoming space for collaboration, and
contributors are expected to adhere to the
[Contributor Covenant](http://contributor-covenant.org) code of conduct.
## License
The gem is available as open source under the terms of the
[MIT License](http://opensource.org/licenses/MIT).
================================================
FILE: Rakefile
================================================
# frozen_string_literal: true
require 'bundler/gem_tasks'
require 'rspec/core/rake_task'
require 'rubocop/rake_task'
RSpec::Core::RakeTask.new(:spec)
RuboCop::RakeTask.new
task default: %i[spec rubocop]
================================================
FILE: bin/console
================================================
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/setup'
require 'rspec/graphql_matchers'
# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.
# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start
require 'irb'
IRB.start
================================================
FILE: bin/setup
================================================
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx
bundle install
# Do any other automated setup that you need to do here
================================================
FILE: lib/rspec/graphql_matchers/accept_argument.rb
================================================
# frozen_string_literal: true
require_relative 'base_matcher'
require_relative './have_a_field_matchers/of_type'
module RSpec
module GraphqlMatchers
class AcceptArgument < BaseMatcher
def initialize(expected_arg_name)
@expectations = []
if expected_arg_name.is_a?(Hash)
(expected_arg_name, expected_type) = expected_arg_name.to_a.first
of_type(expected_type)
warn 'DEPRECATION WARNING: using accept_arguments with a hash will be '\
'deprecated on the next major release. Use the format ' \
"`accept_argument(:argument_name).of_type('ExpectedType!') instead.`"
end
@expected_arg_name = expected_arg_name.to_s
@expected_camel_arg_name = GraphQL::Schema::Member::BuildType.camelize(
@expected_arg_name
)
end
def matches?(graph_object)
@graph_object = graph_object
@actual_argument = field_arguments[@expected_arg_name]
@actual_argument ||= field_arguments[@expected_camel_arg_name]
return false if @actual_argument.nil?
@results = @expectations.reject do |matcher|
matcher.matches?(@actual_argument)
end
@results.empty?
end
def of_type(expected_field_type)
@expectations << HaveAFieldMatchers::OfType.new(expected_field_type)
self
end
def failure_message
base_msg = "expected #{member_name(@graph_object)} " \
"to accept argument `#{@expected_arg_name}`" \
return "#{base_msg} #{failure_messages.join(', ')}" if @actual_argument
"#{base_msg} but no argument was found with that name"
end
def description
["accept argument `#{@expected_arg_name}`"].concat(descriptions).join(', ')
end
private
def descriptions
results.map(&:description)
end
def failure_messages
results.map(&:failure_message)
end
def field_arguments
if @graph_object.respond_to?(:arguments)
@graph_object.public_send(:arguments)
else
raise "Invalid object #{@graph_object} provided to accept_argument " \
'matcher. It does not seem to be a valid GraphQL object type.'
end
end
def results
@results ||= []
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/accept_arguments.rb
================================================
# frozen_string_literal: true
require_relative 'base_matcher'
module RSpec
module GraphqlMatchers
class AcceptArguments < BaseMatcher
attr_reader :actual_field, :expected_args
def initialize(expected_args)
@expected_args = expected_args
end
def matches?(actual_field)
@actual_field = actual_field
@expected_args.all? do |arg_name, arg_type|
matches_argument?(arg_name, arg_type)
end
end
def failure_message
"expected field '#{member_name(actual_field)}' to accept arguments "\
"#{describe_arguments(expected_args)}"
end
def description
"accept arguments #{describe_arguments(expected_args)}"
end
private
def matches_argument?(arg_name, arg_type)
camel_arg_name = GraphQL::Schema::Member::BuildType.camelize(arg_name.to_s)
actual_arg = actual_field.arguments[arg_name.to_s]
actual_arg ||= actual_field.arguments[camel_arg_name]
actual_arg && types_match?(actual_arg.type, arg_type)
end
def describe_arguments(what_args)
what_args.sort.map do |arg_name, arg_type|
"#{arg_name}(#{type_name(arg_type)})"
end.join(', ')
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/base_matcher.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
class BaseMatcher
private
def member_name(member)
member.respond_to?(:graphql_name) && member.graphql_name ||
member.respond_to?(:name) && member.name ||
member.inspect
end
def types_match?(actual_type, expected_type)
expected_type.nil? || type_name(expected_type) == type_name(actual_type)
end
def type_name(a_type)
a_type = a_type.to_type_signature if a_type.respond_to?(:to_type_signature)
a_type.to_s
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/be_of_type.rb
================================================
# frozen_string_literal: true
require_relative 'base_matcher'
module RSpec
module GraphqlMatchers
class BeOfType < BaseMatcher
attr_reader :sample, :expected
def initialize(expected)
@expected = expected
end
def matches?(actual_sample)
@sample = to_graphql(actual_sample)
sample.respond_to?(:type) && types_match?(sample.type, @expected)
end
def failure_message
"expected field '#{member_name(sample)}' to " \
"be of type '#{type_name(expected)}', " \
"but it was '#{type_name(sample.type)}'"
end
def description
"be of type '#{expected}'"
end
private
def to_graphql(field_sample)
return field_sample unless field_sample.respond_to?(:to_type_signature)
field_sample.to_type_signature
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field.rb
================================================
# frozen_string_literal: true
require_relative 'base_matcher'
require_relative './have_a_field_matchers/of_type'
require_relative './have_a_field_matchers/with_property'
require_relative './have_a_field_matchers/with_metadata'
require_relative './have_a_field_matchers/with_hash_key'
require_relative './have_a_field_matchers/with_deprecation_reason'
module RSpec
module GraphqlMatchers
class HaveAField < BaseMatcher
def initialize(expected_field_name, fields = :fields)
@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
return false if actual_field.nil?
@results = @expectations.reject do |matcher|
matcher.matches?(actual_field)
end
@results.empty?
end
def that_returns(expected_field_type)
@expectations << HaveAFieldMatchers::OfType.new(expected_field_type)
self
end
alias returning that_returns
alias of_type that_returns
def with_property(expected_property_name)
@expectations << HaveAFieldMatchers::WithProperty.new(expected_property_name)
self
end
def with_hash_key(expected_hash_key)
@expectations << HaveAFieldMatchers::WithHashKey.new(expected_hash_key)
self
end
def with_metadata(expected_metadata)
@expectations << HaveAFieldMatchers::WithMetadata.new(expected_metadata)
self
end
def with_deprecation_reason(expected_reason = nil)
@expectations << HaveAFieldMatchers::WithDeprecationReason.new(expected_reason)
self
end
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
"#{base_msg} but no field was found with that name"
end
def description
["define field `#{@expected_field_name}`"].concat(descriptions).join(', ')
end
private
def actual_field
@actual_field ||= begin
field = field_collection[@expected_field_name]
field ||= field_collection[@expected_camel_field_name]
field.respond_to?(:to_type_signature) ? field.to_type_signature : field
end
end
def descriptions
results.map(&:description)
end
def failure_messages
results.map(&:failure_message)
end
def field_collection
if @graph_object.respond_to?(@fields)
@graph_object.public_send(@fields)
else
raise "Invalid object #{@graph_object} provided to #{matcher_name} " \
'matcher. It does not seem to be a valid GraphQL object type.'
end
end
def matcher_name
case @fields
when :fields then 'have_a_field'
when :arguments then 'have_an_input_field'
end
end
def results
@results ||= []
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/of_type.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
module HaveAFieldMatchers
class OfType < RSpec::GraphqlMatchers::BeOfType
def description
"of type `#{type_name(expected)}`"
end
def failure_message
"#{description}, but it was `#{type_name(sample.type)}`"
end
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_deprecation_reason.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
module HaveAFieldMatchers
class WithDeprecationReason
def initialize(expected_reason)
@expected_reason = expected_reason
end
def matches?(actual_field)
@actual_reason = actual_field.deprecation_reason
if @expected_reason.nil?
!actual_field.deprecation_reason.nil?
else
actual_field.deprecation_reason == @expected_reason
end
end
def failure_message
message = "#{description}, but it was "
message + (@actual_reason.nil? ? 'not deprecated' : "`#{@actual_reason}`")
end
def description
if @expected_reason.nil?
'with a deprecation reason'
else
"with deprecation reason `#{@expected_reason}`"
end
end
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_hash_key.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
module HaveAFieldMatchers
class WithHashKey
def initialize(expected_hash_key)
@expected_hash_key = expected_hash_key
end
def description
"with hash key `#{@expected_hash_key}`"
end
def matches?(actual_field)
@actual_hash_key = get_hash_key(actual_field)
@actual_hash_key == @expected_hash_key.to_sym
end
def failure_message
"#{description}, but it was `#{@actual_hash_key}`"
end
private
def get_hash_key(actual_field)
if actual_field.respond_to?(:hash_key)
return actual_field.hash_key.to_sym if actual_field.hash_key
end
if actual_field.respond_to?(:metadata)
return actual_field.metadata[:type_class].method_sym
end
actual_field.method_sym
end
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_metadata.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
module HaveAFieldMatchers
class WithMetadata
def initialize(expected_metadata)
@expected_metadata = expected_metadata
end
def description
"with metadata `#{@expected_metadata}`"
end
def matches?(actual_field)
@actual_metadata = actual_field.metadata
actual_field.metadata == @expected_metadata
end
def failure_message
"#{description}, but it was `#{@actual_metadata}`"
end
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_property.rb
================================================
# frozen_string_literal: true
module RSpec
module GraphqlMatchers
module HaveAFieldMatchers
class WithProperty
def initialize(expected_property_name)
@expected_property_name = expected_property_name
end
def description
"resolving with property `#{@expected_property_name}`"
end
def matches?(actual_field)
@actual_property = property(actual_field).to_sym
@actual_property == @expected_property_name.to_sym
end
def failure_message
"#{description}, but it was `#{@actual_property}`"
end
private
def property(field)
property = field.property
property = field.metadata[:type_class].method_sym if property.nil?
property
end
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/implement.rb
================================================
# frozen_string_literal: true
require_relative 'base_matcher'
module RSpec
module GraphqlMatchers
class Implement < BaseMatcher
def initialize(interfaces)
@expected = interfaces.map { |interface| interface_name(interface) }
end
def matches?(graph_object)
@graph_object = graph_object
@actual = actual
@expected.all? { |name| @actual.include?(name) }
end
def failure_message
message = "expected interfaces: #{@expected.join(', ')}\n"
message += "actual interfaces: #{@actual.join(', ')}"
message
end
def failure_message_when_negated
message = "unexpected interfaces: #{@expected.join(', ')}\n"
message += "actual interfaces: #{@actual.join(', ')}"
message
end
def description
"implement #{@expected.join(', ')}"
end
private
def actual
if @graph_object.respond_to?(:interfaces)
return @graph_object.interfaces.map do |interface|
interface_name(interface)
end
end
raise "Invalid object #{@graph_object} provided to #{matcher_name} " \
'matcher. It does not seem to be a valid GraphQL object type.'
end
def interface_name(interface)
return interface.graphql_name if interface.respond_to?(:graphql_name)
interface.to_s
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/matchers.rb
================================================
# frozen_string_literal: true
require 'rspec/matchers'
require 'rspec/graphql_matchers/be_of_type'
require 'rspec/graphql_matchers/accept_arguments'
require 'rspec/graphql_matchers/accept_argument'
require 'rspec/graphql_matchers/have_a_field'
require 'rspec/graphql_matchers/implement'
module RSpec
module Matchers
def be_of_type(expected)
RSpec::GraphqlMatchers::BeOfType.new(expected)
end
def accept_argument(expected_argument)
RSpec::GraphqlMatchers::AcceptArgument.new(expected_argument)
end
def accept_arguments(expected_args)
RSpec::GraphqlMatchers::AcceptArguments.new(expected_args)
end
# rubocop:disable Naming/PredicateName
def have_a_field(field_name)
RSpec::GraphqlMatchers::HaveAField.new(field_name)
end
alias have_field have_a_field
def have_an_input_field(field_name)
RSpec::GraphqlMatchers::HaveAField.new(field_name, :arguments)
end
alias have_input_field have_an_input_field
def have_a_return_field(field_name)
RSpec::GraphqlMatchers::HaveAField.new(field_name)
end
alias have_return_field have_a_return_field
# rubocop:enable Naming/PredicateName
def implement(*interface_names)
RSpec::GraphqlMatchers::Implement.new(interface_names.flatten)
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/types_helper.rb
================================================
# frozen_string_literal: true
require 'graphql'
module RSpec
module GraphqlMatchers
module TypesHelper
class << self
extend Gem::Deprecate
GraphQL::Types.constants.each do |constant_name|
klass = GraphQL::Types.const_get(constant_name)
define_method(constant_name) { klass }
deprecate constant_name, "GraphQL::Types::#{constant_name}", 2023, 10
end
end
def types
TypesHelper
end
end
end
end
================================================
FILE: lib/rspec/graphql_matchers/version.rb
================================================
# frozen_string_literal: true
module Rspec
module GraphqlMatchers
VERSION = '2.0.0-rc.0'.freeze
end
end
================================================
FILE: lib/rspec/graphql_matchers.rb
================================================
# frozen_string_literal: true
require 'rspec/graphql_matchers/version'
require 'rspec/graphql_matchers/matchers'
require 'rspec/graphql_matchers/types_helper'
================================================
FILE: rspec-graphql_matchers.gemspec
================================================
# frozen_string_literal: true
lib = File.expand_path('lib', __dir__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'rspec/graphql_matchers/version'
Gem::Specification.new do |spec|
spec.name = 'rspec-graphql_matchers'
spec.version = Rspec::GraphqlMatchers::VERSION
spec.authors = ['Samuel Brandão']
spec.email = ['gb.samuel@gmail.com']
spec.summary = 'Collection of rspec matchers to test your graphQL api schema.'
spec.homepage = 'https://github.com/khamusa/rspec-graphql_matchers'
spec.license = 'MIT'
spec.files =
`git ls-files -z`
.split("\x0")
.reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.bindir = 'exe'
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ['lib']
spec.add_dependency 'graphql', '~> 2.0'
spec.add_dependency 'rspec', '~> 3.0'
spec.add_development_dependency 'bundler', '~> 2.0'
# CodeClimate does not yet support SimpleCov 0.18
spec.add_development_dependency 'simplecov', '~>0.17.0'
spec.add_development_dependency 'pry', '~> 0'
spec.add_development_dependency 'rubocop', '0.71'
end
================================================
FILE: spec/rspec/accept_argument_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
module RSpec
module GraphqlMatchers
describe 'expect(a_type).to accept_argument(field_name)' do
subject(:a_type) do
Class.new(GraphQL::Schema::InputObject) do
graphql_name 'TestObject'
argument :id, GraphQL::Types::String, required: false
argument :other, GraphQL::Types::ID, required: true
argument :is_test, GraphQL::Types::Boolean, required: false
argument :not_camelized, GraphQL::Types::Boolean, required: false,
camelize: false
end
end
it { is_expected.to accept_argument(:id) }
it 'passes when the type defines the field' do
expect(a_type).to accept_argument(:id)
end
it 'passes with the underscored argument name' do
expect(a_type).to accept_argument(:is_test)
end
it 'passes with the camel cased argument name' do
expect(a_type).to accept_argument(:isTest)
end
it 'matches a non camelized argument with the underscored argument name' do
expect(a_type).to accept_argument(:not_camelized)
end
it 'fails when the type does not define the expected field' do
expect { expect(a_type).to accept_argument(:ids) }
.to fail_with(
'expected TestObject to accept argument `ids` but no argument was found ' \
'with that name'
)
end
it 'fails with a failure message when the type does not define the field' do
expect { expect(a_type).to accept_argument(:ids) }
.to fail_with(
'expected TestObject to accept argument `ids` but no argument ' \
'was found with that name'
)
end
it 'provides a description' do
matcher = accept_argument(:id)
matcher.matches?(a_type)
expect(matcher.description).to eq('accept argument `id`')
end
describe '.of_type(a_type)' do
it 'passes when the type defines the field with correct type as ' \
'strings' do
expect(a_type).to accept_argument(:id).of_type('String')
expect(a_type).to accept_argument('other').of_type('ID!')
expect(a_type).to accept_argument('other' => 'ID!')
end
it 'passes when the type defines the field with correct type as ' \
'graphql objects' do
expect(a_type).to accept_argument(:id).of_type(GraphQL::Types::String)
expect(a_type).to accept_argument('other').of_type('ID!')
end
it 'fails when the type defines a field of the wrong type' do
expect { expect(a_type).to accept_argument(:id).of_type('String!') }
.to fail_with(
'expected TestObject to accept argument `id` ' \
'of type `String!`, but it was `String`'
)
expect { expect(a_type).to accept_argument('other').of_type(GraphQL::Types::Int.to_non_null_type) }
.to fail_with(
'expected TestObject to accept argument `other` ' \
'of type `Int!`, but it was `ID!`'
)
expect { expect(a_type).to accept_argument('other' => GraphQL::Types::Int.to_non_null_type) }
.to fail_with(
'expected TestObject to accept argument `other` ' \
'of type `Int!`, but it was `ID!`'
)
end
context 'when an invalid type is passed' do
let(:a_type) { {} }
it 'fails with a Runtime error' do
expect { expect(a_type).to accept_argument(:id) }
.to raise_error(
RuntimeError,
'Invalid object {} provided to accept_argument ' \
'matcher. It does not seem to be a valid GraphQL object type.'
)
end
end
end
end
end
end
================================================
FILE: spec/rspec/accept_arguments_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
require 'graphql'
describe 'expect(a_field).to accept_arguments(arg_name: arg_type, ...)' do
subject(:field) do
Class.new(GraphQL::Schema::InputObject) do
graphql_name 'SomeInputObject'
argument :id, GraphQL::Types::ID, required: true
argument :name, GraphQL::Types::String, required: true
argument :age, GraphQL::Types::Int, required: false
argument :is_test, GraphQL::Types::Boolean, required: false
argument :not_camelized, GraphQL::Types::Boolean, required: false, camelize: false
end
end
describe '#matches?' do
context 'when expecting a single argument with type' do
let(:expected_args) { { id: GraphQL::Types::ID.to_non_null_type } }
context 'when the field accepts the expected argument name and type' do
it { is_expected.to accept_arguments(expected_args) }
end
context 'the field accepts an argument with the same name but different type' do
let(:expected_args) { { id: GraphQL::Types::ID } }
it { is_expected.not_to accept_arguments(expected_args) }
end
context 'the field does not accept the expected args' do
let(:expected_args) { { idz: GraphQL::Types::ID.to_non_null_type } }
it { is_expected.not_to accept_arguments(expected_args) }
end
context 'when the expected argument is camelcase' do
let(:expected_args) { { isTest: GraphQL::Types::Boolean } }
it { is_expected.to accept_arguments(expected_args) }
end
context 'when the expected argument is underscored' do
let(:expected_args) { { is_test: GraphQL::Types::Boolean } }
it { is_expected.to accept_arguments(expected_args) }
context 'when the actual argument is not camelized' do
let(:expected_args) { { not_camelized: GraphQL::Types::Boolean } }
it { is_expected.to accept_arguments(expected_args) }
end
end
end
context 'when expecting multiple arguments with type' do
context 'when the field accepts only one argument with correct name and type' do
let(:expected_args) do
{
id: GraphQL::Types::ID.to_non_null_type,
age: GraphQL::Types::Int.to_list_type,
name: GraphQL::Types::String
}
end
it { is_expected.not_to accept_arguments(expected_args) }
end
context 'when the field accepts all but one of the argument expected args' do
let(:expected_args) do
{
id: GraphQL::Types::ID.to_non_null_type,
age: GraphQL::Types::Int,
name: GraphQL::Types::Float.to_non_null_type
}
end
it { is_expected.not_to accept_arguments(expected_args) }
end
context 'when the field accepts all arguments with correct type' do
let(:expected_args) do
{
id: GraphQL::Types::ID.to_non_null_type,
age: GraphQL::Types::Int,
name: GraphQL::Types::String.to_non_null_type
}
end
it { is_expected.to accept_arguments(expected_args) }
end
end
end
describe '#description' do
let(:matcher) { accept_arguments(expected_args) }
subject(:description) do
matcher.matches?(field)
matcher.description
end
context 'with a single expected argument with types specified' do
let(:expected_args) { { ability: 'Float' } }
it 'returns a description with the argument name and type' do
expect(description)
.to eq('accept arguments ability(Float)')
end
end
context 'with multiple expected arguments with types specified' do
let(:expected_args) do
{ ability: GraphQL::Types::Int, id: GraphQL::Types::Int, some: GraphQL::Types::Boolean }
end
it 'describes the arguments the field should accept and their types' do
expect(description)
.to eq('accept arguments ability(Int), id(Int), some(Boolean)')
end
end
end
describe '#failure_message' do
let(:matcher) { accept_arguments(expected_args) }
let(:expected_args) { { will: 'NotMatch' } }
subject(:failure_message) do
matcher.matches?(field)
matcher.failure_message
end
it 'informs the expected and actual types' do
expect(failure_message).to end_with(
'to accept arguments will(NotMatch)'
)
end
it 'describes the field through #name' do
expect(failure_message)
.to start_with("expected field 'SomeInputObject' to")
end
end
end
================================================
FILE: spec/rspec/be_of_type_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
describe 'expect(a_field).to be_of_type(graphql_type)' do
scalar_types = {
"Boolean" => GraphQL::Types::Boolean,
"Int" => GraphQL::Types::Int,
"Float" => GraphQL::Types::Float,
"String" => GraphQL::Types::String,
"ID" => GraphQL::Types::ID
}
non_nullable_scalar_types = scalar_types.each_with_object({}) do |(string_name, type), result|
result["#{string_name}!"] = type.to_non_null_type
end
all_types = scalar_types.merge(non_nullable_scalar_types)
all_types.each do |(graphql_name, scalar_type)|
context "when the field has type #{graphql_name}" do
subject(:field) { double('GrahQL Field', type: field_type) }
let(:field_type) { scalar_type }
it "matches a graphQL type object representing #{graphql_name}" do
expect(field).to be_of_type(scalar_type)
end
it "matches the string '#{graphql_name}'" do
expect(field).to be_of_type(graphql_name)
end
it "does not match the string '#{graphql_name.downcase}'" do
expect(field).not_to be_of_type(graphql_name.downcase)
end
scalar_types.each do |(another_graphql_name, another_scalar)|
next if another_scalar == scalar_type
context "when matching against the type #{another_scalar}" do
let(:matcher) { be_of_type(expected_type) }
let(:expected_type) { another_scalar }
it 'does not match' do
expect(matcher.matches?(field)).to be_falsy
end
describe 'the failure messages' do
subject(:failure_message) { matcher.failure_message }
before { matcher.matches?(field) }
it 'informs the expected and actual types' do
expect(failure_message).to end_with(
"to be of type '#{another_graphql_name}', but it was '#{graphql_name}'"
)
end
context 'the field does not respond to #name' do
it 'describes the field through #inspect' do
expect(failure_message).to start_with(
"expected field '#{field.inspect}' to be of type"
)
end
end
context 'the field responds to #name' do
before { allow(field).to receive(:name).and_return('AField') }
it 'describes the field through #name' do
expect(failure_message)
.to start_with("expected field 'AField' to be of type")
end
end
end
end
end
end
end
describe '#description' do
let(:matcher) { be_of_type(String) }
it %q(is "be of type 'String'") do
matcher.matches?(double(type: 'NotMeaningful'))
expect(matcher.description).to eq("be of type 'String'")
end
end
end
================================================
FILE: spec/rspec/graphql_matchers_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
describe Rspec::GraphqlMatchers do
it 'has a version number' do
expect(Rspec::GraphqlMatchers::VERSION).not_to be nil
end
end
================================================
FILE: spec/rspec/have_a_field_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
module RSpec
module GraphqlMatchers
describe 'expect(a_type).to have_a_field(field_name)' do
shared_examples 'have a field' do
it { is_expected.to have_a_field(:id) }
it 'passes when the type defines the field' do
expect(a_type).to have_a_field(:id)
end
it 'passes with the underscored field name' do
expect(a_type).to have_a_field(:is_test)
end
it 'passes with the camel cased field name' do
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(
'expected TestObject to define field `ids` but no field was found ' \
'with that name'
)
end
it 'fails with a failure message when the type does not define the field' do
expect { expect(a_type).to have_a_field(:ids) }
.to fail_with(
'expected TestObject to define field `ids` but no field ' \
'was found with that name'
)
end
it 'provides a description' do
matcher = have_a_field(:id)
matcher.matches?(a_type)
expect(matcher.description).to eq('define field `id`')
end
describe '.that_returns(a_type)' do
it 'passes when the type defines the field with correct type as ' \
'strings' do
expect(a_type).to have_a_field(:id).that_returns('ID!')
expect(a_type).to have_a_field('other').that_returns('String')
expect(a_type).to have_a_field(:is_test).of_type('Boolean')
expect(a_type).to have_a_field(:isTest).of_type('Boolean')
end
it 'passes when the type defines the field with correct type as ' \
'graphql objects' do
expect(a_type).to have_a_field(:id).that_returns('ID!')
expect(a_type).to have_a_field('other').of_type(GraphQL::Types::String)
expect(a_type).to have_a_field(:is_test).of_type(GraphQL::Types::Boolean)
expect(a_type).to have_a_field(:isTest).of_type(GraphQL::Types::Boolean)
end
it 'fails when the type defines a field of the wrong type' do
expect { expect(a_type).to have_a_field(:id).returning('ID') }
.to fail_with(
'expected TestObject to define field `id` ' \
'of type `ID`, but it was `ID!`'
)
expect { expect(a_type).to have_a_field('other')
.returning(GraphQL::Types::Int.to_non_null_type) }
.to fail_with(
'expected TestObject to define field `other` ' \
'of type `Int!`, but it was `String`'
)
end
context 'when an invalid type is passed' do
let(:a_type) { {} }
it 'fails with a Runtime error' do
expect { expect(a_type).to have_a_field(:id) }
.to raise_error(
RuntimeError,
'Invalid object {} provided to have_a_field ' \
'matcher. It does not seem to be a valid GraphQL object type.'
)
end
end
end
describe '.with_hash_key(hash_key)' do
it { is_expected.to have_a_field(:other).with_hash_key(:other_on_hash) }
it { is_expected.to have_a_field(:other).with_hash_key('other_on_hash') }
it 'fails when the hash_key is incorrect' do
expect do
expect(a_type).to have_a_field(:other).with_hash_key(:whatever)
end.to fail_with(
'expected TestObject to define field `other` ' \
'with hash key `whatever`, but it was `other_on_hash`'
)
end
end
describe '.with_deprecation_reason' do
context 'when the field has a deprecation reason' do
let(:deprecated_field) { :deprecated_field }
context 'with an expected deprecation reason' do
it 'passes when the deprecation reasons match' do
expect(a_type).to have_a_field(deprecated_field)
.with_deprecation_reason('deprecated')
end
it 'fails when the deprecation reasons do not match' do
expect do
expect(a_type).to have_a_field(deprecated_field)
.with_deprecation_reason('different deprecation reason')
end.to fail_with(
'expected TestObject to define field `deprecated_field` with ' \
'deprecation reason `different deprecation reason`, ' \
'but it was `deprecated`'
)
end
end
context 'without an expected deprecation reason' do
it 'passes' do
expect(a_type).to have_a_field(deprecated_field).with_deprecation_reason
end
end
end
context 'when the field does not have a deprecation reason' do
let(:non_deprecated_field) { :id }
it 'fails without an expected deprecation reason' do
expect do
expect(a_type).to have_a_field(non_deprecated_field)
.with_deprecation_reason
end.to fail_with(
'expected TestObject to define field `id` with a deprecation reason, ' \
'but it was not deprecated'
)
end
it 'fails with an expected deprecation reason' do
expect do
expect(a_type).to have_a_field(non_deprecated_field)
.with_deprecation_reason('deprecated')
end.to fail_with(
'expected TestObject to define field `id` with deprecation ' \
'reason `deprecated`, but it was not deprecated'
)
end
end
end
end
subject(:a_type) do
Class.new(GraphQL::Schema::Object) do
graphql_name 'TestObject'
field :id, GraphQL::Types::ID, null: false
field :other, GraphQL::Types::String, hash_key: :other_on_hash, null: true
field :is_test, GraphQL::Types::Boolean, null: true
field :not_camelized, GraphQL::Types::String, null: false, camelize: false
field :deprecated_field, GraphQL::Types::String, null: true,
deprecation_reason: 'deprecated'
end
end
include_examples 'have a field'
context 'with fields defined by implementing an interface' do
subject(:a_type) do
actual_interface = Module.new do
include GraphQL::Schema::Interface
graphql_name 'ActualInterface'
field :other, GraphQL::Types::String, hash_key: :other_on_hash, null: true
field :is_test, GraphQL::Types::Boolean, null: true
field :not_camelized, GraphQL::Types::String, null: false, camelize: false
field :deprecated_field, GraphQL::Types::String, null: true,
deprecation_reason: 'deprecated'
end
Class.new(GraphQL::Schema::Object) do
graphql_name 'TestObject'
implements actual_interface
implements GraphQL::Types::Relay::Node
end
end
include_examples 'have a field'
end
end
end
end
================================================
FILE: spec/rspec/have_a_return_field_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
module RSpec
module GraphqlMatchers
describe 'expect(a_type).to have_a_return_field(field_name)' \
'.that_returns(a_type)' do
subject(:a_type) do
Class.new(GraphQL::Schema::RelayClassicMutation) do
graphql_name 'TestObject'
field :id, GraphQL::Types::String
field :other, GraphQL::Types::ID, null: false
end
end
it { is_expected.to have_a_return_field(:id) }
it 'passes when the type defines the field' do
expect(a_type).to have_a_return_field(:id)
end
it 'fails when the type does not define the expected field' do
expect(a_type).not_to have_a_return_field(:ids)
end
it 'fails with a failure message when the type does not define the field' do
expect { expect(a_type).to have_a_return_field(:ids) }
.to fail_with(
"expected #{a_type.graphql_name} to define field `ids` but no field was " \
'found with that name'
)
end
it 'provides a description' do
matcher = have_a_return_field(:id)
matcher.matches?(a_type)
expect(matcher.description).to eq('define field `id`')
end
it 'passes when the type defines the field with correct type as strings' do
expect(a_type).to have_a_return_field(:id).that_returns('String')
expect(a_type).to have_a_return_field('other').that_returns('ID!')
end
it 'passes when the type defines the field with correct type as graphql ' \
'objects' do
expect(a_type).to have_a_return_field(:id).that_returns(GraphQL::Types::String)
expect(a_type).to have_a_return_field('other').that_returns(GraphQL::Types::ID.to_non_null_type)
end
it 'fails when the type defines a field of the wrong type' do
expect { expect(a_type).to have_a_return_field(:id).returning('String!') }
.to fail_with(
"expected #{a_type.graphql_name} to define field `id` of type `String!`, " \
'but it was `String`'
)
expect do
expect(a_type).to have_a_return_field('other').returning(GraphQL::Types::Int.to_non_null_type)
end.to fail_with(
"expected #{a_type.graphql_name} to define field `other` of type `Int!`, " \
'but it was `ID!`'
)
end
context 'when an invalid type is passed' do
let(:a_type) { double(to_s: 'InvalidObject') }
it 'fails with a Runtime error' do
expect { expect(a_type).to have_a_return_field(:id) }
.to raise_error(
RuntimeError,
'Invalid object InvalidObject provided to have_a_field ' \
'matcher. It does not seem to be a valid GraphQL object type.'
)
end
end
end
end
end
================================================
FILE: spec/rspec/have_an_input_field_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
module RSpec
module GraphqlMatchers
describe 'expect(a_type).to have_an_input_field(field_name)' \
'.that_returns(a_type)' do
subject(:a_type) do
Class.new(GraphQL::Schema::RelayClassicMutation) do
graphql_name 'TestObject'
argument :id, GraphQL::Types::String, required: false
argument :other, GraphQL::Types::ID, required: true
end
end
it { is_expected.to have_an_input_field(:id) }
it 'passes when the type defines the field' do
expect(a_type).to have_an_input_field(:id)
end
it 'fails when the type does not define the expected field' do
expect(a_type).not_to have_an_input_field(:ids)
end
it 'fails with a failure message when the type does not define the field' do
expect { expect(a_type).to have_an_input_field(:ids) }
.to fail_with(
"expected #{a_type.graphql_name} to define field `ids` but no field was " \
'found with that name'
)
end
it 'provides a description' do
matcher = have_an_input_field(:id)
matcher.matches?(a_type)
expect(matcher.description).to eq('define field `id`')
end
it 'passes when the type defines the field with correct type as strings' do
expect(a_type).to have_an_input_field(:id).that_returns('String')
expect(a_type).to have_an_input_field('other').that_returns('ID!')
end
it 'passes when the type defines the field with correct type as graphql ' \
'objects' do
expect(a_type).to have_an_input_field(:id).that_returns(GraphQL::Types::String)
expect(a_type).to have_an_input_field('other').that_returns(GraphQL::Types::ID.to_non_null_type)
end
it 'fails when the type defines a field of the wrong type' do
expect { expect(a_type).to have_an_input_field(:id).returning('String!') }
.to fail_with(
"expected #{a_type.graphql_name} to define field `id` of type `String!`, " \
'but it was `String`'
)
expect do
expect(a_type).to have_an_input_field('other').returning(GraphQL::Types::Int.to_non_null_type)
end.to fail_with(
"expected #{a_type.graphql_name} to define field `other` of type `Int!`, " \
'but it was `ID!`'
)
end
context 'when an invalid type is passed' do
let(:a_type) { double(to_s: 'InvalidObject') }
it 'fails with a Runtime error' do
expect { expect(a_type).to have_an_input_field(:id) }
.to raise_error(
RuntimeError,
'Invalid object InvalidObject provided to have_an_input_field ' \
'matcher. It does not seem to be a valid GraphQL object type.'
)
end
end
end
end
end
================================================
FILE: spec/rspec/implement_matcher_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
module RSpec
module GraphqlMatchers
describe 'expect(a_type).to implement(interface_names)' do
AnInterface = Module.new do
include GraphQL::Schema::Interface
graphql_name 'AnInterface'
end
AnotherInterface = Module.new do
include GraphQL::Schema::Interface
graphql_name 'AnotherInterface'
end
AThirdInterface = Module.new do
include GraphQL::Schema::Interface
graphql_name 'AClassBasedApiInterface'
end
subject(:a_type) do
Class.new(GraphQL::Schema::Object) do
graphql_name 'TestObject'
implements GraphQL::Types::Relay::Node
implements AnInterface
implements AThirdInterface
end
end
it { is_expected.to implement('Node') }
it { is_expected.to implement('AnInterface') }
it { is_expected.to implement('AClassBasedApiInterface') }
it { is_expected.to implement('Node', 'AnInterface', 'AClassBasedApiInterface') }
it { is_expected.to implement(['Node']) }
it { is_expected.to implement(['AnInterface']) }
it { is_expected.to implement(%w[Node AnInterface]) }
it { is_expected.to implement(GraphQL::Types::Relay::Node, AnInterface) }
it do
is_expected.to implement([GraphQL::Types::Relay::Node, AnInterface])
end
it { is_expected.not_to implement('AnotherInterface') }
it { is_expected.not_to implement(['AnotherInterface']) }
it { is_expected.not_to implement(AnotherInterface) }
it { is_expected.not_to implement([AnotherInterface]) }
it 'fails with a message when the type does include the interfaces' do
expect { expect(a_type).to implement('AnotherInterface') }
.to fail_with(
"expected interfaces: AnotherInterface\n" \
'actual interfaces: Node, AnInterface, AClassBasedApiInterface'
)
end
it 'provides a description' do
matcher = implement('Node, AnInterface')
matcher.matches?(a_type)
expect(matcher.description).to eq('implement Node, AnInterface')
end
context 'when an invalid type is passed' do
let(:a_type) { double(to_s: 'InvalidObject') }
it 'fails with a Runtime error' do
expect { expect(a_type).to have_a_field(:id) }
.to raise_error(
RuntimeError,
'Invalid object InvalidObject provided to have_a_field matcher. ' \
'It does not seem to be a valid GraphQL object type.'
)
end
end
end
end
end
================================================
FILE: spec/rspec/readme_spec.rb
================================================
# frozen_string_literal: true
require 'spec_helper'
describe 'The readme Examples' do
ruby_code_regex = /```ruby(.*?)```/m
readme_content = File.read(
File.expand_path(
'../../README.md',
__dir__
)
)
# rubocop:disable Security/Eval
readme_content.scan(ruby_code_regex) do |ruby_code|
eval(ruby_code[0])
end
# rubocop:enable Security/Eval
end
================================================
FILE: spec/spec_helper.rb
================================================
# frozen_string_literal: true
require 'pry'
require 'simplecov'
SimpleCov.start
$LOAD_PATH.unshift File.expand_path('../lib', __dir__)
require 'rspec/graphql_matchers'
# rubocop:disable Style/MixinUsage
include RSpec::GraphqlMatchers::TypesHelper
# rubocop:enable Style/MixinUsage
module RSpec
module Matchers
def fail_with(message)
raise_error(RSpec::Expectations::ExpectationNotMetError, message)
end
end
end
gitextract_0bqch8nx/
├── .codeclimate.yml
├── .editorconfig
├── .github/
│ └── workflows/
│ └── rspec.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── bin/
│ ├── console
│ └── setup
├── lib/
│ └── rspec/
│ ├── graphql_matchers/
│ │ ├── accept_argument.rb
│ │ ├── accept_arguments.rb
│ │ ├── base_matcher.rb
│ │ ├── be_of_type.rb
│ │ ├── have_a_field.rb
│ │ ├── have_a_field_matchers/
│ │ │ ├── of_type.rb
│ │ │ ├── with_deprecation_reason.rb
│ │ │ ├── with_hash_key.rb
│ │ │ ├── with_metadata.rb
│ │ │ └── with_property.rb
│ │ ├── implement.rb
│ │ ├── matchers.rb
│ │ ├── types_helper.rb
│ │ └── version.rb
│ └── graphql_matchers.rb
├── rspec-graphql_matchers.gemspec
└── spec/
├── rspec/
│ ├── accept_argument_matcher_spec.rb
│ ├── accept_arguments_matcher_spec.rb
│ ├── be_of_type_matcher_spec.rb
│ ├── graphql_matchers_spec.rb
│ ├── have_a_field_matcher_spec.rb
│ ├── have_a_return_field_spec.rb
│ ├── have_an_input_field_matcher_spec.rb
│ ├── implement_matcher_spec.rb
│ └── readme_spec.rb
└── spec_helper.rb
SYMBOL INDEX (131 symbols across 20 files)
FILE: lib/rspec/graphql_matchers/accept_argument.rb
type RSpec (line 6) | module RSpec
type GraphqlMatchers (line 7) | module GraphqlMatchers
class AcceptArgument (line 8) | class AcceptArgument < BaseMatcher
method initialize (line 9) | def initialize(expected_arg_name)
method matches? (line 27) | def matches?(graph_object)
method of_type (line 41) | def of_type(expected_field_type)
method failure_message (line 46) | def failure_message
method description (line 55) | def description
method descriptions (line 61) | def descriptions
method failure_messages (line 65) | def failure_messages
method field_arguments (line 69) | def field_arguments
method results (line 78) | def results
FILE: lib/rspec/graphql_matchers/accept_arguments.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
class AcceptArguments (line 7) | class AcceptArguments < BaseMatcher
method initialize (line 10) | def initialize(expected_args)
method matches? (line 14) | def matches?(actual_field)
method failure_message (line 22) | def failure_message
method description (line 27) | def description
method matches_argument? (line 33) | def matches_argument?(arg_name, arg_type)
method describe_arguments (line 41) | def describe_arguments(what_args)
FILE: lib/rspec/graphql_matchers/base_matcher.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
class BaseMatcher (line 5) | class BaseMatcher
method member_name (line 8) | def member_name(member)
method types_match? (line 14) | def types_match?(actual_type, expected_type)
method type_name (line 18) | def type_name(a_type)
FILE: lib/rspec/graphql_matchers/be_of_type.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
class BeOfType (line 7) | class BeOfType < BaseMatcher
method initialize (line 10) | def initialize(expected)
method matches? (line 14) | def matches?(actual_sample)
method failure_message (line 19) | def failure_message
method description (line 25) | def description
method to_graphql (line 31) | def to_graphql(field_sample)
FILE: lib/rspec/graphql_matchers/have_a_field.rb
type RSpec (line 10) | module RSpec
type GraphqlMatchers (line 11) | module GraphqlMatchers
class HaveAField (line 12) | class HaveAField < BaseMatcher
method initialize (line 13) | def initialize(expected_field_name, fields = :fields)
method matches? (line 22) | def matches?(graph_object)
method that_returns (line 34) | def that_returns(expected_field_type)
method with_property (line 42) | def with_property(expected_property_name)
method with_hash_key (line 47) | def with_hash_key(expected_hash_key)
method with_metadata (line 53) | def with_metadata(expected_metadata)
method with_deprecation_reason (line 58) | def with_deprecation_reason(expected_reason = nil)
method failure_message (line 63) | def failure_message
method description (line 72) | def description
method actual_field (line 78) | def actual_field
method descriptions (line 87) | def descriptions
method failure_messages (line 91) | def failure_messages
method field_collection (line 95) | def field_collection
method matcher_name (line 104) | def matcher_name
method results (line 111) | def results
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/of_type.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
type HaveAFieldMatchers (line 5) | module HaveAFieldMatchers
class OfType (line 6) | class OfType < RSpec::GraphqlMatchers::BeOfType
method description (line 7) | def description
method failure_message (line 11) | def failure_message
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_deprecation_reason.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
type HaveAFieldMatchers (line 5) | module HaveAFieldMatchers
class WithDeprecationReason (line 6) | class WithDeprecationReason
method initialize (line 7) | def initialize(expected_reason)
method matches? (line 11) | def matches?(actual_field)
method failure_message (line 21) | def failure_message
method description (line 26) | def description
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_hash_key.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
type HaveAFieldMatchers (line 5) | module HaveAFieldMatchers
class WithHashKey (line 6) | class WithHashKey
method initialize (line 7) | def initialize(expected_hash_key)
method description (line 11) | def description
method matches? (line 15) | def matches?(actual_field)
method failure_message (line 20) | def failure_message
method get_hash_key (line 26) | def get_hash_key(actual_field)
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_metadata.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
type HaveAFieldMatchers (line 5) | module HaveAFieldMatchers
class WithMetadata (line 6) | class WithMetadata
method initialize (line 7) | def initialize(expected_metadata)
method description (line 11) | def description
method matches? (line 15) | def matches?(actual_field)
method failure_message (line 20) | def failure_message
FILE: lib/rspec/graphql_matchers/have_a_field_matchers/with_property.rb
type RSpec (line 3) | module RSpec
type GraphqlMatchers (line 4) | module GraphqlMatchers
type HaveAFieldMatchers (line 5) | module HaveAFieldMatchers
class WithProperty (line 6) | class WithProperty
method initialize (line 7) | def initialize(expected_property_name)
method description (line 11) | def description
method matches? (line 15) | def matches?(actual_field)
method failure_message (line 20) | def failure_message
method property (line 26) | def property(field)
FILE: lib/rspec/graphql_matchers/implement.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
class Implement (line 7) | class Implement < BaseMatcher
method initialize (line 8) | def initialize(interfaces)
method matches? (line 12) | def matches?(graph_object)
method failure_message (line 18) | def failure_message
method failure_message_when_negated (line 24) | def failure_message_when_negated
method description (line 30) | def description
method actual (line 36) | def actual
method interface_name (line 47) | def interface_name(interface)
FILE: lib/rspec/graphql_matchers/matchers.rb
type RSpec (line 10) | module RSpec
type Matchers (line 11) | module Matchers
function be_of_type (line 12) | def be_of_type(expected)
function accept_argument (line 16) | def accept_argument(expected_argument)
function accept_arguments (line 20) | def accept_arguments(expected_args)
function have_a_field (line 25) | def have_a_field(field_name)
function have_an_input_field (line 30) | def have_an_input_field(field_name)
function have_a_return_field (line 35) | def have_a_return_field(field_name)
function implement (line 41) | def implement(*interface_names)
FILE: lib/rspec/graphql_matchers/types_helper.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
type TypesHelper (line 7) | module TypesHelper
function types (line 20) | def types
FILE: lib/rspec/graphql_matchers/version.rb
type Rspec (line 3) | module Rspec
type GraphqlMatchers (line 4) | module GraphqlMatchers
FILE: spec/rspec/accept_argument_matcher_spec.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
FILE: spec/rspec/have_a_field_matcher_spec.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
FILE: spec/rspec/have_a_return_field_spec.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
FILE: spec/rspec/have_an_input_field_matcher_spec.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
FILE: spec/rspec/implement_matcher_spec.rb
type RSpec (line 5) | module RSpec
type GraphqlMatchers (line 6) | module GraphqlMatchers
FILE: spec/spec_helper.rb
type RSpec (line 12) | module RSpec
type Matchers (line 13) | module Matchers
function fail_with (line 14) | def fail_with(message)
Condensed preview — 40 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (68K chars).
[
{
"path": ".codeclimate.yml",
"chars": 388,
"preview": "---\nengines:\n duplication:\n enabled: true\n config:\n languages:\n - ruby\n - javascript\n - pytho"
},
{
"path": ".editorconfig",
"chars": 332,
"preview": "# EditorConfig help us maintain consistent coding style between different editors.\n#\n# EditorConfig\n# http://editorconfi"
},
{
"path": ".github/workflows/rspec.yml",
"chars": 833,
"preview": "name: RSpec\n\n# Controls when the action will run. Triggers the workflow on push or pull request\n# events but only for th"
},
{
"path": ".gitignore",
"chars": 87,
"preview": "/.bundle/\n/.yardoc\n/Gemfile.lock\n/_yardoc/\n/coverage/\n/doc/\n/pkg/\n/spec/reports/\n/tmp/\n"
},
{
"path": ".rspec",
"chars": 31,
"preview": "--format documentation\n--color\n"
},
{
"path": ".rubocop.yml",
"chars": 562,
"preview": "AllCops:\n DisplayCopNames: true\n DisplayStyleGuide: true\n\nLayout/AlignParameters:\n EnforcedStyle: with_fixed_indentat"
},
{
"path": "CHANGELOG.md",
"chars": 5415,
"preview": "# Changelog\n\n## 2.0.0 (April 16th, 2023)\n\n- Adds compatibility with graphql-ruby 2.0+. If you're still using an earlie"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 2387,
"preview": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, and in the interest of\nfostering an open"
},
{
"path": "Gemfile",
"chars": 138,
"preview": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\n# Specify your gem's dependencies in rspec-graphql_matcher"
},
{
"path": "LICENSE.txt",
"chars": 1081,
"preview": "The MIT License (MIT)\n\nCopyright (c) 2016 Samuel Brandão\n\nPermission is hereby granted, free of charge, to any person ob"
},
{
"path": "README.md",
"chars": 5922,
"preview": "\n\n# Rspec::Graph"
},
{
"path": "Rakefile",
"chars": 206,
"preview": "# frozen_string_literal: true\n\nrequire 'bundler/gem_tasks'\nrequire 'rspec/core/rake_task'\nrequire 'rubocop/rake_task'\n\nR"
},
{
"path": "bin/console",
"chars": 377,
"preview": "#!/usr/bin/env ruby\n# frozen_string_literal: true\n\nrequire 'bundler/setup'\nrequire 'rspec/graphql_matchers'\n\n# You can a"
},
{
"path": "bin/setup",
"chars": 131,
"preview": "#!/usr/bin/env bash\nset -euo pipefail\nIFS=$'\\n\\t'\nset -vx\n\nbundle install\n\n# Do any other automated setup that you need "
},
{
"path": "lib/rspec/graphql_matchers/accept_argument.rb",
"chars": 2350,
"preview": "# frozen_string_literal: true\n\nrequire_relative 'base_matcher'\nrequire_relative './have_a_field_matchers/of_type'\n\nmodul"
},
{
"path": "lib/rspec/graphql_matchers/accept_arguments.rb",
"chars": 1262,
"preview": "# frozen_string_literal: true\n\nrequire_relative 'base_matcher'\n\nmodule RSpec\n module GraphqlMatchers\n class AcceptAr"
},
{
"path": "lib/rspec/graphql_matchers/base_matcher.rb",
"chars": 598,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n class BaseMatcher\n private\n\n def memb"
},
{
"path": "lib/rspec/graphql_matchers/be_of_type.rb",
"chars": 865,
"preview": "# frozen_string_literal: true\n\nrequire_relative 'base_matcher'\n\nmodule RSpec\n module GraphqlMatchers\n class BeOfType"
},
{
"path": "lib/rspec/graphql_matchers/have_a_field.rb",
"chars": 3221,
"preview": "# frozen_string_literal: true\n\nrequire_relative 'base_matcher'\nrequire_relative './have_a_field_matchers/of_type'\nrequir"
},
{
"path": "lib/rspec/graphql_matchers/have_a_field_matchers/of_type.rb",
"chars": 370,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n module HaveAFieldMatchers\n class OfType < "
},
{
"path": "lib/rspec/graphql_matchers/have_a_field_matchers/with_deprecation_reason.rb",
"chars": 921,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n module HaveAFieldMatchers\n class WithDepre"
},
{
"path": "lib/rspec/graphql_matchers/have_a_field_matchers/with_hash_key.rb",
"chars": 972,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n module HaveAFieldMatchers\n class WithHashK"
},
{
"path": "lib/rspec/graphql_matchers/have_a_field_matchers/with_metadata.rb",
"chars": 597,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n module HaveAFieldMatchers\n class WithMetad"
},
{
"path": "lib/rspec/graphql_matchers/have_a_field_matchers/with_property.rb",
"chars": 832,
"preview": "# frozen_string_literal: true\n\nmodule RSpec\n module GraphqlMatchers\n module HaveAFieldMatchers\n class WithPrope"
},
{
"path": "lib/rspec/graphql_matchers/implement.rb",
"chars": 1421,
"preview": "# frozen_string_literal: true\n\nrequire_relative 'base_matcher'\n\nmodule RSpec\n module GraphqlMatchers\n class Implemen"
},
{
"path": "lib/rspec/graphql_matchers/matchers.rb",
"chars": 1305,
"preview": "# frozen_string_literal: true\n\nrequire 'rspec/matchers'\nrequire 'rspec/graphql_matchers/be_of_type'\nrequire 'rspec/graph"
},
{
"path": "lib/rspec/graphql_matchers/types_helper.rb",
"chars": 495,
"preview": "# frozen_string_literal: true\n\nrequire 'graphql'\n\nmodule RSpec\n module GraphqlMatchers\n module TypesHelper\n cla"
},
{
"path": "lib/rspec/graphql_matchers/version.rb",
"chars": 113,
"preview": "# frozen_string_literal: true\n\nmodule Rspec\n module GraphqlMatchers\n VERSION = '2.0.0-rc.0'.freeze\n end\nend\n"
},
{
"path": "lib/rspec/graphql_matchers.rb",
"chars": 160,
"preview": "# frozen_string_literal: true\n\nrequire 'rspec/graphql_matchers/version'\nrequire 'rspec/graphql_matchers/matchers'\nrequir"
},
{
"path": "rspec-graphql_matchers.gemspec",
"chars": 1132,
"preview": "# frozen_string_literal: true\n\nlib = File.expand_path('lib', __dir__)\n$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?"
},
{
"path": "spec/rspec/accept_argument_matcher_spec.rb",
"chars": 3909,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule RSpec\n module GraphqlMatchers\n describe 'expect(a_type)"
},
{
"path": "spec/rspec/accept_arguments_matcher_spec.rb",
"chars": 4605,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\nrequire 'graphql'\n\ndescribe 'expect(a_field).to accept_arguments(ar"
},
{
"path": "spec/rspec/be_of_type_matcher_spec.rb",
"chars": 2856,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\ndescribe 'expect(a_field).to be_of_type(graphql_type)' do\n scalar"
},
{
"path": "spec/rspec/graphql_matchers_spec.rb",
"chars": 188,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\ndescribe Rspec::GraphqlMatchers do\n it 'has a version number' do\n"
},
{
"path": "spec/rspec/have_a_field_matcher_spec.rb",
"chars": 7783,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule RSpec\n module GraphqlMatchers\n describe 'expect(a_type)"
},
{
"path": "spec/rspec/have_a_return_field_spec.rb",
"chars": 2877,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule RSpec\n module GraphqlMatchers\n describe 'expect(a_type)"
},
{
"path": "spec/rspec/have_an_input_field_matcher_spec.rb",
"chars": 2912,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule RSpec\n module GraphqlMatchers\n describe 'expect(a_type)"
},
{
"path": "spec/rspec/implement_matcher_spec.rb",
"chars": 2642,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nmodule RSpec\n module GraphqlMatchers\n describe 'expect(a_type)"
},
{
"path": "spec/rspec/readme_spec.rb",
"chars": 383,
"preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\ndescribe 'The readme Examples' do\n ruby_code_regex = /```ruby(.*?"
},
{
"path": "spec/spec_helper.rb",
"chars": 431,
"preview": "# frozen_string_literal: true\n\nrequire 'pry'\nrequire 'simplecov'\nSimpleCov.start\n$LOAD_PATH.unshift File.expand_path('.."
}
]
About this extraction
This page contains the full source code of the khamusa/rspec-graphql_matchers GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 40 files (61.6 KB), approximately 16.1k tokens, and a symbol index with 131 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.