Example #1
0
 def setUp(self):
     super(TestUserPreferenceMiddleware, self).setUp()
     self.middleware = LanguagePreferenceMiddleware()
     self.session_middleware = SessionMiddleware()
     self.user = UserFactory.create()
     self.anonymous_user = AnonymousUserFactory()
     self.request = RequestFactory().get('/somewhere')
     self.request.user = self.user
     self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
     self.session_middleware.process_request(self.request)
Example #2
0
 def setUp(self):
     super(TestUserPreferenceMiddleware, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
     self.middleware = LanguagePreferenceMiddleware()
     self.session_middleware = SessionMiddleware()
     self.user = UserFactory.create()
     self.anonymous_user = AnonymousUserFactory()
     self.request = RequestFactory().get('/somewhere')
     self.request.user = self.user
     self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'
     self.session_middleware.process_request(self.request)
     self.client = Client()
 def setUp(self):
     super().setUp()
     self.middleware = LanguagePreferenceMiddleware()
     self.session_middleware = SessionMiddleware()
     self.user = UserFactory.create()
     self.anonymous_user = AnonymousUserFactory()
     self.request = RequestFactory().get('/somewhere')
     self.request.user = self.user
     self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'
     self.session_middleware.process_request(self.request)
     self.client = Client()
 def setUp(self):
     super(TestUserPreferenceMiddleware, self).setUp()
     self.middleware = LanguagePreferenceMiddleware()
     self.session_middleware = SessionMiddleware()
     self.user = UserFactory.create()
     self.anonymous_user = AnonymousUserFactory()
     self.request = RequestFactory().get('/somewhere')
     self.request.user = self.user
     self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
     self.session_middleware.process_request(self.request)
Example #5
0
class TestUserPreferenceMiddleware(CacheIsolationTestCase):
    """
    Tests to make sure user preferences are getting properly set in the middleware.
    """
    def setUp(self):
        super(TestUserPreferenceMiddleware, self).setUp()  # lint-amnesty, pylint: disable=super-with-arguments
        self.middleware = LanguagePreferenceMiddleware()
        self.session_middleware = SessionMiddleware()
        self.user = UserFactory.create()
        self.anonymous_user = AnonymousUserFactory()
        self.request = RequestFactory().get('/somewhere')
        self.request.user = self.user
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'
        self.session_middleware.process_request(self.request)
        self.client = Client()

    def test_logout_shouldnt_remove_cookie(self):

        self.middleware.process_request(self.request)

        self.request.user = self.anonymous_user

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        response.delete_cookie.assert_not_called()

    @ddt.data(None, 'es', 'en')
    def test_preference_setting_changes_cookie(self, lang_pref_out):
        """
        Test that the LANGUAGE_COOKIE is always set to the user's current language preferences
        at the end of the request, with an expiry that's the same as the users current session cookie.
        """
        if lang_pref_out:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_out)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        if lang_pref_out:
            response.set_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                value=lang_pref_out,
                domain=settings.SESSION_COOKIE_DOMAIN,
                max_age=COOKIE_DURATION,
                secure=self.request.is_secure(),
            )
        else:
            response.delete_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                domain=settings.SESSION_COOKIE_DOMAIN,
            )

        assert LANGUAGE_SESSION_KEY not in self.request.session

    @ddt.data(*itertools.product(
        (None, 'eo', 'es'),  # LANGUAGE_COOKIE
        (None, 'es', 'en'),  # Language Preference In
    ))
    @ddt.unpack
    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.set_user_preference')
    def test_preference_cookie_changes_setting(self, lang_cookie, lang_pref_in,
                                               mock_set_user_preference):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie

        if lang_pref_in:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_in)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        self.middleware.process_request(self.request)

        if lang_cookie is None:
            assert mock_set_user_preference.mock_calls == []
        else:
            mock_set_user_preference.assert_called_with(
                self.user, LANGUAGE_KEY, lang_cookie)

    @ddt.data(*(
        (logged_in, ) + test_def for logged_in in (True, False)
        for test_def in [
            # (LANGUAGE_COOKIE, LANGUAGE_SESSION_KEY, Accept-Language In,
            #  Accept-Language Out, Session Lang Out)
            (None, None, None, None, None),
            (None, 'eo', None, None, 'eo'),
            (None, 'en', None, None, 'en'),
            (None, 'eo', 'en', 'en', 'eo'),
            (None, None, 'en', 'en', None),
            ('en', None, None, 'en', None),
            ('en', 'en', None, 'en', 'en'),
            ('en', None, 'eo', 'en;q=1.0,eo', None),
            ('en', None, 'en', 'en', None),
            ('en', 'eo', 'en', 'en', None),
            ('en', 'eo', 'eo', 'en;q=1.0,eo', None)
        ]))
    @ddt.unpack
    def test_preference_cookie_overrides_browser(
        self,
        logged_in,
        lang_cookie,
        lang_session_in,
        accept_lang_in,
        accept_lang_out,
        lang_session_out,
    ):
        if not logged_in:
            self.request.user = self.anonymous_user
        if lang_cookie:
            self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie
        if lang_session_in:
            self.request.session[LANGUAGE_SESSION_KEY] = lang_session_in
        if accept_lang_in:
            self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_lang_in
        else:
            del self.request.META['HTTP_ACCEPT_LANGUAGE']

        self.middleware.process_request(self.request)

        accept_lang_result = self.request.META.get('HTTP_ACCEPT_LANGUAGE')
        if accept_lang_result:
            accept_lang_result = parse_accept_lang_header(accept_lang_result)

        if accept_lang_out:
            accept_lang_out = parse_accept_lang_header(accept_lang_out)

        if accept_lang_out and accept_lang_result:
            six.assertCountEqual(self, accept_lang_result, accept_lang_out)
        else:
            assert accept_lang_result == accept_lang_out

        assert self.request.session.get(
            LANGUAGE_SESSION_KEY) == lang_session_out

    @ddt.data(None, 'es', 'en')
    def test_logout_preserves_cookie(self, lang_cookie):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]
        # Use an actual call to the logout endpoint, because the logout function
        # explicitly clears all cookies
        self.client.get(reverse('logout'))
        if lang_cookie:
            assert self.client.cookies[
                settings.LANGUAGE_COOKIE].value == lang_cookie
        else:
            assert settings.LANGUAGE_COOKIE not in self.client.cookies

    @ddt.data((None, None), ('es', 'es-419'), ('en', 'en'),
              ('es-419', 'es-419'))
    @ddt.unpack
    def test_login_captures_lang_pref(self, lang_cookie, expected_lang):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]

        # Use an actual call to the login endpoint, to validate that the middleware
        # stack does the right thing
        response = self.client.post(
            reverse('user_api_login_session'),
            data={
                'email': self.user.email,
                'password': UserFactory._DEFAULT_PASSWORD,  # pylint: disable=protected-access
                'remember': True,
            })

        assert response.status_code == 200

        if lang_cookie:
            assert response['Content-Language'] == expected_lang
            assert get_user_preference(self.user, LANGUAGE_KEY) == lang_cookie
            assert self.client.cookies[
                settings.LANGUAGE_COOKIE].value == lang_cookie
        else:
            assert response['Content-Language'] == 'en'
            assert get_user_preference(self.user, LANGUAGE_KEY) is None
            assert self.client.cookies[settings.LANGUAGE_COOKIE].value == ''

    def test_process_response_no_user_noop(self):
        del self.request.user
        response = mock.Mock(spec=HttpResponse)

        result = self.middleware.process_response(self.request, response)

        assert result is response
        assert response.mock_calls == []

    def test_preference_update_noop(self):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'es'

        # No preference yet, should write to the database

        assert get_user_preference(self.user, LANGUAGE_KEY) is None
        self.middleware.process_request(self.request)
        assert get_user_preference(self.user, LANGUAGE_KEY) == 'es'

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Preference is the same as the cookie, shouldn't write to the database

        with self.assertNumQueries(3):
            self.middleware.process_request(self.request)

        assert get_user_preference(self.user, LANGUAGE_KEY) == 'es'

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Cookie changed, should write to the database again

        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'
        self.middleware.process_request(self.request)
        assert get_user_preference(self.user, LANGUAGE_KEY) == 'en'

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.is_request_from_mobile_app'
    )
    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.get_user_preference')
    def test_remove_lang_cookie_for_mobile_app(self, mock_get_user_preference,
                                               mock_is_mobile_request):
        """
        Test to verify language preference cookie removed for mobile app requests.
        """
        mock_get_user_preference.return_value = 'en'
        mock_is_mobile_request.return_value = False
        response = mock.Mock(spec=HttpResponse)

        response = self.middleware.process_response(self.request, response)
        response.delete_cookie.assert_not_called()
        response.set_cookie.assert_called()

        mock_is_mobile_request.return_value = True
        response = self.middleware.process_response(self.request, response)
        response.delete_cookie.assert_called()
