def test_many_to_one_extras__add_by_id__adds_by_id(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateUserMutation(DjangoUpdateMutation): class Meta: model = User exclude_fields = ("password",) many_to_one_extras = {"cats": {"add": {"type": "ID"}}} class Mutations(graphene.ObjectType): update_user = UpdateUserMutation.Field() user = UserFactory.create() # Create some enemies cats = CatFactory.create_batch(5, owner=user) other_cats = CatFactory.create_batch(5) self.assertEqual(user.cats.all().count(), 5) schema = Schema(mutation=Mutations) mutation = """ mutation UpdateUser( $id: ID!, $input: UpdateUserInput! ){ updateUser(id: $id, input: $input){ user{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "username": user.username, "firstName": user.first_name, "lastName": user.last_name, "email": user.email, "catsAdd": [cat.id for cat in other_cats], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) user.refresh_from_db() self.assertEqual(user.cats.all().count(), 10)
def test__many_to_one_relation_exists__creates_specified_fields(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class CreateDogMutation(DjangoCreateMutation): class Meta: model = Dog class Mutations(graphene.ObjectType): create_dog = CreateDogMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation CreateDog( $input: CreateDogInput! ){ createDog(input: $input){ dog{ id enemies{ edges{ node{ id } } } } } } """ result = schema.execute( mutation, variables={ "input": { "name": "Sparky", "breed": "HUSKY", "tag": "1234", "owner": to_global_id("UserNode", user.id), "enemies": [to_global_id("CatNode", cat.id)], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) data = Dict(result.data) self.assertIsNone(result.errors) self.assertEqual(to_global_id("CatNode", cat.id), data.createDog.dog.enemies.edges[0].node.id) new_dog = Dog.objects.get(pk=disambiguate_id(data.createDog.dog.id)) # Load from database cat.refresh_from_db() self.assertEqual(cat, new_dog.enemies.first())
def test_many_to_many_extras__add_extra_by_input__adds_by_input(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class CreateCatMutation(DjangoCreateMutation): class Meta: model = Cat class UpdateDogMutation(DjangoUpdateMutation): class Meta: model = Dog many_to_many_extras = {"enemies": {"exact": {"type": "CreateCatInput"}}} class Mutations(graphene.ObjectType): create_cat = CreateCatMutation.Field() update_dog = UpdateDogMutation.Field() dog = DogFactory.create() user = UserFactory.create() # Create some enemies cats = CatFactory.create_batch(5) self.assertEqual(dog.enemies.all().count(), 0) schema = Schema(mutation=Mutations) mutation = """ mutation UpdateDog( $id: ID!, $input: UpdateDogInput! ){ updateDog(id: $id, input: $input){ dog{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("DogNode", dog.id), "input": { "name": "Sparky", "tag": "tag", "breed": "HUSKY", "owner": to_global_id("UserNode", user.id), "enemies": [ {"name": cat.name, "owner": cat.owner.id} for cat in cats ], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) dog.refresh_from_db() self.assertEqual(dog.enemies.all().count(), 5)
def test_check_permissions__override__uses_new_check_permissions_to_grant_access( self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat # This will be overridden permissions = ("tests.change_cat", ) @classmethod def check_permissions(cls, root, info, id, input) -> None: if input["name"] == "Name 2": raise ValueError("Cannot be Name 2") return None class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute(mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "Name 2", "owner": to_global_id("UserNode", user.id) } }, context=Dict(user=user)) self.assertEqual(len(result.errors), 1) result = schema.execute(mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "Name 3", "owner": to_global_id("UserNode", user.id) } }, context=Dict(user=user)) self.assertIsNone(result.errors)
def test_get_permissions__list_with_permissions__requires_returned_permissions( self, ): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat @classmethod def get_permissions(cls, root, info, *args, **kwargs): return ["tests.change_cat"] class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserFactory.create() user_with_permissions = UserWithPermissionsFactory.create( permissions=["tests.change_cat"]) cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Name", "owner": to_global_id("UserNode", user.id) }, }, context=Dict(user=user), ) self.assertEqual(len(result.errors), 1) result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Name", "owner": to_global_id("UserNode", user.id) }, }, context=Dict(user=user_with_permissions), ) self.assertIsNone(result.errors)
def test_validate__validate_field_raises__returns_error(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat @classmethod def validate_name(cls, root, info, value, input, id, obj): owner = User.objects.get(pk=disambiguate_id(input["owner"])) if value == owner.get_full_name(): raise ValueError("Cat must have different name than owner") class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserFactory.create(first_name="John", last_name="Doe") cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "John Doe", "owner": to_global_id("UserNode", user.id), }, }, context=Dict(user=user), ) self.assertEqual(len(result.errors), 1) result = schema.execute( mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "Kitty", "owner": to_global_id("UserNode", user.id) }, }, context=Dict(user=user), ) self.assertIsNone(result.errors)
def test_many_to_many_extras__calling_exact_with_empty_list__resets_relation(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class PatchDogMutation(DjangoPatchMutation): class Meta: model = Dog many_to_many_extras = {"enemies": {"exact": {"type": "ID"}}} class Mutations(graphene.ObjectType): patch_dog = PatchDogMutation.Field() dog = DogFactory.create() user = UserFactory.create() # Create some enemies cats = CatFactory.create_batch(5) dog.enemies.set(cats) self.assertEqual(dog.enemies.all().count(), 5) schema = Schema(mutation=Mutations) mutation = """ mutation PatchDog( $id: ID!, $input: PatchDogInput! ){ patchDog(id: $id, input: $input){ dog{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("DogNode", dog.id), "input": { "name": "Sparky", "tag": "tag", "breed": "HUSKY", "owner": to_global_id("UserNode", user.id), "enemies": [], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) dog.refresh_from_db() self.assertEqual(dog.enemies.all().count(), 0)
def test_many_to_many_extras__calling_exact_with_empty_list__resets_relation( self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat many_to_many_extras = {"enemies": {"exact": {"type": "ID"}}} class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() cat = CatFactory.create() user = UserFactory.create() # Create some enemies dog = DogFactory.create_batch(5) cat.enemies.set(dog) self.assertEqual(cat.enemies.all().count(), 5) schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Garfield", "owner": to_global_id("UserNode", user.id), "enemies": [], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) cat.refresh_from_db() self.assertEqual(cat.enemies.all().count(), 0)
def test_many_to_many_extras__add_extra_by_id__adds_by_id(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class PatchCatMutation(DjangoPatchMutation): class Meta: model = Cat many_to_many_extras = {"enemies": {"add": {"type": "ID"}}} class Mutations(graphene.ObjectType): patch_cat = PatchCatMutation.Field() cat = CatFactory.create() user = UserFactory.create() # Create some enemies dog = DogFactory.create_batch(5) self.assertEqual(cat.enemies.all().count(), 0) schema = Schema(mutation=Mutations) mutation = """ mutation PatchCat( $id: ID!, $input: PatchCatInput! ){ patchCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Garfield", "owner": to_global_id("UserNode", user.id), "enemiesAdd": [dog.id for dog in dog], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) cat.refresh_from_db() self.assertEqual(cat.enemies.all().count(), 5)
def test_many_to_one_extras__set_exact_by_id__sets_by_id(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class CreateUserMutation(DjangoCreateMutation): class Meta: model = User exclude_fields = ("password", ) many_to_one_extras = {"cats": {"exact": {"type": "ID"}}} class Mutations(graphene.ObjectType): create_user = CreateUserMutation.Field() user = UserFactory.build() other_cats = CatFactory.create_batch(5) schema = Schema(mutation=Mutations) mutation = """ mutation CreateUser( $input: CreateUserInput! ){ createUser(input: $input){ user{ id } } } """ result = schema.execute( mutation, variables={ "input": { "username": user.username, "firstName": user.first_name, "lastName": user.last_name, "email": user.email, "cats": [cat.id for cat in other_cats], } }, context=Dict(user=user), ) self.assertIsNone(result.errors) data = Dict(result.data) user = User.objects.get(pk=disambiguate_id(data.createUser.user.id)) self.assertEqual(user.cats.all().count(), 5)
def test_default_setup__adding_resource_by_id__adds_resource(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() cat = CatFactory.create() user = UserFactory.create() dog = DogFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Garfield", "owner": to_global_id("UserNode", user.id), "enemies": [to_global_id("DogNode", dog.id)], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) cat.refresh_from_db() self.assertEqual(cat.enemies.all().count(), 1)
def test_get_permissions__empty_list__overrides_and_grants_access(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat # This will be overridden permissions = ("tests.change_cat", ) @classmethod def get_permissions(cls, root, info, *args, **kwargs): return [] class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute(mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "Name", "owner": to_global_id("UserNode", user.id) } }, context=Dict(user=user)) self.assertIsNone(result.errors)
def test_validate__validate_field_does_nothing__passes(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat @classmethod def validate_name(cls, root, info, value, input, id, obj): pass class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("UserNode", user.id), "input": { "name": "Name", "owner": to_global_id("UserNode", user.id) }, }, context=Dict(user=user), ) self.assertIsNone(result.errors)
def test_mutate__object_exists__deletes_object(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class DeleteCatMutation(DjangoDeleteMutation): class Meta: model = Cat permissions = ("tests.delete_cat", ) class Mutations(graphene.ObjectType): delete_cat = DeleteCatMutation.Field() user = UserWithPermissionsFactory.create( permissions=["tests.delete_cat"]) cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation DeleteCat( $id: ID! ){ deleteCat(id: $id){ found deletedId deletedRawId deletedInputId } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), }, context=Dict(user=user), ) self.assertIsNone(result.errors) data = Dict(result.data) self.assertIsNone(Cat.objects.filter(id=cat.id).first()) self.assertTrue(data.deleteCat.found) self.assertEqual(cat.id, int(disambiguate_id(data.deleteCat.deletedId)))
def test_permissions__user_has_permission__does_not_return_error(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class UpdateCatMutation(DjangoUpdateMutation): class Meta: model = Cat permissions = ("tests.change_cat", ) class Mutations(graphene.ObjectType): update_cat = UpdateCatMutation.Field() user = UserWithPermissionsFactory.create( permissions=["tests.change_cat"]) cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation UpdateCat( $id: ID!, $input: UpdateCatInput! ){ updateCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Name", "owner": to_global_id("UserNode", user.id) }, }, context=Dict(user=user), ) self.assertIsNone(result.errors)
def test_mutate__only_supply_some_fields__changes_relevant_fields(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class PatchCatMutation(DjangoPatchMutation): class Meta: model = Cat permissions = ("tests.change_cat",) class Mutations(graphene.ObjectType): patch_cat = PatchCatMutation.Field() user = UserWithPermissionsFactory.create(permissions=["tests.change_cat"]) cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation PatchCat( $id: ID!, $input: PatchCatInput! ){ patchCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), # Notably, owner is omitted "input": {"name": "New name"}, }, context=Dict(user=user), ) self.assertIsNone(result.errors) cat.refresh_from_db() self.assertEqual("New name", cat.name)
def test_muate__user_misses_permission__fails(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class DeleteCatMutation(DjangoDeleteMutation): class Meta: model = Cat permissions = ("tests.delete_cat", ) class Mutations(graphene.ObjectType): delete_cat = DeleteCatMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation DeleteCat( $id: ID! ){ deleteCat(id: $id){ found deletedId } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), # Notably, owner is omitted "input": { "name": "New name" }, }, context=Dict(user=user), ) self.assertIsNotNone(result.errors) self.assertIn("Not permitted", str(result.errors))
def test_get_permissions__conditional_list__requires_returned_permissions(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class PatchCatMutation(DjangoPatchMutation): class Meta: model = Cat @classmethod def get_permissions(cls, root, info, input, id, *args, **kwargs): owner_id = int(disambiguate_id(input["owner"])) if info.context.user.id == owner_id: return [] return ["tests.change_cat"] class Mutations(graphene.ObjectType): patch_cat = PatchCatMutation.Field() user = UserFactory.create() new_cat_owner = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation PatchCat( $id: ID!, $input: PatchCatInput! ){ patchCat(id: $id, input: $input){ cat{ id } } } """ result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Name", "owner": to_global_id("UserNode", new_cat_owner.id), }, }, context=Dict(user=user), ) self.assertEqual(len(result.errors), 1) result = schema.execute( mutation, variables={ "id": to_global_id("CatNode", cat.id), "input": { "name": "Name", "owner": to_global_id("UserNode", new_cat_owner.id), }, }, context=Dict(user=new_cat_owner), ) self.assertIsNone(result.errors)
def test__many_to_one_relation_exists__creates_specified_fields(self): # This registers the UserNode type # noinspection PyUnresolvedReferences from .schema import UserNode class CreateUserMutation(DjangoCreateMutation): class Meta: model = User exclude_fields = ("password", ) class Mutations(graphene.ObjectType): create_user = CreateUserMutation.Field() user = UserFactory.create() cat = CatFactory.create() schema = Schema(mutation=Mutations) mutation = """ mutation CreateUser( $input: CreateUserInput! ){ createUser(input: $input){ user{ id cats{ edges{ node{ id } } } } } } """ result = schema.execute( mutation, variables={ "input": { "username": "******", "email": "*****@*****.**", "firstName": "John", "lastName": "Doe", "cats": [to_global_id("CatNode", cat.id)], }, }, context=Dict(user=user), ) self.assertIsNone(result.errors) data = Dict(result.data) self.assertIsNone(result.errors) self.assertEqual(to_global_id("CatNode", cat.id), data.createUser.user.cats.edges[0].node.id) new_user = User.objects.get( pk=disambiguate_id(data.createUser.user.id)) # Load from database cat.refresh_from_db() self.assertEqual(cat, new_user.cats.first())