From 97a81120b71237615dbd8f4ee6599ddd777e2cd1 Mon Sep 17 00:00:00 2001
From: Syrus Akbary <me@syrusakbary.com>
Date: Fri, 30 Oct 2015 00:36:31 -0700
Subject: [PATCH] Added mutations in examples

---
 examples/starwars_django/data.py              | 27 ++++---
 examples/starwars_django/schema.py            | 43 +++++++---
 .../starwars_django/tests/test_mutation.py    | 78 +++++++++++++++++++
 examples/starwars_relay/data.py               | 29 +++----
 examples/starwars_relay/schema.py             | 41 +++++++---
 .../starwars_relay/tests/test_mutation.py     | 75 ++++++++++++++++++
 6 files changed, 246 insertions(+), 47 deletions(-)
 create mode 100644 examples/starwars_django/tests/test_mutation.py
 create mode 100644 examples/starwars_relay/tests/test_mutation.py

diff --git a/examples/starwars_django/data.py b/examples/starwars_django/data.py
index bf88b7a9..82e72efa 100644
--- a/examples/starwars_django/data.py
+++ b/examples/starwars_django/data.py
@@ -85,31 +85,30 @@ def initialize():
     executor.save()
 
 
-def createShip(shipName, factionId):
-    nextShip = len(data['Ship'].keys())+1
-    newShip = Ship(
-        id=str(nextShip),
-        name=shipName
+def create_ship(ship_name, faction_id):
+    new_ship = Ship(
+        name=ship_name,
+        faction_id=faction_id
     )
-    newShip.save()
-    return newShip
+    new_ship.save()
+    return new_ship
 
 
-def getShip(_id):
+def get_ship(_id):
     return Ship.objects.get(id=_id)
 
 
-def getShips():
+def get_ships():
     return Ship.objects.all()
 
 
-def getFaction(_id):
+def get_faction(_id):
     return Faction.objects.get(id=_id)
 
 
-def getRebels():
-    return getFaction(1)
+def get_rebels():
+    return get_faction(1)
 
 
-def getEmpire():
-    return getFaction(2)
+def get_empire():
+    return get_faction(2)
diff --git a/examples/starwars_django/schema.py b/examples/starwars_django/schema.py
index c6839a14..2f3f9e38 100644
--- a/examples/starwars_django/schema.py
+++ b/examples/starwars_django/schema.py
@@ -7,11 +7,12 @@ from graphene.contrib.django import (
 from .models import (
     Ship as ShipModel, Faction as FactionModel, Character as CharacterModel)
 from .data import (
-    getFaction,
-    getShip,
-    getShips,
-    getRebels,
-    getEmpire,
+    get_faction,
+    get_ship,
+    get_ships,
+    get_rebels,
+    get_empire,
+    create_ship
 )
 
 schema = graphene.Schema(name='Starwars Django Relay Schema')
@@ -23,7 +24,7 @@ class Ship(DjangoNode):
 
     @classmethod
     def get_node(cls, id):
-        return Ship(getShip(id))
+        return Ship(get_ship(id))
 
 
 @schema.register
@@ -38,7 +39,24 @@ class Faction(DjangoNode):
 
     @classmethod
     def get_node(cls, id):
-        return Faction(getFaction(id))
+        return Faction(get_faction(id))
+
+
+class IntroduceShip(relay.ClientIDMutation):
+    class Input:
+        ship_name = graphene.StringField(required=True)
+        faction_id = graphene.StringField(required=True)
+
+    ship = graphene.Field(Ship)
+    faction = graphene.Field(Faction)
+
+    @classmethod
+    def mutate_and_get_payload(cls, input, info):
+        ship_name = input.get('ship_name')
+        faction_id = input.get('faction_id')
+        ship = create_ship(ship_name, faction_id)
+        faction = get_faction(faction_id)
+        return IntroduceShip(ship=ship, faction=faction)
 
 
 class Query(graphene.ObjectType):
@@ -49,15 +67,20 @@ class Query(graphene.ObjectType):
 
     @resolve_only_args
     def resolve_ships(self):
-        return [Ship(s) for s in getShips()]
+        return [Ship(s) for s in get_ships()]
 
     @resolve_only_args
     def resolve_rebels(self):
-        return Faction(getRebels())
+        return Faction(get_rebels())
 
     @resolve_only_args
     def resolve_empire(self):
-        return Faction(getEmpire())
+        return Faction(get_empire())
+
+
+class Mutation(graphene.ObjectType):
+    introduce_ship = graphene.Field(IntroduceShip)
 
 
 schema.query = Query
+schema.mutation = Mutation
diff --git a/examples/starwars_django/tests/test_mutation.py b/examples/starwars_django/tests/test_mutation.py
new file mode 100644
index 00000000..1eb28e08
--- /dev/null
+++ b/examples/starwars_django/tests/test_mutation.py
@@ -0,0 +1,78 @@
+import pytest
+from ..schema import schema
+from ..data import initialize
+
+pytestmark = pytest.mark.django_db
+
+
+def test_mutations():
+    initialize()
+
+    query = '''
+    mutation MyMutation {
+      introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
+        ship {
+          id
+          name
+        }
+        faction {
+          name
+          ships {
+            edges {
+              node {
+                id
+                name
+              }
+            }
+          }
+        }
+      }
+    }
+    '''
+    expected = {
+        'introduceShip': {
+            'ship': {
+                'id': 'U2hpcDo5',
+                'name': 'Peter'
+            },
+            'faction': {
+                'name': 'Alliance to Restore the Republic',
+                'ships': {
+                    'edges': [{
+                        'node': {
+                            'id': 'U2hpcDox',
+                            'name': 'X-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDoy',
+                            'name': 'Y-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDoz',
+                            'name': 'A-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo0',
+                            'name': 'Millenium Falcon'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo1',
+                            'name': 'Home One'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo5',
+                            'name': 'Peter'
+                        }
+                    }]
+                },
+            }
+        }
+    }
+    result = schema.execute(query)
+    assert not result.errors
+    assert result.data == expected
diff --git a/examples/starwars_relay/data.py b/examples/starwars_relay/data.py
index 2e49854f..eb2b0ca2 100644
--- a/examples/starwars_relay/data.py
+++ b/examples/starwars_relay/data.py
@@ -77,28 +77,29 @@ def setup():
     }
 
 
-def createShip(shipName, factionId):
-    nextShip = len(data['Ship'].keys())+1
-    newShip = Ship(
-        id=str(nextShip),
-        name=shipName
+def create_ship(ship_name, faction_id):
+    from .schema import Ship
+    next_ship = len(data['Ship'].keys()) + 1
+    new_ship = Ship(
+        id=str(next_ship),
+        name=ship_name
     )
-    data['Ship'][newShip.id] = newShip
-    data['Faction'][factionId].ships.append(newShip.id)
-    return newShip
+    data['Ship'][new_ship.id] = new_ship
+    data['Faction'][faction_id].ships.append(new_ship.id)
+    return new_ship
 
 
-def getShip(_id):
+def get_ship(_id):
     return data['Ship'][_id]
 
 
-def getFaction(_id):
+def get_faction(_id):
     return data['Faction'][_id]
 
 
-def getRebels():
-    return getFaction('1')
+def get_rebels():
+    return get_faction('1')
 
 
-def getEmpire():
-    return getFaction('2')
+def get_empire():
+    return get_faction('2')
diff --git a/examples/starwars_relay/schema.py b/examples/starwars_relay/schema.py
index 5e01f48b..9fa19540 100644
--- a/examples/starwars_relay/schema.py
+++ b/examples/starwars_relay/schema.py
@@ -2,10 +2,11 @@ import graphene
 from graphene import resolve_only_args, relay
 
 from .data import (
-    getFaction,
-    getShip,
-    getRebels,
-    getEmpire,
+    get_faction,
+    get_ship,
+    get_rebels,
+    get_empire,
+    create_ship,
 )
 
 schema = graphene.Schema(name='Starwars Relay Schema')
@@ -17,7 +18,7 @@ class Ship(relay.Node):
 
     @classmethod
     def get_node(cls, id):
-        return getShip(id)
+        return get_ship(id)
 
 
 class Faction(relay.Node):
@@ -29,11 +30,28 @@ class Faction(relay.Node):
     @resolve_only_args
     def resolve_ships(self, **args):
         # Transform the instance ship_ids into real instances
-        return [getShip(ship_id) for ship_id in self.ships]
+        return [get_ship(ship_id) for ship_id in self.ships]
 
     @classmethod
     def get_node(cls, id):
-        return getFaction(id)
+        return get_faction(id)
+
+
+class IntroduceShip(relay.ClientIDMutation):
+    class Input:
+        ship_name = graphene.StringField(required=True)
+        faction_id = graphene.StringField(required=True)
+
+    ship = graphene.Field(Ship)
+    faction = graphene.Field(Faction)
+
+    @classmethod
+    def mutate_and_get_payload(cls, input, info):
+        ship_name = input.get('ship_name')
+        faction_id = input.get('faction_id')
+        ship = create_ship(ship_name, faction_id)
+        faction = get_faction(faction_id)
+        return IntroduceShip(ship=ship, faction=faction)
 
 
 class Query(graphene.ObjectType):
@@ -43,11 +61,16 @@ class Query(graphene.ObjectType):
 
     @resolve_only_args
     def resolve_rebels(self):
-        return getRebels()
+        return get_rebels()
 
     @resolve_only_args
     def resolve_empire(self):
-        return getEmpire()
+        return get_empire()
+
+
+class Mutation(graphene.ObjectType):
+    introduce_ship = graphene.Field(IntroduceShip)
 
 
 schema.query = Query
+schema.mutation = Mutation
diff --git a/examples/starwars_relay/tests/test_mutation.py b/examples/starwars_relay/tests/test_mutation.py
new file mode 100644
index 00000000..02baab5c
--- /dev/null
+++ b/examples/starwars_relay/tests/test_mutation.py
@@ -0,0 +1,75 @@
+from ..schema import schema
+from ..data import setup
+
+setup()
+
+
+def test_mutations():
+    query = '''
+    mutation MyMutation {
+      introduceShip(input:{clientMutationId:"abc", shipName: "Peter", factionId: "1"}) {
+        ship {
+          id
+          name
+        }
+        faction {
+          name
+          ships {
+            edges {
+              node {
+                id
+                name
+              }
+            }
+          }
+        }
+      }
+    }
+    '''
+    expected = {
+        'introduceShip': {
+            'ship': {
+                'id': 'U2hpcDo5',
+                'name': 'Peter'
+            },
+            'faction': {
+                'name': 'Alliance to Restore the Republic',
+                'ships': {
+                    'edges': [{
+                        'node': {
+                            'id': 'U2hpcDox',
+                            'name': 'X-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDoy',
+                            'name': 'Y-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDoz',
+                            'name': 'A-Wing'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo0',
+                            'name': 'Millenium Falcon'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo1',
+                            'name': 'Home One'
+                        }
+                    }, {
+                        'node': {
+                            'id': 'U2hpcDo5',
+                            'name': 'Peter'
+                        }
+                    }]
+                },
+            }
+        }
+    }
+    result = schema.execute(query)
+    assert not result.errors
+    assert result.data == expected