class TestUserPreferenceMiddleware(TestCase):
    """
    Tests to make sure user preferences are getting properly set in the middleware.
    """

    def setUp(self):
        super(TestUserPreferenceMiddleware, self).setUp()
        self.middleware = LanguagePreferenceMiddleware()
        self.session_middleware = SessionMiddleware()
        self.user = UserFactory.create()
        self.anonymous_user = AnonymousUserFactory()
        self.request = RequestFactory().get('/somewhere')
        self.request.user = self.user
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
        self.session_middleware.process_request(self.request)

    def test_logout_shouldnt_remove_cookie(self):

        self.middleware.process_request(self.request)

        self.request.user = self.anonymous_user

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        response.delete_cookie.assert_not_called()

    @ddt.data(None, 'es', 'en')
    def test_preference_setting_changes_cookie(self, lang_pref_out):
        """
        Test that the LANGUAGE_COOKIE is always set to the user's current language preferences
        at the end of the request, with an expiry that's the same as the users current session cookie.
        """
        if lang_pref_out:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_out)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        if lang_pref_out:
            response.set_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                value=lang_pref_out,
                domain=settings.SESSION_COOKIE_DOMAIN,
                max_age=COOKIE_DURATION,
            )
        else:
            response.delete_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                domain=settings.SESSION_COOKIE_DOMAIN,
            )

        self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session)

    @ddt.data(*itertools.product(
        (None, 'eo', 'es'),  # LANGUAGE_COOKIE
        (None, 'es', 'en'),  # Language Preference In
    ))
    @ddt.unpack
    @mock.patch('openedx.core.djangoapps.lang_pref.middleware.set_user_preference')
    def test_preference_cookie_changes_setting(self, lang_cookie, lang_pref_in, mock_set_user_preference):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie

        if lang_pref_in:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_in)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        self.middleware.process_request(self.request)

        if lang_cookie is None:
            self.assertEqual(mock_set_user_preference.mock_calls, [])
        else:
            mock_set_user_preference.assert_called_with(self.user, LANGUAGE_KEY, lang_cookie)

    @ddt.data(*(
        (logged_in, ) + test_def
        for logged_in in (True, False)
        for test_def in [
            # (LANGUAGE_COOKIE, LANGUAGE_SESSION_KEY, Accept-Language In,
            #  Accept-Language Out, Session Lang Out)
            (None, None, None, None, None),
            (None, 'eo', None, None, 'eo'),
            (None, 'en', None, None, 'en'),
            (None, 'eo', 'en', 'en', 'eo'),
            (None, None, 'en', 'en', None),
            ('en', None, None, 'en', None),
            ('en', 'en', None, 'en', 'en'),
            ('en', None, 'eo', 'en;q=1.0,eo', None),
            ('en', None, 'en', 'en', None),
            ('en', 'eo', 'en', 'en', None),
            ('en', 'eo', 'eo', 'en;q=1.0,eo', None)
        ]
    ))
    @ddt.unpack
    def test_preference_cookie_overrides_browser(
            self, logged_in, lang_cookie, lang_session_in, accept_lang_in, accept_lang_out,
            lang_session_out,
    ):
        if not logged_in:
            self.request.user = self.anonymous_user
        if lang_cookie:
            self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie
        if lang_session_in:
            self.request.session[LANGUAGE_SESSION_KEY] = lang_session_in
        if accept_lang_in:
            self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_lang_in
        else:
            del self.request.META['HTTP_ACCEPT_LANGUAGE']

        self.middleware.process_request(self.request)

        accept_lang_result = self.request.META.get('HTTP_ACCEPT_LANGUAGE')
        if accept_lang_result:
            accept_lang_result = parse_accept_lang_header(accept_lang_result)

        if accept_lang_out:
            accept_lang_out = parse_accept_lang_header(accept_lang_out)

        if accept_lang_out and accept_lang_result:
            self.assertItemsEqual(accept_lang_result, accept_lang_out)
        else:
            self.assertEqual(accept_lang_result, accept_lang_out)

        self.assertEquals(self.request.session.get(LANGUAGE_SESSION_KEY), lang_session_out)

    @ddt.data(None, 'es', 'en')
    def test_logout_preserves_cookie(self, lang_cookie):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]
        # Use an actual call to the logout endpoint, because the logout function
        # explicitly clears all cookies
        self.client.get(reverse('logout'))
        if lang_cookie:
            self.assertEqual(
                self.client.cookies[settings.LANGUAGE_COOKIE].value,
                lang_cookie
            )
        else:
            self.assertNotIn(settings.LANGUAGE_COOKIE, self.client.cookies)

    @ddt.data(
        (None, None),
        ('es', 'es-419'),
        ('en', 'en'),
        ('es-419', 'es-419')
    )
    @ddt.unpack
    def test_login_captures_lang_pref(self, lang_cookie, expected_lang):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]

        # Use an actual call to the login endpoint, to validate that the middleware
        # stack does the right thing
        if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
            response = self.client.post(
                reverse('user_api_login_session'),
                data={
                    'email': self.user.email,
                    'password': UserFactory._DEFAULT_PASSWORD,
                    'remember': True,
                }
            )
        else:
            response = self.client.post(
                reverse('login_post'),
                data={
                    'email': self.user.email,
                    'password': UserFactory._DEFAULT_PASSWORD,
                    'honor_code': True,
                }
            )

        self.assertEqual(response.status_code, 200)

        if lang_cookie:
            self.assertEqual(response['Content-Language'], expected_lang)
            self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), lang_cookie)
            self.assertEqual(
                self.client.cookies[settings.LANGUAGE_COOKIE].value,
                lang_cookie
            )
        else:
            self.assertEqual(response['Content-Language'], 'en')
            self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
            self.assertEqual(self.client.cookies[settings.LANGUAGE_COOKIE].value, '')

    def test_process_response_no_user_noop(self):
        del self.request.user
        response = mock.Mock(spec=HttpResponse)

        result = self.middleware.process_response(self.request, response)

        self.assertIs(result, response)
        self.assertEqual(response.mock_calls, [])

    def test_preference_update_noop(self):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'es'

        # No preference yet, should write to the database

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)

        with self.assertNumQueries(5):
            self.middleware.process_request(self.request)

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Preference is the same as the cookie, shouldn't write to the database

        with self.assertNumQueries(3):
            self.middleware.process_request(self.request)

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Cookie changed, should write to the database again

        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'

        with self.assertNumQueries(5):
            self.middleware.process_request(self.request)

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'en')

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)
class TestUserPreferenceMiddleware(TestCase):
    """
    Tests to make sure user preferences are getting properly set in the middleware.
    """

    def setUp(self):
        super(TestUserPreferenceMiddleware, self).setUp()
        self.middleware = LanguagePreferenceMiddleware()
        self.session_middleware = SessionMiddleware()
        self.user = UserFactory.create()
        self.anonymous_user = AnonymousUserFactory()
        self.request = RequestFactory().get('/somewhere')
        self.request.user = self.user
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
        self.session_middleware.process_request(self.request)

    def test_no_language_set_in_session_or_prefs(self):
        # nothing set in the session or the prefs
        self.middleware.process_request(self.request)
        self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session)  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('eo', 'esperanto')])
    )
    def test_language_in_user_prefs(self):
        # language set in the user preferences and not the session
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)
        self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo')  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english'), ('eo', 'esperanto')])
    )
    def test_language_in_session(self):
        # language set in both the user preferences and session,
        # preference should get precedence. The session will hold the last value,
        # which is probably the user's last preference. Look up the updated preference.

        # Dark lang middleware should run after this middleware, so it can
        # set a session language as an override of the user's preference.
        self.request.session[LANGUAGE_SESSION_KEY] = 'en'  # pylint: disable=no-member
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)

        self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo')  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('eo', 'dummy Esperanto'), ('ar', 'arabic')])
    )
    def test_supported_browser_language_in_session(self):
        """
        test: browser language should be set in user session if it is supported by system for unauthenticated user.
        """
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertEqual(self.request.session[LANGUAGE_SESSION_KEY], 'ar')   # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english')])
    )
    def test_browser_language_not_be_in_session(self):
        """
        test: browser language should not be set in user session if it is not supported by system.
        """
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertNotEqual(self.request.session.get(LANGUAGE_SESSION_KEY), 'ar')   # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english'), ('ar', 'arabic')])
    )
    def test_delete_user_lang_preference_not_supported_by_system(self):
        """
        test: user preferred language has been removed from user preferences model if it is not supported by system
        for authenticated users.
        """
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)
        self.assertEqual(get_user_preference(self.request.user, LANGUAGE_KEY), None)
