Lelouch
Lelouch

Reputation: 2193

Django test with allauth

I want to test a django app with allauth with the scenario "that for unauthenticated users, they are redirected to the login page, which lists several social network options".

Therefore, the environment requires some social-app to be set up. So I did:

def set_up_allauth():
    site = Site.objects.create(name="localhost", domain="localhost")
    fb = SocialApp.objects.create(
        provider="facebook",
        name="Facebook",
        client_id="<id>",
        secret="<secret>",
    )
    fb.sites.add(site)
    fb.save()

class CollectionPageTest(TestCase):
    def setUp(self):
        set_up_allauth()

    def test_collection_visitor(self):
        # import pdb; pdb.set_trace()
        response = self.client.get(reverse("collection"))
        self.assertRedirects(
            response, reverse("account_login"), status_code=302
        )

If I put a import pdb; pdb.set_trace() at the above indicated position, I can see that SocialApp.objects.all() contains the created Facebook app, but in the end of the test, I always get failure:

ImproperlyConfigured: No Facebook app configured: please add a SocialApp using the Django admin

I wonder what is happening here and how to solve it? (I am guessing this is because the .sites is not hooked up to the current testing environment?)


The part of settings.py that concerns allauth

# ==============
# Django-allauth
# ==============
AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth`
    "django.contrib.auth.backends.ModelBackend",
    # `allauth` specific authentication methods, such as login by e-mail
    "allauth.account.auth_backends.AuthenticationBackend",
)

ACCOUNT_EMAIL_REQUIRED = True
# ACCOUNT_EMAIL_VERIFICATION = "mandatory"
# ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = "/app/"
ACCOUNT_EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = ""

# The id of the working URL in the Sites table
# Currently the URL is http://localhost:8000/
SITE_ID = 1

SOCIALACCOUNT_PROVIDERS = {
    'facebook': {
        'SCOPE': ['email', 'user_photos', "publish_actions"],
        'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
        'METHOD': 'oauth2',
        'LOCALE_FUNC': lambda request: 'en_US',
        'VERIFIED_EMAIL': False,
        'VERSION': 'v2.2'
    },
    'instagram': {
        'AUTH_PARAMS': {'auth_type': 'reauthenticate'},
        'METHOD': 'oauth2',
        'LOCALE_FUNC': lambda request: 'en_US',
        'VERIFIED_EMAIL': False,
    }
}

# The email backend for allauth
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

TEMPLATE_CONTEXT_PROCESSORS = (
    # Required by allauth template tags
    "django.core.context_processors.request",
    # allauth specific context processors
    "allauth.account.context_processors.account",
    "allauth.socialaccount.context_processors.socialaccount",
    'django.contrib.auth.context_processors.auth',
    'postman.context_processors.inbox',     # Django-postman
)

LOGIN_REDIRECT_URL = "/user/dashboard/"
ROOT_URL = ''

Upvotes: 3

Views: 2564

Answers (2)

Adam Starrh
Adam Starrh

Reputation: 6968

So the fixtures weren't working for me. I don't like fixtures anyway, so I came up with an alternate solution:

SetupTestData.py

from django.test import TestCase
from django.contrib.sites.models import Site

class TestData(TestCase):

    @classmethod
    def setUpTestData(cls):

        cls.current_site = Site.objects.get_current()

        cls.SocialApp1 = cls.current_site.socialapp_set.create(
            provider="facebook",
            name="facebook",
            client_id="1234567890",
            secret="0987654321",
        )

        cls.SocialApp2 = cls.current_site.socialapp_set.create(
            provider="instagram",
            name="instagram",
            client_id="1234567890",
            secret="0987654321",
        )

test_collection_page.py

from TestPath.tests.SetupTestData import TestData

class CollectionPageTest(TestData):
    def test_collection_visitor(self):
        # import pdb; pdb.set_trace()
        response = self.client.get(reverse("collection"))
        self.assertRedirects(
            response, reverse("account_login"), status_code=302
        )

Simply subclass the same TestData whenever you need these to be active.

Upvotes: 3

ozren1983
ozren1983

Reputation: 1951

Use following fixture (put it in file social_apps.json, in fixtures folder of your app) to setup allauth and sites:

[
  {
    "model": "sites.site", 
    "pk": 1, 
    "fields": {
      "domain": "localhost", 
      "name": "localhost"
    }
  },
  {
        "model":"socialaccount.socialapp",
        "pk":1,
        "fields":{
            "id":"1",
            "provider":"facebook",
            "name":"facebook",
            "client_id":"0011223344556677",
            "secret":"012345678901234567890123456",
            "key":""
        }
  },
  {
        "model":"socialaccount.socialapp_sites",
        "pk":1,
        "fields":{
            "id":1,
            "socialapp_id":1,
            "site_id":1
        }
  }
]

Then, update your CollectionPageTest to include fixtures declaration:

class CollectionPageTest(TestCase):
    fixtures = ['social_apps']

    def test_collection_visitor(self):
        # import pdb; pdb.set_trace()
        response = self.client.get(reverse("collection"))
        self.assertRedirects(
            response, reverse("account_login"), status_code=302
        )

Upvotes: 1

Related Questions