master 97324d257f28 cached
40 files
61.6 KB
16.1k tokens
131 symbols
1 requests
Download .txt
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 Status](https://github.com/khamusa/rspec-graphql_matchers/actions/workflows/rspec.yml/badge.svg)

# 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
Download .txt
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
Download .txt
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": "![RSpec Status](https://github.com/khamusa/rspec-graphql_matchers/actions/workflows/rspec.yml/badge.svg)\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.

Copied to clipboard!