Example #8
0
class TestUserPreferenceMiddleware(TestCase):
    """
    Tests to make sure user preferences are getting properly set in the middleware.
    """
    def setUp(self):
        super(TestUserPreferenceMiddleware, self).setUp()
        self.middleware = LanguagePreferenceMiddleware()
        self.session_middleware = SessionMiddleware()
        self.user = UserFactory.create()
        self.anonymous_user = AnonymousUserFactory()
        self.request = RequestFactory().get('/somewhere')
        self.request.user = self.user
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
        self.session_middleware.process_request(self.request)

    def test_logout_shouldnt_remove_cookie(self):

        self.middleware.process_request(self.request)

        self.request.user = self.anonymous_user

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        response.delete_cookie.assert_not_called()

    @ddt.data(None, 'es', 'en')
    def test_preference_setting_changes_cookie(self, lang_pref_out):
        """
        Test that the LANGUAGE_COOKIE is always set to the user's current language preferences
        at the end of the request, with an expiry that's the same as the users current session cookie.
        """
        if lang_pref_out:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_out)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        response = mock.Mock(spec=HttpResponse)
        self.middleware.process_response(self.request, response)

        if lang_pref_out:
            response.set_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                value=lang_pref_out,
                domain=settings.SESSION_COOKIE_DOMAIN,
                max_age=COOKIE_DURATION,
            )
        else:
            response.delete_cookie.assert_called_with(
                settings.LANGUAGE_COOKIE,
                domain=settings.SESSION_COOKIE_DOMAIN,
            )

        self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session)

    @ddt.data(*itertools.product(
        (None, 'eo', 'es'),  # LANGUAGE_COOKIE
        (None, 'es', 'en'),  # Language Preference In
    ))
    @ddt.unpack
    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.set_user_preference')
    def test_preference_cookie_changes_setting(self, lang_cookie, lang_pref_in,
                                               mock_set_user_preference):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie

        if lang_pref_in:
            set_user_preference(self.user, LANGUAGE_KEY, lang_pref_in)
        else:
            delete_user_preference(self.user, LANGUAGE_KEY)

        self.middleware.process_request(self.request)

        if lang_cookie is None:
            self.assertEqual(mock_set_user_preference.mock_calls, [])
        else:
            mock_set_user_preference.assert_called_with(
                self.user, LANGUAGE_KEY, lang_cookie)

    @ddt.data(*(
        (logged_in, ) + test_def for logged_in in (True, False)
        for test_def in [
            # (LANGUAGE_COOKIE, LANGUAGE_SESSION_KEY, Accept-Language In,
            #  Accept-Language Out, Session Lang Out)
            (None, None, None, None, None),
            (None, 'eo', None, None, 'eo'),
            (None, 'en', None, None, 'en'),
            (None, 'eo', 'en', 'en', 'eo'),
            (None, None, 'en', 'en', None),
            ('en', None, None, 'en', None),
            ('en', 'en', None, 'en', 'en'),
            ('en', None, 'eo', 'en;q=1.0,eo', None),
            ('en', None, 'en', 'en', None),
            ('en', 'eo', 'en', 'en', None),
            ('en', 'eo', 'eo', 'en;q=1.0,eo', None)
        ]))
    @ddt.unpack
    def test_preference_cookie_overrides_browser(
        self,
        logged_in,
        lang_cookie,
        lang_session_in,
        accept_lang_in,
        accept_lang_out,
        lang_session_out,
    ):
        if not logged_in:
            self.request.user = self.anonymous_user
        if lang_cookie:
            self.request.COOKIES[settings.LANGUAGE_COOKIE] = lang_cookie
        if lang_session_in:
            self.request.session[LANGUAGE_SESSION_KEY] = lang_session_in
        if accept_lang_in:
            self.request.META['HTTP_ACCEPT_LANGUAGE'] = accept_lang_in
        else:
            del self.request.META['HTTP_ACCEPT_LANGUAGE']

        self.middleware.process_request(self.request)

        accept_lang_result = self.request.META.get('HTTP_ACCEPT_LANGUAGE')
        if accept_lang_result:
            accept_lang_result = parse_accept_lang_header(accept_lang_result)

        if accept_lang_out:
            accept_lang_out = parse_accept_lang_header(accept_lang_out)

        if accept_lang_out and accept_lang_result:
            self.assertItemsEqual(accept_lang_result, accept_lang_out)
        else:
            self.assertEqual(accept_lang_result, accept_lang_out)

        self.assertEquals(self.request.session.get(LANGUAGE_SESSION_KEY),
                          lang_session_out)

    @ddt.data(None, 'es', 'en')
    def test_logout_preserves_cookie(self, lang_cookie):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]
        # Use an actual call to the logout endpoint, because the logout function
        # explicitly clears all cookies
        self.client.get(reverse('logout'))
        if lang_cookie:
            self.assertEqual(
                self.client.cookies[settings.LANGUAGE_COOKIE].value,
                lang_cookie)
        else:
            self.assertNotIn(settings.LANGUAGE_COOKIE, self.client.cookies)

    @ddt.data((None, None), ('es', 'es-419'), ('en', 'en'),
              ('es-419', 'es-419'))
    @ddt.unpack
    def test_login_captures_lang_pref(self, lang_cookie, expected_lang):
        if lang_cookie:
            self.client.cookies[settings.LANGUAGE_COOKIE] = lang_cookie
        elif settings.LANGUAGE_COOKIE in self.client.cookies:
            del self.client.cookies[settings.LANGUAGE_COOKIE]

        # Use an actual call to the login endpoint, to validate that the middleware
        # stack does the right thing
        if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
            response = self.client.post(reverse('user_api_login_session'),
                                        data={
                                            'email': self.user.email,
                                            'password':
                                            UserFactory._DEFAULT_PASSWORD,
                                            'remember': True,
                                        })
        else:
            response = self.client.post(reverse('login_post'),
                                        data={
                                            'email': self.user.email,
                                            'password':
                                            UserFactory._DEFAULT_PASSWORD,
                                            'honor_code': True,
                                        })

        self.assertEqual(response.status_code, 200)

        if lang_cookie:
            self.assertEqual(response['Content-Language'], expected_lang)
            self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY),
                             lang_cookie)
            self.assertEqual(
                self.client.cookies[settings.LANGUAGE_COOKIE].value,
                lang_cookie)
        else:
            self.assertEqual(response['Content-Language'], 'en')
            self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY),
                             None)
            self.assertEqual(
                self.client.cookies[settings.LANGUAGE_COOKIE].value, '')

    def test_process_response_no_user_noop(self):
        del self.request.user
        response = mock.Mock(spec=HttpResponse)

        result = self.middleware.process_response(self.request, response)

        self.assertIs(result, response)
        self.assertEqual(response.mock_calls, [])

    def test_preference_update_noop(self):
        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'es'

        # No preference yet, should write to the database

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), None)
        self.middleware.process_request(self.request)
        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Preference is the same as the cookie, shouldn't write to the database

        with self.assertNumQueries(3):
            self.middleware.process_request(self.request)

        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'es')

        response = mock.Mock(spec=HttpResponse)

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)

        # Cookie changed, should write to the database again

        self.request.COOKIES[settings.LANGUAGE_COOKIE] = 'en'
        self.middleware.process_request(self.request)
        self.assertEqual(get_user_preference(self.user, LANGUAGE_KEY), 'en')

        with self.assertNumQueries(1):
            self.middleware.process_response(self.request, response)
