Skip to content

Commit f5e6d32

Browse files
committed
Regression tests
- test to check that sort argument is generated automatically for a SQLALchemyConnectionField that uses a SQLALchemyInterface.connection - test for relationship filtering a model using a relationship to a table with joined table inheritance
1 parent 902fa93 commit f5e6d32

File tree

3 files changed

+213
-2
lines changed

3 files changed

+213
-2
lines changed

graphene_sqlalchemy/tests/models.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,46 @@ class Employee(Person):
402402
}
403403

404404

405+
class Owner(Base):
406+
id = Column(Integer(), primary_key=True)
407+
name = Column(String())
408+
409+
accounts = relationship(lambda: Account, back_populates="owner", lazy="selectin")
410+
411+
__tablename__ = "owner"
412+
413+
414+
class Account(Base):
415+
id = Column(Integer(), primary_key=True)
416+
type = Column(String())
417+
418+
owner_id = Column(Integer(), ForeignKey(Owner.__table__.c.id))
419+
owner = relationship(Owner, back_populates="accounts")
420+
421+
balance = Column(Integer())
422+
423+
__tablename__ = "account"
424+
__mapper_args__ = {
425+
"polymorphic_on": type,
426+
}
427+
428+
429+
class CurrentAccount(Account):
430+
overdraft = Column(Integer())
431+
432+
__mapper_args__ = {
433+
"polymorphic_identity": "current",
434+
}
435+
436+
437+
class SavingsAccount(Account):
438+
interest_rate = Column(Integer())
439+
440+
__mapper_args__ = {
441+
"polymorphic_identity": "savings",
442+
}
443+
444+
405445
############################################
406446
# Custom Test Models
407447
############################################

graphene_sqlalchemy/tests/test_fields.py

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
from graphene.relay import Connection, Node
66

77
from ..fields import SQLAlchemyConnectionField, UnsortedSQLAlchemyConnectionField
8-
from ..types import SQLAlchemyObjectType
8+
from ..types import SQLAlchemyInterface, SQLAlchemyObjectType
99
from .models import Editor as EditorModel
10+
from .models import Employee as EmployeeModel
11+
from .models import Person as PersonModel
1012
from .models import Pet as PetModel
1113

1214

@@ -21,6 +23,18 @@ class Meta:
2123
model = EditorModel
2224

2325

26+
class Person(SQLAlchemyInterface):
27+
class Meta:
28+
model = PersonModel
29+
use_connection = True
30+
31+
32+
class Employee(SQLAlchemyObjectType):
33+
class Meta:
34+
model = EmployeeModel
35+
interfaces = (Person, Node)
36+
37+
2438
##
2539
# SQLAlchemyConnectionField
2640
##
@@ -91,3 +105,10 @@ def test_custom_sort():
91105
def test_sort_init_raises():
92106
with pytest.raises(TypeError, match="Cannot create sort"):
93107
SQLAlchemyConnectionField(Connection)
108+
109+
110+
def test_interface_required_sqlalachemy_connection():
111+
field = SQLAlchemyConnectionField(Person.connection, required=True)
112+
assert isinstance(field.type, NonNull)
113+
assert issubclass(field.type.of_type, Connection)
114+
assert field.type.of_type._meta.node is Person

graphene_sqlalchemy/tests/test_filters.py

Lines changed: 151 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,19 @@
66

