def test_clean_text_lines_removes_normalised_text_lines(): text_lines = [ "Flights booked. Maybe we can meet up and cook all together?", "Oh my! At least it went a hip!!! 😬", "Happy Anniversary to you Jim." ] cleaned_lines = clean_text_lines(text_lines) assert_that( cleaned_lines, contains_exactly( contains_exactly( "flights", "booked", "maybe", "we", "can", "meet", "up", "and", "cook", "all", "together", ), contains_exactly("oh", "my", "at", "least", "it", "went", "a", "hip", "😬"), contains_exactly("happy", "anniversary", "to", "you", "jim")))
def test_edge_cursor_can_be_used_as_after_argument_to_get_next_page( builder, graphql): with builder: builder.add_molecule(chembl_id="CHEMBL42") builder.add_molecule(chembl_id="CHEMBL43") builder.add_molecule(chembl_id="CHEMBL44") query = """ query ($after: String) { moleculesConnection(first: 2, after: $after) { edges { cursor node { chemblId } } } } """ response = graphql(query, variables={"after": None}) assert_that( response["moleculesConnection"], is_mapping({ "edges": contains_exactly( is_mapping({ "cursor": anything, "node": { "chemblId": "CHEMBL42" } }), is_mapping({ "cursor": anything, "node": { "chemblId": "CHEMBL43" } }), ), })) response = graphql( query, variables={ "after": response["moleculesConnection"]["edges"][-1]["cursor"] }) assert_that( response["moleculesConnection"], is_mapping({ "edges": contains_exactly( is_mapping({ "cursor": anything, "node": { "chemblId": "CHEMBL44" } }), ), }))
def test_can_get_synonyms_of_molecule(builder, graphql): with builder: molecule_1 = builder.add_molecule(chembl_id="CHEMBL1") molecule_2 = builder.add_molecule(chembl_id="CHEMBL2") builder.add_molecule(chembl_id="CHEMBL3") builder.add_molecule_synonym( molecule=molecule_1, name="<synonym 1>", ) builder.add_molecule_synonym( molecule=molecule_2, name="<synonym 2a>", ) builder.add_molecule_synonym( molecule=molecule_2, name="<synonym 2b>", ) query = """ query { molecules { chemblId synonyms { name } } } """ response = graphql(query) assert_that( response["molecules"], contains_exactly( is_mapping({ "chemblId": "CHEMBL1", "synonyms": contains_exactly({"name": "<synonym 1>"}, ), }), is_mapping({ "chemblId": "CHEMBL2", "synonyms": contains_exactly( {"name": "<synonym 2a>"}, {"name": "<synonym 2b>"}, ), }), is_mapping({ "chemblId": "CHEMBL3", "synonyms": contains_exactly(), }), ))
def test_when_there_are_fewer_molecules_than_requested_then_all_molecules_are_fetched( builder, graphql): with builder: builder.add_molecule(chembl_id="CHEMBL42") query = """ query { moleculesConnection(first: 2) { edges { node { chemblId } } pageInfo { hasNextPage } } } """ response = graphql(query) assert_that( response["moleculesConnection"], is_mapping({ "edges": contains_exactly(is_mapping({"node": { "chemblId": "CHEMBL42" }}), ), "pageInfo": is_mapping({"hasNextPage": False}), }))
def test_when_there_are_no_molecules_then_connection_is_empty(graphql): query = """ query { moleculesConnection(first: 2) { edges { node { chemblId } } pageInfo { endCursor hasNextPage } } } """ response = graphql(query) assert_that( response["moleculesConnection"], is_mapping({ "edges": contains_exactly(), "pageInfo": is_mapping({ "endCursor": None, "hasNextPage": False }), }))
def test_when_resolution_raises_graph_error_then_result_is_invalid(): Root = g.ObjectType("Root", fields=( g.field("value", g.String), )) root_resolver = g.root_object_resolver(Root) @root_resolver.field(Root.fields.value) def root_resolve_value(graph, query, args): raise g.GraphError("BAD") graph_definition = g.define_graph(resolvers=(root_resolver, )) graph = graph_definition.create_graph({}) query = """ query { value } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that(result, is_invalid(errors=contains_exactly( all_of( is_instance(GraphQLError), has_str("BAD"), ), )))
def mismatches_when_duplicate_is_missing(): matcher = contains_exactly(equal_to("apple"), equal_to("apple")) assert_equal( unmatched("was missing element:\n * 'apple'\nThese elements were in the iterable, but did not match the missing element:\n * 'apple': already matched"), matcher.match(["apple"]) )
def mismatches_when_contains_extra_item(): matcher = contains_exactly(equal_to("apple")) assert_equal( unmatched("had extra elements:\n * 'coconut'"), matcher.match(["coconut", "apple"]) )
def mismatches_when_item_is_expected_but_iterable_is_empty(): matcher = contains_exactly(equal_to("apple")) assert_equal( unmatched("iterable was empty"), matcher.match([]) )
def when_empty_iterable_is_expected_then_empty_iterable_matches(): matcher = contains_exactly() assert_equal( matched(), matcher.match([]) )
def mismatches_when_item_is_missing(): matcher = contains_exactly(equal_to("apple"), equal_to("banana"), equal_to("coconut")) assert_equal( unmatched("was missing element:\n * 'banana'\nThese elements were in the iterable, but did not match the missing element:\n * 'coconut': was 'coconut'\n * 'apple': already matched"), matcher.match(["coconut", "apple"]) )
def mismatches_when_actual_is_not_iterable(): matcher = contains_exactly() assert_equal( unmatched("was not iterable\nwas 0"), matcher.match(0) )
def elements_are_coerced_to_matchers(): matcher = contains_exactly("apple", "banana") assert_equal( "iterable containing these 2 elements in any order:\n * 'apple'\n * 'banana'", matcher.describe() )
def test_when_there_are_no_edges_then_connection_is_empty(): graph = create_graph({}) result = graph.resolve( Query( g.key( "books", Query.fields.books_connection( Query.fields.books_connection.params.first(2), g.key( "edges", BooksConnection.fields.edges( g.key( "node", BookEdge.fields.node( g.key("title", Book.fields.title()), )), )), g.key( "page_info", BooksConnection.fields.page_info( g.key("end_cursor", PageInfo.fields.end_cursor()), g.key("has_next_page", PageInfo.fields.has_next_page()), )), )), )) assert_that( result.books, has_attrs( edges=contains_exactly(), page_info=has_attrs(end_cursor=None, has_next_page=False), ))
def test_can_get_scalar_fields_of_molecule(builder, graphql): with builder: builder.add_molecule( chembl_id="CHEMBL1", pref_name="<pref name 1>", ) builder.add_molecule( chembl_id="CHEMBL2", pref_name="<pref name 2>", ) query = """ query { molecules { chemblId prefName } } """ response = graphql(query) assert_that( response["molecules"], contains_exactly( { "chemblId": "CHEMBL1", "prefName": "<pref name 1>", }, { "chemblId": "CHEMBL2", "prefName": "<pref name 2>", }, ))
def test_nodes_can_be_fetched_directly(): graph = create_graph({ 42: "Leave it to Psmith", 43: "The Gentleman's Guide to Vice and Virtue", 44: "Catch-22", }) result = graph.resolve( Query( g.key( "books", Query.fields.books_connection( Query.fields.books_connection.params.first(2), g.key( "nodes", BooksConnection.fields.nodes( g.key("title", Book.fields.title()), )), g.key( "page_info", BooksConnection.fields.page_info( g.key("has_next_page", PageInfo.fields.has_next_page()), )), )), )) assert_that( result.books, has_attrs(nodes=contains_exactly( has_attrs(title="Leave it to Psmith"), has_attrs(title="The Gentleman's Guide to Vice and Virtue"), ), ))
def test_when_there_are_fewer_edges_than_requested_then_all_edges_are_fetched( ): graph = create_graph({ 42: "Leave it to Psmith", }) result = graph.resolve( Query( g.key( "books", Query.fields.books_connection( Query.fields.books_connection.params.first(2), g.key( "edges", BooksConnection.fields.edges( g.key( "node", BookEdge.fields.node( g.key("title", Book.fields.title()), )), )), g.key( "page_info", BooksConnection.fields.page_info( g.key("has_next_page", PageInfo.fields.has_next_page()), )), )), )) assert_that( result.books, has_attrs( edges=contains_exactly( has_attrs(node=has_attrs(title="Leave it to Psmith")), ), page_info=has_attrs(has_next_page=False), ))
def mismatches_when_duplicate_is_missing(): matcher = contains_exactly(equal_to("apple"), equal_to("apple")) assert_equal( unmatched( "was missing element:\n * 'apple'\nThese elements were in the iterable, but did not match the missing element:\n * 'apple': already matched" ), matcher.match(["apple"]))
def description_contains_descriptions_of_submatchers(): matcher = contains_exactly(equal_to("apple"), equal_to("banana")) assert_equal( "iterable containing these 2 elements in any order:\n * 'apple'\n * 'banana'", matcher.describe() )
def description_uses_singular_when_there_is_one_submatcher(): matcher = contains_exactly(equal_to("apple")) assert_equal( "iterable containing 1 element:\n * 'apple'", matcher.describe() )
def test_enum_has_no_child_types(self): class Direction(enum.Enum): up = "up" down = "down" DirectionGraphType = schema.EnumType(Direction) assert_that(schema.collect_types((DirectionGraphType, )), contains_exactly(DirectionGraphType))
def test_clean_text_removes_normalises_text(): text = "Oh my! At least it went a hip!!! 😬" table = str.maketrans("", "", string.punctuation) cleaned_text = clean_text(text, table=table) assert_that( cleaned_text, contains_exactly("oh", "my", "at", "least", "it", "went", "a", "hip", "😬"))
def test_extract_drops_lines_containing_left_to_right_mark_character(): text = io.StringIO( dedent("""\ [02/08/2016, 06:44:26] \u200eYou added Gary Barker [17/08/2018, 23:52:10] John Smith: Oh my! At least it went a hip!!! 😬 """)) text_lines = extract_text(text) assert_that(text_lines, contains_exactly("Oh my! At least it went a hip!!! 😬", ))
def test_edge_cursor_can_be_used_as_after_argument_to_get_next_page(): graph = create_graph({ 42: "Leave it to Psmith", 43: "The Gentleman's Guide to Vice and Virtue", 44: "Catch-22", }) def fetch(*, after): return graph.resolve( Query( g.key( "books", Query.fields.books_connection( Query.fields.books_connection.params.first(2), Query.fields.books_connection.params.after(after), g.key( "edges", BooksConnection.fields.edges( g.key("cursor", BookEdge.fields.cursor()), g.key( "node", BookEdge.fields.node( g.key("title", Book.fields.title()), )), )), )), )) result = fetch(after=None) assert_that( result.books, has_attrs(edges=contains_exactly( has_attrs(node=has_attrs(title="Leave it to Psmith")), has_attrs(node=has_attrs( title="The Gentleman's Guide to Vice and Virtue")), ), )) result = fetch(after=result.books.edges[-1].cursor) assert_that( result.books, has_attrs(edges=contains_exactly( has_attrs(node=has_attrs(title="Catch-22")), ), ))
def test_can_recursively_resolve(): Root = g.ObjectType( "Root", fields=lambda: [ g.field("books", type=g.ListType(Book)), ], ) Book = g.ObjectType( "Book", fields=lambda: [ g.field("title", type=g.String), ], ) @g.resolver(Root) def resolve_root(graph, query): return query.create_object(iterables.to_dict( (field_query.key, graph.resolve(field_query.type_query)) for field_query in query.field_queries )) @g.resolver(g.ListType(Book)) def resolve_book(graph, query): books = [ dict(title="Leave it to Psmith"), dict(title="Pericles, Prince of Tyre"), ] return [ query.element_query.create_object(iterables.to_dict( (field_query.key, book[field_query.field.name]) for field_query in query.element_query.field_queries )) for book in books ] resolvers = [resolve_root, resolve_book] query = Root( g.key("books", Root.fields.books( g.key("title", Book.fields.title()), )), ) result = g.create_graph(resolvers).resolve(query) assert_that(result, has_attrs( books=contains_exactly( has_attrs(title="Leave it to Psmith"), has_attrs(title="Pericles, Prince of Tyre"), ), ))
def test_can_get_fields_backed_by_expressions(): Base = sqlalchemy.ext.declarative.declarative_base() class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(BookRow(c_title="Leave it to Psmith")) session.add(BookRow(c_title="Pericles, Prince of Tyre")) session.commit() Book = g.ObjectType( "Book", fields=lambda: [ g.field("title", type=g.String), ], ) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: gsql.expression(BookRow.c_title), }, ) resolvers = [book_resolver] query = gsql.select( g.ListType(Book)(g.key("title", Book.fields.title()), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({ sqlalchemy.orm.Session: session, }) result = graph.resolve(query) assert_that( result, contains_exactly( has_attrs(title="Leave it to Psmith", ), has_attrs(title="Pericles, Prince of Tyre", ), ))
def test_can_pass_arguments_to_expression(): Base = sqlalchemy.ext.declarative.declarative_base() class BookRow(Base): __tablename__ = "book" c_id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True) c_title = sqlalchemy.Column(sqlalchemy.Unicode, nullable=False) engine = sqlalchemy.create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) session = sqlalchemy.orm.Session(engine) session.add(BookRow(c_title="Leave it to Psmith")) session.commit() Book = g.ObjectType( "Book", fields=lambda: [ g.field( "title", type=g.String, params=[ g.param("truncate", g.Int), ]), ], ) book_resolver = gsql.sql_table_resolver( Book, BookRow, fields={ Book.fields.title: lambda args: gsql.expression( sqlalchemy.func.substr(BookRow.c_title, 1, args.truncate)), }, ) resolvers = [book_resolver] query = gsql.select( g.ListType(Book)(g.key( "title", Book.fields.title(Book.fields.title.params.truncate(8))), )) graph_definition = g.define_graph(resolvers) graph = graph_definition.create_graph({sqlalchemy.orm.Session: session}) result = graph.resolve(query) assert_that(result, contains_exactly(has_attrs(title="Leave it", ), ))
def test_extract_text_extracts_text_strings(): text = io.StringIO( dedent("""\ [05/06/2018, 18:54:06] John Smith: Flights booked. Maybe we can meet up and cook all together? [17/08/2018, 23:52:10] John Smith: Oh my! At least it went a hip!!! 😬 [13/01/2019, 22:20:03] Glenn Quagmire: Happy Anniversary to you Jim. """)) text_lines = extract_text(text) assert_that( text_lines, contains_exactly( "Flights booked. Maybe we can meet up and cook all together?", "Oh my! At least it went a hip!!! 😬", "Happy Anniversary to you Jim."))
def test_when_query_is_invalid_then_result_is_invalid(): Root = g.ObjectType("Root", fields=(g.field("value", g.String), )) graph_definition = g.define_graph(resolvers=()) graph = graph_definition.create_graph({}) query = """ query { bad } """ result = graphql.execute(graph=graph, document_text=query, query_type=Root) assert_that( result, is_invalid(errors=contains_exactly( has_attrs(message="Cannot query field 'bad' on type 'Root'."), )))
def test_enum_is_converted_to_non_null_enum_type(): class Season(enum.Enum): winter = "WINTER" spring = "SPRING" summer = "SUMMER" autumn = "AUTUMN" SeasonGraphType = g.EnumType(Season) graphql_type = to_graphql_type(SeasonGraphType) assert_that(graphql_type, is_graphql_non_null(is_graphql_enum_type( name="Season", values=contains_exactly( is_graphql_enum_value(name="WINTER", value="WINTER"), is_graphql_enum_value(name="SPRING", value="SPRING"), is_graphql_enum_value(name="SUMMER", value="SUMMER"), is_graphql_enum_value(name="AUTUMN", value="AUTUMN"), ), )))
def test_object_type_interfaces_are_converted_to_graphql_interfaces(): graph_interface_type = g.InterfaceType("Interface", fields=( g.field("value", type=g.String), )) graph_object_type = g.ObjectType( "Obj", fields=( g.field("value", type=g.String), ), interfaces=(graph_interface_type, ), ) assert_that(to_graphql_type(graph_object_type), is_graphql_non_null( is_graphql_object_type( interfaces=contains_exactly( is_graphql_interface_type(name="Interface"), ), ), ))
def description_is_of_empty_iterable_when_there_are_zero_submatchers(): matcher = contains_exactly() assert_equal("empty iterable", matcher.describe())
def matches_when_all_submatchers_match_one_item_with_no_items_leftover(): matcher = contains_exactly(equal_to("apple"), equal_to("banana")) assert_equal(matched(), matcher.match(["banana", "apple"]))