forked from DGNum/gestioCOF
156 lines
5.3 KiB
Python
156 lines
5.3 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
from allauth.socialaccount.models import SocialAccount
|
||
|
from django.db import IntegrityError, transaction
|
||
|
from django.test import TestCase
|
||
|
|
||
|
from gestioncof.models import CofProfile, User
|
||
|
|
||
|
|
||
|
class UserTests(TestCase):
|
||
|
def test_has_profile(self):
|
||
|
"""
|
||
|
A User always has a related CofProfile and a CofProfile always has a
|
||
|
related User.
|
||
|
"""
|
||
|
u = User.objects.create_user("foo", "", "")
|
||
|
|
||
|
# Creating a User creates a related CofProfile.
|
||
|
self.assertTrue(hasattr(u, "profile"))
|
||
|
|
||
|
# there's no point in having a cofprofile without a user associated.
|
||
|
p = u.profile
|
||
|
|
||
|
u.delete()
|
||
|
|
||
|
with transaction.atomic():
|
||
|
with self.assertRaises(CofProfile.DoesNotExist):
|
||
|
p.refresh_from_db()
|
||
|
|
||
|
# there's no point in having a user without a cofprofile associated.
|
||
|
u = User.objects.create_user("foo", "", "")
|
||
|
|
||
|
u.profile.delete()
|
||
|
|
||
|
with transaction.atomic():
|
||
|
with self.assertRaises(User.DoesNotExist):
|
||
|
u.refresh_from_db()
|
||
|
|
||
|
|
||
|
class CofProfileTests(TestCase):
|
||
|
def setUp(self):
|
||
|
self.u = User.objects.create_user("user", "", "")
|
||
|
self.p = self.u.profile
|
||
|
|
||
|
def test_login_clipper_sync_clipper_connections(self):
|
||
|
"""
|
||
|
The value of `login_clipper` is sync with the identifier of the most
|
||
|
recently used clipper connection.
|
||
|
"""
|
||
|
|
||
|
def socialaccount_transform(o):
|
||
|
"""
|
||
|
Function to compare QuerySet of `SocialAccount`, instead of the
|
||
|
default, `repr`, only depends on the involved user.
|
||
|
"""
|
||
|
return "{provider} {username} {uid}".format(
|
||
|
provider=o.provider, username=o.user.username, uid=o.uid
|
||
|
)
|
||
|
|
||
|
def assertClipperAccountQuerysetEquals(user, *args, **kwargs):
|
||
|
kwargs.setdefault("transform", socialaccount_transform)
|
||
|
qs = SocialAccount.objects.filter(provider="clipper", user=user).order_by(
|
||
|
"last_login"
|
||
|
)
|
||
|
self.assertQuerysetEqual(qs, *args, **kwargs)
|
||
|
|
||
|
# Not saved in the database.
|
||
|
self.assertEqual(CofProfile().login_clipper, "")
|
||
|
|
||
|
# This CofProfile has been created without any value for login_clipper.
|
||
|
u, p = self.u, self.p
|
||
|
self.assertEqual(p.login_clipper, "")
|
||
|
|
||
|
# Filling value for the first time triggers the creation of a clipper
|
||
|
# connection (SocialAccount) for the related user.
|
||
|
p.login_clipper = "theclipper"
|
||
|
p.save()
|
||
|
|
||
|
self.assertEqual(p.login_clipper, "theclipper")
|
||
|
assertClipperAccountQuerysetEquals(u, ["clipper user theclipper"])
|
||
|
|
||
|
# Assigning a new value updates the existing connection.
|
||
|
p.login_clipper = "anotherclipper"
|
||
|
p.save()
|
||
|
|
||
|
self.assertEqual(p.login_clipper, "anotherclipper")
|
||
|
assertClipperAccountQuerysetEquals(u, ["clipper user anotherclipper"])
|
||
|
|
||
|
# Creating a clipper connection, using SocialAccount, sets the used
|
||
|
# identifier as value.
|
||
|
conn = SocialAccount.objects.create(provider="clipper", user=u, uid="clip")
|
||
|
|
||
|
self.assertEqual(p.login_clipper, "clip")
|
||
|
assertClipperAccountQuerysetEquals(
|
||
|
u, ["clipper user anotherclipper", "clipper user clip"]
|
||
|
)
|
||
|
|
||
|
# Removing a clipper connection sets the identifier most recently
|
||
|
# used one as value.
|
||
|
conn.delete()
|
||
|
|
||
|
p.refresh_from_db()
|
||
|
self.assertEqual(p.login_clipper, "anotherclipper")
|
||
|
assertClipperAccountQuerysetEquals(u, ["clipper user anotherclipper"])
|
||
|
|
||
|
# If the deletion of SocialAccount(s) leaves no clipper connection,
|
||
|
# flush the value.
|
||
|
SocialAccount.objects.filter(provider="clipper", user=u).delete()
|
||
|
|
||
|
p.refresh_from_db()
|
||
|
self.assertEqual(p.login_clipper, "")
|
||
|
|
||
|
# Assigning an identifier already in use updates the related connection
|
||
|
# as the most recently used.
|
||
|
SocialAccount.objects.bulk_create(
|
||
|
[
|
||
|
SocialAccount(provider="clipper", user=u, uid="theclipper"),
|
||
|
SocialAccount(provider="clipper", user=u, uid="clip"),
|
||
|
]
|
||
|
)
|
||
|
# Note 'clip' is the most recent one, and value is empty because
|
||
|
# bulk_create didn't trigger post_save signals.
|
||
|
|
||
|
p.login_clipper = "theclipper"
|
||
|
p.save()
|
||
|
|
||
|
self.assertEqual(p.login_clipper, "theclipper")
|
||
|
assertClipperAccountQuerysetEquals(
|
||
|
u, ["clipper user clip", "clipper user theclipper"]
|
||
|
)
|
||
|
|
||
|
# Flushing value removes all clipper connections, and set value to None
|
||
|
# to avoid failure due to the unicity constraint.
|
||
|
p.login_clipper = ""
|
||
|
p.save()
|
||
|
|
||
|
self.assertEqual(p.login_clipper, "")
|
||
|
self.assertFalse(
|
||
|
SocialAccount.objects.filter(provider="clipper", user=u).exists()
|
||
|
)
|
||
|
|
||
|
# Value is unique among all CofProfile instances…
|
||
|
p.login_clipper = "theclipper"
|
||
|
p.save()
|
||
|
p2 = User.objects.create_user("user2", "", "").profile
|
||
|
p2.login_clipper = "theclipper"
|
||
|
|
||
|
with transaction.atomic():
|
||
|
with self.assertRaises(IntegrityError):
|
||
|
p2.save()
|
||
|
|
||
|
# …except for '' (stored as NULL).
|
||
|
p.login_clipper = ""
|
||
|
p.save()
|
||
|
p2.login_clipper = ""
|
||
|
p2.save()
|