def test_missing_query():
    schema = """type Author {
      name: String
    }"""
    with pytest.raises(InvalidArgument,
                       match="Query type is not defined in the schema"):
        queries(schema)
def test_invalid_custom_scalar_strategy(custom_scalars, expected):
    # When the user passes `custom_scalars`
    # And it has a wrong type
    # Then there should be an error
    schema = CUSTOM_SCALAR_TEMPLATE.format(
        query="getByDate(created: Date!): Int")
    with pytest.raises(InvalidArgument, match=expected):
        queries(schema, custom_scalars=custom_scalars)
def test_query_from_graphql_schema(data, schema, validate_operation):
    query = """type Query {
      getBooksByAuthor(name: String): [Book]
    }"""
    schema = cached_build_schema(schema + query)
    query = data.draw(queries(schema))
    validate_operation(schema, query)
def test_custom_scalar_nested_argument(validate_operation, other_type):
    # When a custom scalar type is defined
    # And is used as a field inside an input type
    # And is nullable
    schema = f"""
scalar Date

input QueryInput {{
  created: Date
  id: {other_type}
}}

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

    # Then it could be skipped
    strategy = queries(schema)

    @given(strategy)
    def test(query):
        validate_operation(schema, query)

    test()
    # And "id" is still possible to generate
    assert find(
        strategy,
        lambda x: "id" in x).strip() == '{\n  getByDate(created: {id: ""})\n}'
def test_minimal_queries(query, schema, minimum):
    schema = schema + f"type Query {{ {query} }}"
    strategy = queries(schema)
    minimal_query = f"""{{
  getAuthors{minimum} {{
    name
  }}
}}"""
    assert find(strategy, lambda x: True).strip() == minimal_query
def test_custom_scalar_non_argument(data, validate_operation):
    # When a custom scalar type is defined
    # And is used in a non-argument position

    schema = CUSTOM_SCALAR_TEMPLATE.format(query="getObjects: [Object]")
    query = data.draw(queries(schema))
    validate_operation(schema, query)
    # Then queries should be generated
    assert "created" in query
def test_custom_printer(simple_schema):
    def printer(node):
        return str(node)

    @given(queries(simple_schema, print_ast=printer))
    @settings(max_examples=1)
    def test(query):
        assert query == "DocumentNode"

    test()
def test_custom_scalar_argument(data, input_type):
    # When a custom scalar type is defined
    # And is used in an argument position
    # And is not nullable

    schema = CUSTOM_SCALAR_TEMPLATE.format(
        query=f"getByDate(created: {input_type}!): Object")

    with pytest.raises(TypeError, match="Scalar 'Date' is not supported"):
        data.draw(queries(schema))
def test_custom_scalar_registered(data, validate_operation):
    # When the user registered a custom strategy for a scalar
    # Then it should generate valid queries
    schema = CUSTOM_SCALAR_TEMPLATE.format(
        query="getByDate(created: Date!): Int")
    expected = "EXAMPLE"

    query = data.draw(
        queries(schema,
                custom_scalars={"Date": st.just(expected).map(nodes.String)}))
    validate_operation(schema, query)
    assert f'getByDate(created: "{expected}")' in query
def test_no_surrogates(data, validate_operation):
    # Unicode surrogates are not supported by GraphQL spec
    schema = """
    type Query {
        hello(user: String!): String
    }
    """
    query = data.draw(queries(schema))
    document = validate_operation(schema, query)
    argument_node = document.definitions[0].selection_set.selections[
        0].arguments[0]
    assume(argument_node.name.value == "user")
    value = argument_node.value.value
    value.encode("utf8")
def test_empty_interface(data, validate_operation):
    # When the schema contains an empty interface (which is invalid)
    schema = """
interface Empty

type First implements Empty {
  int: Int!
}
type Second implements Empty {
  float: Float!
}

type Query {
  getByEmpty: Empty
}"""
    # Then query generation should not fail
    query = data.draw(queries(schema))
    # And then schema validation should fail instead
    with pytest.raises(TypeError,
                       match="Type Empty must define one or more fields"):
        validate_operation(schema, query)
def test_custom_scalar_argument_nullable(validate_operation):
    # When a custom scalar type is defined
    # And is used in an argument position
    # And is nullable
    # And there are no other arguments

    num_of_queries = 0

    schema = CUSTOM_SCALAR_TEMPLATE.format(
        query="getByDate(created: Date): Object")

    @given(query=queries(schema))
    def test(query):
        nonlocal num_of_queries

        num_of_queries += 1
        validate_operation(schema, query)
        assert "getByDate {" in query or "getByDate(created: null)" in query

    test()
    # Then only two queries should be generated - no fields, and `created: null`
    assert num_of_queries == 2
def test_default_values(validate_operation, type_name, default, format_kwargs):
    # When the input schema contains nodes with default values
    schema = """
scalar Date

enum Color {{
  RED
  GREEN
  BLUE
}}

input InputData {{
  inner: {inner_type_name} = {inner_default},
}}

type Query {{
  getValue(arg: {outer_type_name} = {outer_default}): Int!
}}
    """.format(**format_kwargs({
        "type_name": type_name,
        "default": default
    }))
    strategy = queries(
        schema,
        custom_scalars={"Date": st.just("2022-04-26").map(nodes.String)})
    # Then these default values should be used in generated queries

    all_valid = True

    def validate_and_find(query):
        nonlocal all_valid
        try:
            validate_operation(schema, query)
        except AssertionError:
            all_valid = False
        return default in query

    find(strategy, validate_and_find)
    assert all_valid
def test_arguments(data, schema, arguments, node_names, notnull,
                   validate_operation):
    if notnull:
        arguments += "!"
    query_type = f"""type Query {{
      getModel({arguments}): Model
    }}"""

    schema = schema + query_type
    query = data.draw(queries(schema))
    validate_operation(schema, query)
    for node_name in node_names:
        assert node_name not in query
    if notnull:
        assert "getModel(" in query
    parsed = graphql.parse(query)
    selection = parsed.definitions[0].selection_set.selections[0]
    if notnull:
        # there should be one argument if it is not null
        assert len(selection.arguments) == 1
    # at least one Model field is selected
    assert len(selection.selection_set.selections) > 0
def test_custom_scalar_field(data, validate_operation):
    # When a custom scalar type is defined
    # And is used in a field position
    # And is not nullable
    schema = """
    scalar Date

    type Object {
      created: Date!
    }
    type Query {
      getObject: Object
    }
    """
    # Then query should be generated without errors
    query = data.draw(queries(schema))
    validate_operation(schema, query)
    assert (query.strip() == """{
  getObject {
    created
  }
}""")
def test_query(data, schema, query_type, validate_operation):
    schema = schema + query_type
    query = data.draw(queries(schema))
    validate_operation(schema, query)
def test_aliases(data, validate_operation, schema):
    # See GH-49, GH-57
    # When Query contain types on the same level that have fields with the same name but with different types
    query = data.draw(queries(schema))
    # Then no invalid queries should be generated
    validate_operation(schema, query)
def test_query_subset(data, simple_schema, validate_operation):
    query = data.draw(queries(simple_schema, fields=["getBooks"]))
    validate_operation(simple_schema, query)
    assert "getAuthors" not in query
def test_wrong_fields(simple_schema):
    with pytest.raises(ValueError, match="Unknown fields: wrong"):
        queries(simple_schema, fields=["wrong"])
def test_empty_fields(simple_schema):
    with pytest.raises(ValueError,
                       match="If you pass `fields`, it should not be empty"):
        queries(simple_schema, fields=[])