Example #9
0
class TestUserPreferenceMiddleware(TestCase):
    """
    Tests to make sure user preferences are getting properly set in the middleware.
    """

    def setUp(self):
        super(TestUserPreferenceMiddleware, self).setUp()
        self.middleware = LanguagePreferenceMiddleware()
        self.session_middleware = SessionMiddleware()
        self.user = UserFactory.create()
        self.anonymous_user = AnonymousUserFactory()
        self.request = RequestFactory().get('/somewhere')
        self.request.user = self.user
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'ar;q=1.0'  # pylint: disable=no-member
        self.session_middleware.process_request(self.request)

    def test_no_language_set_in_session_or_prefs(self):
        # nothing set in the session or the prefs
        self.middleware.process_request(self.request)
        self.assertNotIn(LANGUAGE_SESSION_KEY, self.request.session)  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('eo', 'esperanto')])
    )
    def test_language_in_user_prefs(self):
        # language set in the user preferences and not the session
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)
        self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo')  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english'), ('eo', 'esperanto')])
    )
    def test_language_in_session(self):
        # language set in both the user preferences and session,
        # preference should get precedence. The session will hold the last value,
        # which is probably the user's last preference. Look up the updated preference.

        # Dark lang middleware should run after this middleware, so it can
        # set a session language as an override of the user's preference.
        self.request.session[LANGUAGE_SESSION_KEY] = 'en'  # pylint: disable=no-member
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)

        self.assertEquals(self.request.session[LANGUAGE_SESSION_KEY], 'eo')  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('eo', 'dummy Esperanto'), ('ar', 'arabic')])
    )
    def test_supported_browser_language_in_session(self):
        """
        test: browser language should be set in user session if it is supported by system for unauthenticated user.
        """
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertEqual(self.request.session[LANGUAGE_SESSION_KEY], 'ar')   # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english')])
    )
    def test_browser_language_not_be_in_session(self):
        """
        test: browser language should not be set in user session if it is not supported by system.
        """
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertNotEqual(self.request.session.get(LANGUAGE_SESSION_KEY), 'ar')   # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english'), ('ar', 'arabic')])
    )
    def test_delete_user_lang_preference_not_supported_by_system(self):
        """
        test: user preferred language has been removed from user preferences model if it is not supported by system
        for authenticated users.
        """
        set_user_preference(self.user, LANGUAGE_KEY, 'eo')
        self.middleware.process_request(self.request)
        self.assertEqual(get_user_preference(self.request.user, LANGUAGE_KEY), None)

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('eu-es', 'euskara (Espainia)'), ('en', 'english')])
    )
    def test_supported_browser_language_prefix_in_session(self):
        """
        test: browser language should be set in user session if it's prefix is supported by system for
        unathenticated users
        """
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'eu;q=1.0'  # pylint: disable=no-member
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertEqual(self.request.session.get(LANGUAGE_SESSION_KEY), 'eu-es')  # pylint: disable=no-member

    @mock.patch(
        'openedx.core.djangoapps.lang_pref.middleware.released_languages',
        mock.Mock(return_value=[('en', 'english')])
    )
    def test_unsupported_browser_language_prefix(self):
        """
        test: browser language should not be set in user session if it's prefix is not supported by system.
        """
        self.request.META['HTTP_ACCEPT_LANGUAGE'] = 'eu;q=1.0'  # pylint: disable=no-member
        self.request.user = self.anonymous_user
        self.middleware.process_request(self.request)
        self.assertNotEqual(self.request.session.get(LANGUAGE_SESSION_KEY), 'eu-es')   # pylint: disable=no-member