77
from ..fields import SQLAlchemyConnectionField
88
from ..filters import FloatFilter
9-
from ..types import ORMField, SQLAlchemyObjectType
9+
from ..types import ORMField, SQLAlchemyInterface, SQLAlchemyObjectType
1010
from .models import (
11+
Account,
1112
Article,
13+
CurrentAccount,
1214
Editor,
1315
HairKind,
1416
Image,
17+
Owner,
1518
Pet,
1619
Reader,
1720
Reporter,
21+
SavingsAccount,
1822
ShoppingCart,
1923
ShoppingCartItem,
2024
Tag,
@@ -1199,3 +1203,149 @@ async def test_additional_filters(session):
11991203
schema = graphene.Schema(query=Query)
12001204
result = await schema.execute_async(query, context_value={"session": session})
12011205
assert_and_raise_result(result, expected)
1206+
1207+
1208+
# Test relationship filter for interface fields
1209+
async def add_relationship_interface_test_data(session):
1210+
owner1 = Owner(name="John Doe")
1211+
owner2 = Owner(name="Jane Doe")
1212+
session.add_all([owner1, owner2])
1213+
1214+
o1_account1 = CurrentAccount(owner=owner1, balance=1000, overdraft=100)
1215+
o1_account2 = CurrentAccount(owner=owner1, balance=2000, overdraft=50)
1216+
o1_account3 = SavingsAccount(owner=owner1, balance=300, interest_rate=3)
1217+
1218+
o2_account1 = CurrentAccount(owner=owner2, balance=1000, overdraft=100)
1219+
o2_account2 = SavingsAccount(owner=owner2, balance=300, interest_rate=3)
1220+
session.add_all([o1_account1, o1_account2, o1_account3, o2_account1, o2_account2])
1221+
1222+
await eventually_await_session(session, "commit")
1223+
1224+
1225+
def create_relationship_interface_schema(session):
1226+
class OwnerType(SQLAlchemyObjectType):
1227+
class Meta:
1228+
model = Owner
1229+
interfaces = (relay.Node,)
1230+
1231+
class AccountType(SQLAlchemyInterface):
1232+
class Meta:
1233+
model = Account
1234+
use_connection = True
1235+
1236+
class CurrentAccountType(SQLAlchemyObjectType):
1237+
class Meta:
1238+
model = CurrentAccount
1239+
interfaces = (
1240+
AccountType,
1241+
relay.Node,
1242+
)
1243+
1244+
class SavingsAccountType(SQLAlchemyObjectType):
1245+
class Meta:
1246+
model = SavingsAccount
1247+
interfaces = (
1248+
AccountType,
1249+
relay.Node,
1250+
)
1251+
1252+
class Query(graphene.ObjectType):
1253+
node = relay.Node.Field()
1254+
owners = SQLAlchemyConnectionField(OwnerType.connection)
1255+
accounts = SQLAlchemyConnectionField(AccountType.connection)
1256+
1257+
return (Query, [CurrentAccountType, SavingsAccountType])
1258+
1259+
1260+
@pytest.mark.asyncio
1261+
async def test_filter_relationship_interface(session):
1262+
await add_relationship_interface_test_data(session)
1263+
1264+
(Query, types) = create_relationship_interface_schema(session)
1265+
1266+
query = """
1267+
query {
1268+
owners(filter: { accounts: { contains: [{balance: {gte: 2000}}]}}) {
1269+
edges {
1270+
node {
1271+
name
1272+
accounts {
1273+
edges {
1274+
node {
1275+
__typename
1276+
balance
1277+
}
1278+
}
1279+
}
1280+
}
1281+
}
1282+
}
1283+
}
1284+
"""
1285+
expected = {
1286+
"owners": {
1287+
"edges": [
1288+
{
1289+
"node": {
1290+
"name": "John Doe",
1291+
"accounts": {
1292+
"edges": [
1293+
{
1294+
"node": {
1295+
"__typename": "CurrentAccountType",
1296+
"balance": 1000,
1297+
},
1298+
},
1299+
{
1300+
"node": {
1301+
"__typename": "CurrentAccountType",
1302+
"balance": 2000,
1303+
},
1304+
},
1305+
{
1306+
"node": {
1307+
"__typename": "SavingsAccountType",
1308+
"balance": 300,
1309+
},
1310+
},
1311+
],
1312+
},
1313+
},
1314+
},
1315+
],
1316+
},
1317+
}
1318+
schema = graphene.Schema(query=Query, types=types)
1319+
result = await schema.execute_async(query, context_value={"session": session})
1320+
assert_and_raise_result(result, expected)
1321+
1322+
query = """
1323+
query {
1324+
owners(filter: { accounts: { contains: [{balance: {gte: 1000}}]}}) {
1325+
edges {
1326+
node {
1327+
name
1328+
}
1329+
}
1330+
}
1331+
}
1332+
"""
1333+
expected = {
1334+
"owners": {
1335+
"edges": [
1336+
{
1337+
"node": {
1338+
"name": "John Doe",
1339+
},
1340+
},
1341+
{
1342+
"node": {
1343+
"name": "Jane Doe",
1344+
},
1345+
},
1346+
]
1347+
},
1348+
}
1349+
1350+
result = await schema.execute_async(query, context_value={"session": session})
1351+
assert_and_raise_result(result, expected)

0 commit comments

Comments
 (0)