Metadata-Version: 2.1
Name: hypothesis-graphql
Version: 0.8.0
Summary: Hypothesis strategies for GraphQL schemas and queries
Home-page: https://github.com/Stranger6667/hypothesis-graphql
License: MIT
Keywords: hypothesis,graphql,testing
Author: Dmitry Dygalo
Author-email: dadygalo@gmail.com
Requires-Python: >=3.6,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Framework :: Hypothesis
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Software Development :: Testing
Requires-Dist: attrs (>20.3.0)
Requires-Dist: graphql-core (>=3.1.0,<4.0.0)
Requires-Dist: hypothesis (>5.8.0)
Project-URL: Repository, https://github.com/Stranger6667/hypothesis-graphql
Description-Content-Type: text/x-rst

hypothesis-graphql
==================

|Build| |Coverage| |Version| |Python versions| |Chat| |License|

Hypothesis strategies for GraphQL schemas, queries and data.

**NOTE** This package is experimental, some features are not supported yet.

Usage
-----

There are a few strategies for different use cases.

1. Schema generation - ``hypothesis_graphql.strategies.schemas()``
2. Query - ``hypothesis_graphql.strategies.queries(schema)``.
3. Mutation - ``hypothesis_graphql.strategies.mutations(schema)``.

Lets take this schema as an example:

.. code::

    type Book {
      title: String
      author: Author
    }

    type Author {
      name: String
      books: [Book]
    }

    type Query {
      getBooks: [Book]
      getAuthors: [Author]
    }

    type Mutation {
      addBook(title: String!, author: String!): Book!
      addAuthor(name: String!): Author!
    }

Then strategies might be used in this way:

.. code:: python

    from hypothesis import given
    from hypothesis_graphql import strategies as gql_st

    SCHEMA = "..."  # the one above


    @given(gql_st.queries(SCHEMA))
    def test_query(query):
        ...
        # This query might be generated:
        #
        # query {
        #   getBooks {
        #     title
        #   }
        # }


    @given(gql_st.mutations(SCHEMA))
    def test_mutation(mutation):
        ...
        # This mutation might be generated:
        #
        # mutation {
        #   addBook(title: "H4Z\u7869", author: "\u00d2"){
        #     title
        #   }
        # }

Customization
-------------

To restrict the set of fields in generated operations use the ``fields`` argument:

.. code:: python

    @given(gql_st.queries(SCHEMA, fields=["getAuthors"]))
    def test_query(query):
        # Only `getAuthors` will be generated
        ...

It is also possible to generate custom scalars. For example, ``Date``:

.. code:: python

    from hypothesis import strategies as st, given
    from hypothesis_graphql import strategies as gql_st, nodes

    SCHEMA = """
    scalar Date

    type Query {
      getByDate(created: Date!): Int
    }
    """


    @given(
        gql_st.queries(
            SCHEMA,
            custom_scalars={
                # Standard scalars work out of the box, for custom ones you need
                # to pass custom strategies that generate proper AST nodes
                "Date": st.dates().map(nodes.String)
            },
        )
    )
    def test_query(query):
        # Example:
        #
        #  { getByDate(created: "2000-01-01") }
        #
        ...

The ``hypothesis_graphql.nodes`` module includes a few helpers to generate various node types:

- ``String`` -> ``graphql.StringValueNode``
- ``Float`` -> ``graphql.FloatValueNode``
- ``Int`` -> ``graphql.IntValueNode``
- ``Object`` -> ``graphql.ObjectValueNode``
- ``List`` -> ``graphql.ListValueNode``
- ``Boolean`` -> ``graphql.BooleanValueNode``
- ``Enum`` -> ``graphql.EnumValueNode``
- ``Null`` -> ``graphql.NullValueNode`` (a constant, not a function)

They exist because classes like ``graphql.StringValueNode`` can't be directly used in ``map`` calls due to kwarg-only arguments.

.. |Build| image:: https://github.com/Stranger6667/hypothesis-graphql/workflows/build/badge.svg
   :target: https://github.com/Stranger6667/hypothesis-graphql/actions
.. |Coverage| image:: https://codecov.io/gh/Stranger6667/hypothesis-graphql/branch/master/graph/badge.svg
   :target: https://codecov.io/gh/Stranger6667/hypothesis-graphql/branch/master
   :alt: codecov.io status for master branch
.. |Version| image:: https://img.shields.io/pypi/v/hypothesis-graphql.svg
   :target: https://pypi.org/project/hypothesis-graphql/
.. |Python versions| image:: https://img.shields.io/pypi/pyversions/hypothesis-graphql.svg
   :target: https://pypi.org/project/hypothesis-graphql/
.. |Chat| image:: https://img.shields.io/gitter/room/Stranger6667/hypothesis-graphql.svg
   :target: https://gitter.im/Stranger6667/hypothesis-graphql
   :alt: Gitter
.. |License| image:: https://img.shields.io/pypi/l/hypothesis-graphql.svg
   :target: https://opensource.org/licenses/MIT

