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=[])