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)
Esempio n. 7
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 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)
Esempio n. 9
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)
Esempio n. 16
0
    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)
Esempio n. 17
0
    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))
Esempio n. 18
0
    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())