Example #1
0
class GetAudienceTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_setting_missing(self):
        # If BROWSERID_AUDIENCES isn't defined, raise
        # ImproperlyConfigured.
        request = self.factory.get('/')

        # Simulate missing attribute with a mock property that raises
        # AttributeError.
        with patch('django_browserid.base.settings') as settings:
            mock_browserid_audiences = PropertyMock(side_effect=AttributeError)
            type(settings).BROWSERID_AUDIENCES = mock_browserid_audiences

            with self.assertRaises(ImproperlyConfigured):
                base.get_audience(request)

    def test_same_origin_found(self):
        # If an audience is found in BROWSERID_AUDIENCES with the same
        # origin as the request URI, return it.
        request = self.factory.get('http://testserver')

        audiences = ['https://example.com', 'http://testserver']
        with self.settings(BROWSERID_AUDIENCES=audiences):
            eq_(base.get_audience(request), 'http://testserver')

    def test_no_audience(self):
        # If no matching audiences is found in BROWSERID_AUDIENCES,
        # raise ImproperlyConfigured.
        request = self.factory.get('http://testserver')

        with self.settings(BROWSERID_AUDIENCES=['https://example.com']):
            with self.assertRaises(ImproperlyConfigured):
                base.get_audience(request)
Example #2
0
class InValidStockRSRTestCase(TestCase):

    """Testing request to stock RSR.

    invalid hosts :
    - "invalid_host"
    - ""
    """

    def setUp(self):
        """Setup."""
        self.factory = RequestFactory()
        self.req_not_found_host = self.factory.get('/', {}, HTTP_HOST='not-found.akvo.org')
        self.req_not_found_host2 = self.factory.get('/', {}, HTTP_HOST='not-found.test.akvo.org')
        self.req_invalid_host = self.factory.get('/', {}, HTTP_HOST='invalid_host')
        self.req_empty_host = self.factory.get('/', {}, HTTP_HOST='')

    def test_is_rsr_host(self):
        """Test request to normal RSR host."""
        self.assertFalse(_is_rsr_host(self.req_not_found_host.get_host()))
        self.assertFalse(_is_rsr_host(self.req_not_found_host2.get_host()))
        with self.assertRaises(DisallowedHost):
            _is_rsr_host(self.req_invalid_host.get_host())
        with self.assertRaises(DisallowedHost):
            _is_rsr_host(self.req_empty_host.get_host())
class GetNetTest(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        self.url = reverse('calendar:list')

    def test_valid_next(self):
        url = self.url + '?cal_next=1'
        req = self.factory.get(url)
        net = get_net(req)
        self.assertEqual(net, 1)

    def test_valid_prev(self):
        url = self.url + '?cal_prev=1'
        req = self.factory.get(url)
        net = get_net(req)
        self.assertEqual(net, -1)

    def test_invalid(self):
        url = self.url + '?cal_next=nann'
        req = self.factory.get(url)
        net = get_net(req)
        self.assertEqual(net, 0)

    def test_valid_next_and_prev(self):
        url = self.url + '?cal_next=1&cal_prev=2'
        req = self.factory.get(url)
        net = get_net(req)
        self.assertEqual(net, -1)
class HelperTester(django.test.TestCase):
    def setUp(self):
        # Every test needs access to the request factory.
        self.factory = RequestFactory()
        self.helper = helper.Helper()
        pass

    def tearDown(self):
        assert settings.CACHE_BACKEND == "locmem:///"
        [cache.delete(key) for key in cache._cache.keys()]

    def test_uniqueList(self):
        a = [1, 1, 2, 3, 4, 7, 7, 6, 6, 8]
        b = helper.uniqueList(a)
        expected = [1, 2, 3, 4, 7, 6, 8]
        for (i, j) in zip(b, expected):
            self.assertTrue(i == j)

    def test_jsonp(self):
        request = self.factory.get("/home")
        response = self.helper.jsonp(request, {"random_data": "random"})
        self.assertTrue(response.content, '{"random_data": "random"}')
        request = self.factory.get("/home?callback=123")
        response = self.helper.jsonp(request, {"random_data": "random"})
        self.assertTrue(response.content, '123({"random_data": "random"});')
Example #5
0
class CsrfTokenTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        self.view = views.CsrfToken()

    def test_lazy_token_called(self):
        """
        If the csrf_token variable in the RequestContext is a lazy
        callable, make sure it is called during the view.
        """
        global _lazy_csrf_token_called
        _lazy_csrf_token_called = False

        # I'd love to use a Mock here instead, but lazy doesn't behave
        # well with Mocks for some reason.
        def _lazy_csrf_token():
            global _lazy_csrf_token_called
            _lazy_csrf_token_called = True
            return 'asdf'
        csrf_token = lazy(_lazy_csrf_token, six.text_type)()

        request = self.factory.get('/browserid/csrf/')
        with patch('django_browserid.views.RequestContext') as RequestContext:
            RequestContext.return_value = {'csrf_token': csrf_token}
            response = self.view.get(request)

        eq_(response.status_code, 200)
        eq_(response.content, b'asdf')
        ok_(_lazy_csrf_token_called)

    def test_never_cache(self):
        request = self.factory.get('/browserid/csrf/')
        response = self.view.get(request)
        eq_(response['Cache-Control'], 'max-age=0')
Example #6
0
class CsrfTokenTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        self.view = views.CsrfToken()

    def test_session_csrf(self):
        request = self.factory.get('/browserid/csrf/')
        request.csrf_token = 'asdf'

        response = self.view.get(request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, b'asdf')

    def test_django_csrf(self):
        request = self.factory.get('/browserid/csrf/')
        rotate_token(request)
        token = get_token(request)

        response = self.view.get(request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.content, six.b(token))

    def test_never_cache(self):
        request = self.factory.get('/browserid/csrf/')
        response = self.view.get(request)
        self.assertTrue('max-age=0' in response['Cache-Control'])
class LoginViewTestCase(unittest.TestCase):
    
    def setUp(self):
        self.factory = RequestFactory()
    
    def test_get(self):
        request = self.factory.get(reverse("account_login"))
        request.user = AnonymousUser()
        response = LoginView.as_view()(request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.template_name, ["account/login.html"])

    def test_get_disabled(self):
        request = self.factory.get(reverse("account_login"))
        request.user = AnonymousUser()
        response = LoginDisabledView.as_view()(request)
        self.assertEqual(response.status_code, 200)
    
    def test_post_disabled(self):
        request = self.factory.post(reverse("account_login"))
        request.user = AnonymousUser()
        response = LoginDisabledView.as_view()(request)
        self.assertEqual(response.status_code, 403)
    
    def test_custom_redirect_field(self):
        request = self.factory.request()
        request.GET = {"next_page": "/profile/"}
        form = LoginUsernameForm({"username": "******", "password": "******"})
        view = LoginRedirectView(request=request, redirect_field_name="next_page")
        self.assertEqual("/profile/", view.form_valid(form)["Location"])
class BaseClientTestCase(object):
    "Common client test functionality."

    oauth_client = None

    def setUp(self):
        super(BaseClientTestCase, self).setUp()
        self.consumer_key = self.get_random_string()
        self.consumer_secret = self.get_random_string()
        self.provider = self.create_provider(
            consumer_key=self.consumer_key, consumer_secret=self.consumer_secret)
        self.oauth = self.oauth_client(self.provider)
        self.factory = RequestFactory()

    def test_redirect_url(self, *args, **kwargs):
        "Redirect url is build from provider authorization_url."
        with patch.object(self.oauth, 'get_redirect_args') as args:
            args.return_value = {'foo': 'bar'}
            request = self.factory.get('/login/')
            url = self.oauth.get_redirect_url(request, callback='/callback/')
            scheme, netloc, path, params, query, fragment = urlparse(url)
            query = parse_qs(query)
            self.assertEqual('%s://%s%s' % (scheme, netloc, path), self.provider.authorization_url)
            self.assertEqual(query, {'foo': ['bar']})

    def test_additional_redirect_args(self, *args, **kwargs):
        "Additional redirect arguments."
        with patch.object(self.oauth, 'get_redirect_args') as args:
            args.return_value = {'foo': 'bar'}
            request = self.factory.get('/login/')
            additional = {'scope': 'email'}
            url = self.oauth.get_redirect_url(request, callback='/callback/', parameters=additional)
            scheme, netloc, path, params, query, fragment = urlparse(url)
            query = parse_qs(query)
            self.assertEqual(query, {'foo': ['bar'], 'scope': ['email']})
Example #9
0
class TestTourView(TestCase):
    def setUp(self):
        self.view = fx_views.TourView.as_view()
        self.rf = RequestFactory(HTTP_USER_AGENT='Firefox')

    @override_settings(DEV=True)
    def test_fx_old_tour_template(self, render_mock):
        """Should use old firstrun template"""
        req = self.rf.get('/en-US/firefox/tour/')
        self.view(req, version='29.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/australis/firstrun.html'])

    @override_settings(DEV=True)
    def test_fx_dev_browser_35_0_a2(self, render_mock):
        """Should use dev browser firstrun template"""
        req = self.rf.get('/en-US/firefox/tour/')
        self.view(req, version='35.0a2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/dev-firstrun.html'])

    @override_settings(DEV=True)
    def test_fx_firstrun_tour_36_0(self, render_mock):
        """Should use fx36 tour template for 36.0"""
        req = self.rf.get('/en-US/firefox/tour/')
        self.view(req, version='36.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/australis/fx36/tour.html'])
Example #10
0
class GetPageNumberFromRequestTest(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def test_no_querystring_key(self):
        # Ensure the first page is returned if page info cannot be
        # retrieved from the querystring.
        request = self.factory.get('/')
        self.assertEqual(1, utils.get_page_number_from_request(request))

    def test_default_querystring_key(self):
        # Ensure the default page label is used if ``querystring_key``
        # is not provided.
        request = self.factory.get('?{0}=2'.format(PAGE_LABEL))
        self.assertEqual(2, utils.get_page_number_from_request(request))

    def test_default(self):
        # Ensure the default page number is returned if page info cannot be
        # retrieved from the querystring.
        request = self.factory.get('/')
        page_number = utils.get_page_number_from_request(request, default=3)
        self.assertEqual(3, page_number)

    def test_custom_querystring_key(self):
        # Ensure the page returned correctly reflects the ``querystring_key``.
        request = self.factory.get('?mypage=4'.format(PAGE_LABEL))
        page_number = utils.get_page_number_from_request(
            request, querystring_key='mypage')
        self.assertEqual(4, page_number)

    def test_post_data(self):
        # The page number can also be present in POST data.
        request = self.factory.post('/', {PAGE_LABEL: 5})
        self.assertEqual(5, utils.get_page_number_from_request(request))
Example #11
0
class UtilModuleTest(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def test_get_credentials_no_cloud(self):
        request = self.factory.get('url')
        request.META['HTTP_AUTHORIZATION'] = 'Basic ' + base64.b64encode('user:pass')
        user, password, cloud = util.get_credentials(request)
        self.assertEqual(user, 'user')
        self.assertEqual(password, 'pass')
        self.assertEqual(cloud, settings.LIB_DIGI_DEVICECLOUD['DEFAULT_CLOUD_SERVER'])

    def test_get_credentials_with_cloud(self):
        request = self.factory.get('url')
        usercloud= settings.LIB_DIGI_DEVICECLOUD['USERNAME_CLOUD_DELIMETER'].join(['user', 'custom_cloud'])
        request.META['HTTP_AUTHORIZATION'] = 'Basic ' + base64.b64encode(':'.join([usercloud, 'pass']))
        user, password, cloud = util.get_credentials(request)
        self.assertEqual(user, 'user')
        self.assertEqual(password, 'pass')
        self.assertEqual(cloud, 'custom_cloud')

    def test_key_search(self):
        d = {'a': {'deeply': {'nested': {'dict': {'key': 'value'}}}}}
        self.assertTrue(util.is_key_in_nested_dict(d, 'nested'))
        self.assertFalse(util.is_key_in_nested_dict(d, 'nope'))
Example #12
0
class TestTourView(TestCase):
    def setUp(self):
        self.view = fx_views.TourView.as_view()
        self.rf = RequestFactory(HTTP_USER_AGENT='Firefox')

    @override_settings(DEV=False)
    def test_fx_australis_secure_redirect(self, render_mock):
        """Should redirect to https"""
        url = '/en-US/firefox/tour/'
        req = self.rf.get(url)
        with patch.object(req, 'is_secure', return_value=False):
            resp = self.view(req, fx_version='29.0a2')
        eq_(resp['location'], 'https://testserver' + url)

    @override_settings(DEV=True)
    def test_fx_australis_secure_redirect_not_dev(self, render_mock):
        """Should not redirect to https: in DEV mode."""
        url = '/en-US/firefox/tour/'
        req = self.rf.get(url)
        with patch.object(req, 'is_secure', return_value=False):
            resp = self.view(req, fx_version='29.0a2')
        eq_(resp.status_code, 200)

    @override_settings(DEV=True)
    def test_fx_australis_secure_redirect_secure(self, render_mock):
        """Should not redirect to https: when already secure."""
        url = '/en-US/firefox/tour/'
        req = self.rf.get(url)
        with patch.object(req, 'is_secure', return_value=True):
            resp = self.view(req, fx_version='29.0a2')
        eq_(resp.status_code, 200)
Example #13
0
class GetQuerystringForPageTest(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def test_querystring(self):
        # Ensure the querystring is correctly generated from request.
        request = self.factory.get('/')
        querystring = utils.get_querystring_for_page(request, 2, 'mypage')
        self.assertEqual('?mypage=2', querystring)

    def test_default_page(self):
        # Ensure the querystring is empty for the default page.
        request = self.factory.get('/')
        querystring = utils.get_querystring_for_page(
            request, 3, 'mypage', default_number=3)
        self.assertEqual('', querystring)

    def test_composition(self):
        # Ensure existing querystring is correctly preserved.
        request = self.factory.get('/?mypage=1&foo=bar')
        querystring = utils.get_querystring_for_page(request, 4, 'mypage')
        self.assertIn('mypage=4', querystring)
        self.assertIn('foo=bar', querystring)

    def test_querystring_key(self):
        # The querystring key is deleted from the querystring if present.
        request = self.factory.get('/?querystring_key=mykey')
        querystring = utils.get_querystring_for_page(request, 5, 'mypage')
        self.assertEqual('?mypage=5', querystring)
Example #14
0
    def test_version_sidebar(self):
        request = RequestFactory()
        request.GET = {}
        request.APP = amo.FIREFOX

        request.get(reverse('search.search'))
        facets = {
            u'platforms': [{u'doc_count': 58, u'key': 1}],
            u'appversions': [{u'doc_count': 58, u'key': 5000000200100}],
            u'categories': [{u'doc_count': 55, u'key': 1}],
            u'tags': [],
        }
        versions = version_sidebar(request, {}, facets)
        assert versions[0].selected

        versions = version_sidebar(request, {'appver': '5.0'}, facets)
        assert versions[1].selected

        # We're not storing the version in the session anymore: no memories.
        versions = version_sidebar(request, {}, facets)
        assert versions[0].selected

        # We read the appver from the cleaned form data.
        request.GET['appver'] = '123.4'
        # No form data, fallback to default (first entry).
        versions = version_sidebar(request, {}, facets)
        assert versions[0].selected
        # Form data has the proper version, use it.
        versions = version_sidebar(request, {'appver': '5.0'}, facets)
        assert versions[1].selected
        # Form data has the proper version, which is new: add it.
        versions = version_sidebar(request, {'appver': '123.4'}, facets)
        assert versions[1].selected
        assert len(versions) == 3
Example #15
0
class TestViews(TestCase):
    def setUp(self):
        self.rf = RequestFactory()

    def test_hacks_newsletter_frames_allow(self):
        """
        Bedrock pages get the 'x-frame-options: DENY' header by default.
        The hacks newsletter page is framed, so needs to ALLOW.
        """
        with self.activate('en-US'):
            resp = self.client.get(reverse('mozorg.hacks_newsletter'))

        ok_('x-frame-options' not in resp)

    @patch('bedrock.newsletter.views.l10n_utils.render')
    def test_updated_allows_good_tokens(self, mock_render):
        token = unicode(uuid.uuid4())
        req = self.rf.get('/', {'token': token, 'unsub': 1})
        updated(req)
        self.assertEqual(mock_render.call_args[0][2]['token'], token)

    @patch('bedrock.newsletter.views.l10n_utils.render')
    def test_updated_disallows_bad_tokens(self, mock_render):
        token = 'the-dude'
        req = self.rf.get('/', {'token': token, 'unsub': 1})
        updated(req)
        eq_(mock_render.call_args[0][2]['token'], None)

        token = '\'>"><img src=x onerror=alert(1)>'
        req = self.rf.get('/', {'token': token, 'unsub': 1})
        updated(req)
        eq_(mock_render.call_args[0][2]['token'], None)
Example #16
0
    def test_cached_view(self):
        calls = [0]

        @cached_view(timeout=100)
        def get_calls(request):
            calls[0] += 1
            return calls[0]

        factory = RequestFactory()
        r1 = factory.get('/hi')
        r2 = factory.get('/hi')
        r2.META['REMOTE_ADDR'] = '10.10.10.10'
        r3 = factory.get('/bye')

        self.assertEqual(get_calls(r1), 1) # cache
        self.assertEqual(get_calls(r1), 1) # hit
        self.assertEqual(get_calls(r2), 1) # hit, since only url is considered
        self.assertEqual(get_calls(r3), 2) # miss

        get_calls.invalidate(r1)
        self.assertEqual(get_calls(r1), 3) # miss

        # Can pass uri to invalidate
        get_calls.invalidate(r1.build_absolute_uri())
        self.assertEqual(get_calls(r1), 4) # miss
Example #17
0
class SSLifyMiddlwareTest(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def test_perma_redirects_http_to_https(self):
        request = self.factory.get('/woot/')
        self.assertTrue(request.build_absolute_uri().startswith('http://'))

        middleware = SSLifyMiddleware()
        request = middleware.process_request(request)

        self.assertIsInstance(request, HttpResponsePermanentRedirect)
        self.assertTrue(request['Location'].startswith('https://'))
        self.assertEqual(443, urlsplit(request['Location']).port)

    def test_custom_ssl_port(self):
        custom_port = 8443
        with self.settings(SSLIFY_PORT=custom_port):
            request = self.factory.get('/woot/')
            middleware = SSLifyMiddleware()
            request = middleware.process_request(request)

            self.assertEqual(custom_port, urlsplit(request['Location']).port)

    def test_disable_for_tests(self):
        with self.settings(SSLIFY_DISABLE=True):
            request = self.client.get('/woot/')
            self.assertEqual(404, request.status_code)

    def tearDown(self):
        del self.factory
Example #18
0
class TestPlatformRedirector(TestCase):
    def setUp(self):
        self.rf = RequestFactory()

    def test_desktop_redirects(self):
        callback = platform_redirector('/red/', '/green/', '/blue/')
        url = callback(self.rf.get('/take/comfort/',
                                   HTTP_USER_AGENT='Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; '
                                                   'rv:53.0) Gecko/20100101 Firefox/53.0'))
        self.assertEqual(url, '/red/')

    def test_android_redirects(self):
        callback = platform_redirector('/red/', '/green/', '/blue/')
        url = callback(self.rf.get('/take/comfort/',
                                   HTTP_USER_AGENT='Mozilla/5.0 (Android 6.0.1; Mobile; rv:51.0) '
                                                   'Gecko/51.0 Firefox/51.0'))
        self.assertEqual(url, '/green/')

    def test_ios_redirects(self):
        callback = platform_redirector('/red/', '/green/', '/blue/')
        url = callback(self.rf.get('/take/comfort/',
                                   HTTP_USER_AGENT='Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3 like '
                                                   'Mac OS X; de-de) AppleWebKit/533.17.9 (KHTML, '
                                                   'like Gecko) Mobile/8F190'))
        self.assertEqual(url, '/blue/')
Example #19
0
class HomeTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_not_authenticated(self):
        """
        If the current user isn't authenticated, render the home
        page.
        """
        request = self.factory.get('/')
        request.user = Mock()
        request.user.is_authenticated.return_value = False

        with patch('affiliates.base.views.render') as render:
            eq_(views.home(request), render.return_value)
            render.assert_called_with(request, 'base/home.html')

    def test_authenticated(self):
        """
        If the current user is authenticated, redirect to the dashboard.
        """
        request = self.factory.get('/')
        request.user = Mock()
        request.user.is_authenticated.return_value = True

        response = views.home(request)
        self.assertRedirectsNoFollow(response, reverse('base.dashboard'))
    def test_review_queue(self):
        tracker, commit1 = make_commit(self.widgy_site, vt_class=ReviewedVersionTracker)

        p = Permission.objects.get(codename='change_versioncommit')
        user = User.objects.create()
        user.user_permissions.add(p)
        user.save()

        request_factory = RequestFactory()

        tracker = refetch(tracker)
        self.assertFalse(tracker.get_published_node(request_factory.get('/')))

        commit1.approve(user)

        tracker = refetch(tracker)
        self.assertEqual(tracker.get_published_node(request_factory.get('/')),
                         commit1.root_node)

        commit2 = tracker.commit(publish_at=timezone.now())
        tracker = refetch(tracker)
        self.assertEqual(tracker.get_published_node(request_factory.get('/')),
                         commit1.root_node)

        commit2.approve(user)
        tracker = refetch(tracker)
        self.assertEqual(tracker.get_published_node(request_factory.get('/')),
                         commit2.root_node)
class MailPreviewMessageViewTest(TestCase):

    def setUp(self):
        self.factory = RequestFactory()

    def test_dispatch_unknown_mail(self):
        request = self.factory.get(
            reverse('mail_factory_preview_message',
                    kwargs={'mail_name': 'unknown', 'lang': 'fr'}))
        view = views.MailPreviewMessageView()
        with self.assertRaises(Http404):
            view.dispatch(request, 'unknown', 'fr')

    def test_dispatch(self):
        request = self.factory.get(
            reverse('mail_factory_preview_message',
                    kwargs={'mail_name': 'no_custom', 'lang': 'fr'}))
        view = views.MailPreviewMessageView()
        view.request = request
        view.dispatch(request, 'no_custom', 'fr')
        self.assertEqual(view.mail_name, 'no_custom')
        self.assertEqual(view.lang, 'fr')
        self.assertEqual(view.mail_class, factory._registry['no_custom'])

    def test_get_context_data(self):
        view = views.MailPreviewMessageView()
        view.lang = 'fr'
        view.mail_name = 'no_custom'
        view.mail_class = factory._registry['no_custom']
        data = view.get_context_data()
        self.assertIn('mail_name', data)
        self.assertEqual(data['mail_name'], 'no_custom')
        self.assertIn('message', data)
Example #22
0
def request_config():
    factory = RequestFactory()
    # test defaults
    request = factory.get("/")
    table = (Fake("Table")
             .has_attr(prefixed_page_field="page",
                       prefixed_per_page_field="per_page",
                       prefixed_order_by_field="sort",
                       order_by=NOTSET)
             .expects("paginate"))
    RequestConfig(request).configure(table)
    assert table.order_by is NOTSET

    # basic test
    request = factory.get("/?page=1&per_page=5&sort=abc")
    table = (Fake("Table")
             .has_attr(prefixed_page_field="page",
                       prefixed_per_page_field="per_page",
                       prefixed_order_by_field="sort")
             .expects("paginate").with_args(page=1, per_page=5)
             .expects("order_by").with_args("abc"))

    RequestConfig(request).configure(table)

    # Test with some defaults.
    request = factory.get("/?page=1&sort=abc")
    table = (Fake("Table")
             .has_attr(prefixed_page_field="page",
                       prefixed_per_page_field="per_page",
                       prefixed_order_by_field="sort")
             .expects("paginate").with_args(page=1, per_page=5)
             .expects("order_by").with_args("abc"))

    RequestConfig(request, paginate={"per_page": 5}).configure(table)
Example #23
0
class Test500View(BaseTest):

    def setUp(self):
        super(Test500View, self).setUp()
        self.factory = RequestFactory()

    def test_default_server_error(self):
        try:
            raise ValueError('test')
        except ValueError:
            request = self.factory.get('/index/{0}/'.format(self.resource.id),
                                       follow=True)
            view = server_error(request)
            self.assertEqual(view.content, '<h1>Server Error (500)</h1>')

    def test_custom_server_error(self):
        try:
            raise TemplateSyntaxError('test')
        except TemplateSyntaxError:
            request = self.factory.get('/index/{0}/'.format(self.resource.id),
                                       follow=True)
            request.user = self.user
            thread_locals.resource = self.resource
            view = server_error(request)
            self.failUnless('TemplateSyntaxError' in view.content)
Example #24
0
class TrackMiddlewareTestCase(TestCase):

    def setUp(self):
        self.track_middleware = TrackMiddleware()
        self.request_factory = RequestFactory()

    def test_normal_request(self, mock_server_track):
        request = self.request_factory.get('/somewhere')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    def test_default_filters_do_not_render_view(self, mock_server_track):
        for url in ['/event', '/event/1', '/login', '/heartbeat']:
            request = self.request_factory.get(url)
            self.track_middleware.process_request(request)
            self.assertFalse(mock_server_track.called)
            mock_server_track.reset_mock()

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[])
    def test_reading_filtered_urls_from_settings(self, mock_server_track):
        request = self.request_factory.get('/event')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)

    @override_settings(TRACKING_IGNORE_URL_PATTERNS=[r'^/some/excluded.*'])
    def test_anchoring_of_patterns_at_beginning(self, mock_server_track):
        request = self.request_factory.get('/excluded')
        self.track_middleware.process_request(request)
        self.assertTrue(mock_server_track.called)
        mock_server_track.reset_mock()

        request = self.request_factory.get('/some/excluded/url')
        self.track_middleware.process_request(request)
        self.assertFalse(mock_server_track.called)
Example #25
0
class SiteMappingTests(TestCase, TestUtils):

    def setUp(self):
        self.factory = RequestFactory()

    def test_get_site_by_request(self):
        dummy_request = self.factory.get('/')
        dummy_request.META['HTTP_REFERER'] = 'http://dev.beamremit.com/'
        site = get_site_by_request(dummy_request)
        self.assertIsNotNone(site)
        self.assertEqual(site.id, 0)
        self.assertEqual(site.domain, 'dev.beamremit.com')

        dummy_request = self.factory.get('/')
        dummy_request.META['HTTP_REFERER'] = 'http://dev.bitcoinagainstebola.org/'
        site = get_site_by_request(dummy_request)
        self.assertIsNotNone(site)
        self.assertEqual(site.id, 1)
        self.assertEqual(site.domain, 'dev.bitcoinagainstebola.org')

        dummy_request = self.factory.get('/')
        dummy_request.META['HTTP_REFERER'] = 'http://dev.bitcoinagainstebola.org/#!/'
        site = get_site_by_request(dummy_request)
        self.assertIsNotNone(site)
        self.assertEqual(site.id, 1)
        self.assertEqual(site.domain, 'dev.bitcoinagainstebola.org')

    def test_get_site_by_request_fail(self):
        dummy_request = self.factory.get('/')
        dummy_request.META['HTTP_REFERER'] = 'foo'
        dummy_request.DATA = {'hello': 'error'}
        site = get_site_by_request(dummy_request)
        self.assertIsNotNone(site)
        self.assertEqual(site.id, 0)
Example #26
0
class MiddlewareTests(TestCase):

    def setUp(self):
        self.factory = RequestFactory()
        self.middleware = SubdomainMiddleware()
        self.url = '/'
        self.old_cache_get = cache.get

    def tearDown(self):
        cache.get = self.old_cache_get

    @override_settings(PRODUCTION_DOMAIN='readthedocs.org')
    def test_no_cname_creation(self):
        self.assertEqual(Domain.objects.count(), 0)
        self.project = get(Project, slug='my_slug')
        cache.get = lambda x: 'my_slug'
        request = self.factory.get(self.url, HTTP_HOST='my.valid.hostname')
        self.middleware.process_request(request)
        self.assertEqual(Domain.objects.count(), 0)

    @override_settings(PRODUCTION_DOMAIN='readthedocs.org')
    def test_no_readthedocs_domain(self):
        self.assertEqual(Domain.objects.count(), 0)
        self.project = get(Project, slug='pip')
        cache.get = lambda x: 'my_slug'
        request = self.factory.get(self.url, HTTP_HOST='pip.readthedocs.org')
        self.middleware.process_request(request)
        self.assertEqual(Domain.objects.count(), 0)
class TemplateTagTestCase(TestCase):
    def setUp(self):
        self.HTTP_HOST = CUSTOM_HTTP_HOST
        self.factory = RequestFactory(HTTP_HOST=self.HTTP_HOST)

    def test_short_url(self):
        """
        the short_url templatetag works with auto-generated links
        """
        link = Link.objects.create(url='http://www.python.org/')
        request = self.factory.get(reverse('index'))
        out = Template(
            "{% load shortener_helpers %}"
            "{% short_url link %}"
        ).render(RequestContext(request, {'link': link}))
        self.assertEqual(
            out, 'http://%s/%s' % (self.HTTP_HOST, link.to_base62()))

    def test_short_url_with_custom(self):
        """
        the short_url templatetag works with custom links
        """
        custom = 'python'
        link = Link.objects.create(
            url='http://www.python.org/', id=base62.to_decimal(custom))
        request = self.factory.get(reverse('index'))
        out = Template(
            "{% load shortener_helpers %}"
            "{% short_url link %}"
        ).render(RequestContext(request, {'link': link}))
        self.assertEqual(
            out, 'http://%s/%s' % (self.HTTP_HOST, link.to_base62()))
Example #28
0
class TemplateFilterChoiceTestCase(TestCase):
    regular_url = "/simple/?param=1"
    pjax_url = "/simple/?param=1&_pjax=true"

    def setUp(self):
        self.rf = RequestFactory()

    def build_regular_request(self):
        return self.rf.get(self.regular_url)

    def build_pjax_request(self):
        return self.rf.get(self.pjax_url, HTTP_X_PJAX=True)

    def test_template_choice_filter_with_request(self):
        from easy_pjax.templatetags.pjax_tags import pjax

        assert pjax("base.html", self.build_pjax_request()) == "pjax_base.html"
        assert pjax("base.html", self.build_regular_request()) == "base.html"

    def test_template_choice_filter_with_template_params(self):
        from easy_pjax.templatetags.pjax_tags import pjax

        assert pjax("base.html,other_pjax.html", self.build_pjax_request()) == "other_pjax.html"
        assert pjax("base.html", self.build_regular_request()) == "base.html"

    def test_template_choice_filter_with_flag(self):
        from easy_pjax.templatetags.pjax_tags import pjax

        assert pjax("base.html", True) == "pjax_base.html"
        assert pjax("base.html", False) == "base.html"
Example #29
0
class TestHome(TestCase):
    def setUp(self):
        self.view = views.HomeTestView.as_view()
        self.rf = RequestFactory()

    @override_settings(MOBILIZER_LOCALE_LINK={'es-ES': 'El Dudarino', 'de': 'Herr Dude'})
    def test_gets_right_mobilizer_url(self, resp_mock):
        """Home page should get correct mobilizer link for locale."""
        req = self.rf.get('/')
        req.locale = 'de'
        self.view(req)
        ctx = resp_mock.call_args[0][2]
        self.assertEqual(ctx['mobilizer_link'], 'Herr Dude')

    @override_settings(MOBILIZER_LOCALE_LINK={'en-US': 'His Dudeness', 'de': 'Herr Dude'})
    def test_gets_default_mobilizer_url(self, resp_mock):
        """Home page should get default mobilizer link for other locale."""
        req = self.rf.get('/')
        req.locale = 'xx'  # does not exist
        self.view(req)
        ctx = resp_mock.call_args[0][2]
        self.assertEqual(ctx['mobilizer_link'], 'His Dudeness')

    def test_can_post(self, resp_mock):
        """Home page must accept post for newsletter signup."""
        req = self.rf.post('/')
        self.view(req)
        # would return 405 before calling render otherwise
        resp_mock.assert_called_once_with(req, ['mozorg/home.html'], ANY)
Example #30
0
class TestContributeSignupSwitcher(TestCase):
    def setUp(self):
        self.rf = RequestFactory()

        patcher = patch('bedrock.mozorg.views.lang_file_has_tag')
        self.lang_file_has_tag = patcher.start()
        self.addCleanup(patcher.stop)

        patcher = patch('bedrock.mozorg.views.ContributeSignup')
        self.ContributeSignup = patcher.start()
        self.addCleanup(patcher.stop)

        patcher = patch('bedrock.mozorg.views.ContributeSignupOldForm')
        self.ContributeSignupOldForm = patcher.start()
        self.addCleanup(patcher.stop)

    def test_uses_new_view(self):
        """Uses new view when lang file has the tag."""
        req = self.rf.get('/')
        self.lang_file_has_tag.return_value = True
        views.contribute_signup(req)
        self.ContributeSignup.as_view.return_value.assert_called_with(req)
        self.assertFalse(self.ContributeSignupOldForm.as_view.return_value.called)

    def test_uses_old_view(self):
        """Uses old view when lang file does not have the tag."""
        req = self.rf.get('/')
        self.lang_file_has_tag.return_value = False
        views.contribute_signup(req)
        self.ContributeSignupOldForm.as_view.return_value.assert_called_with(req)
        self.assertFalse(self.ContributeSignup.as_view.return_value.called)
Example #31
0
class TestWhatsNew(TestCase):
    def setUp(self):
        self.view = fx_views.WhatsnewView.as_view()
        self.rf = RequestFactory(HTTP_USER_AGENT='Firefox')

    @override_settings(DEV=True)
    def test_fx_dev_browser_35_0_a2_whatsnew(self, render_mock):
        """Should show dev browser whatsnew template"""
        req = self.rf.get('/en-US/firefox/whatsnew/')
        self.view(req, version='35.0a2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/dev-whatsnew.html'])

    @override_settings(DEV=True)
    def test_rv_prefix(self, render_mock):
        """Prefixed oldversion shouldn't impact version sniffing."""
        req = self.rf.get('/en-US/firefox/whatsnew/?oldversion=rv:10.0')
        self.view(req, version='54.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.html'])

    @override_settings(DEV=True)
    def test_fx_default_whatsnew(self, render_mock):
        """Should use standard template for 54.0"""
        req = self.rf.get('/en-US/firefox/whatsnew/')
        self.view(req, version='54.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.html'])

    # begin 57.0 whatsnew tests

    @override_settings(DEV=True)
    def test_fx_57_0_EN(self, render_mock):
        """Should use English CEO letter template for 57.0 in English"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'en-US'
        self.view(req, version='57.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/fx57/whatsnew-57.en-US.html'])

    @override_settings(DEV=True)
    def test_fx_57_0_locale(self, render_mock):
        """Should use regular template for 57.0 in locales without the letter"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'nl'
        self.view(req, version='57.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/fx57/whatsnew-57.html'])

    @override_settings(DEV=True)
    def test_fx_dev_57_0(self, render_mock):
        """Should use developer whatsnew page for 57.0 dev edition"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'en-US'
        self.view(req, version='57.0a2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/developer/whatsnew.html'])

    @override_settings(DEV=True)
    def test_fx_57_0_old_version(self, render_mock):
        """Should use Quantum template when updating from older major version"""
        req = self.rf.get('/en-US/firefox/whatsnew/?oldversion=56.0')
        self.view(req, version='57.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/fx57/whatsnew-57.en-US.html'])

    @override_settings(DEV=True)
    def test_fx_57_0_old_minor_version(self, render_mock):
        """Should use mobile promo template when updating from older minor version"""
        req = self.rf.get('/en-US/firefox/whatsnew/?oldversion=57.0.1')
        self.view(req, version='57.0.2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.html'])

    # end 57.0 whatsnew tests

    # begin 59.0 whatsnew tests

    @override_settings(DEV=True)
    def test_fx_59_0(self, render_mock):
        """Should use Firefox Accounts template for 59.0"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'en-US'
        self.view(req, version='59.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fxa.html'])

    @override_settings(DEV=True)
    def test_fx_59_0_old_major_version(self, render_mock):
        """Should use Firefox Accounts template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=58.0')
        req.locale = 'en-US'
        self.view(req, version='59.0.1')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fxa.html'])

    @override_settings(DEV=True)
    def test_fx_59_0_old_minor_version(self, render_mock):
        """Should use regular whatsnew template when updating from older minor version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=59.0')
        req.locale = 'en-US'
        self.view(req, version='59.0.1')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.html'])

    @override_settings(DEV=True)
    def test_fx_59_0_id_locale_template(self, render_mock):
        """Should use id locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=58.0')
        req.locale = 'id'
        self.view(req, version='59.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.id.html'])

    @override_settings(DEV=True)
    def test_fx_59_0_zh_TW_locale_template(self, render_mock):
        """Should use zh-TW locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=58.0')
        req.locale = 'zh-TW'
        self.view(req, version='59.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.zh-TW.html'])

    # end 59.0 whatsnew tests

    # begin 60.0 whatsnew tests

    @override_settings(DEV=True)
    def test_fx_60_0(self, render_mock):
        """Should use FxA/Fx mobile/Focus template for 60.0"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'en-US'
        self.view(req, version='60.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fx60.html'])

    @override_settings(DEV=True)
    def test_fx_60_0_old_major_version(self, render_mock):
        """Should use FxA/Fx mobile/Focus template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=59.0')
        req.locale = 'en-US'
        self.view(req, version='60.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fx60.html'])

    @override_settings(DEV=True)
    def test_fx_60_0_id_locale_template(self, render_mock):
        """Should use id locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=59.0')
        req.locale = 'id'
        self.view(req, version='60.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.id.html'])

    @override_settings(DEV=True)
    def test_fx_60_0_zh_TW_locale_template(self, render_mock):
        """Should use zh-TW locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=59.0')
        req.locale = 'zh-TW'
        self.view(req, version='60.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.zh-TW.html'])

    # end 60.0 whatsnew tests

    # begin 61.0 whatsnew tests

    @override_settings(DEV=True)
    def test_fx_61_0(self, render_mock):
        """Should use FxA/Fx mobile/Focus template for 61.0"""
        req = self.rf.get('/firefox/whatsnew/')
        req.locale = 'en-US'
        self.view(req, version='61.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fx61.html'])

    @override_settings(DEV=True)
    def test_fx_61_0_old_major_version(self, render_mock):
        """Should use FxA/Fx mobile/Focus template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=60.0')
        req.locale = 'en-US'
        self.view(req, version='61.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/whatsnew-fx61.html'])

    @override_settings(DEV=True)
    def test_fx_61_0_id_locale_template(self, render_mock):
        """Should use id locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=60.0')
        req.locale = 'id'
        self.view(req, version='61.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.id.html'])

    @override_settings(DEV=True)
    def test_fx_61_0_zh_TW_locale_template(self, render_mock):
        """Should use zh-TW locale specific template when updating from older major version"""
        req = self.rf.get('/firefox/whatsnew/?oldversion=60.0')
        req.locale = 'zh-TW'
        self.view(req, version='61.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/whatsnew/index.zh-TW.html'])
Example #32
0
class EditUserViews(TestCase):
    """view user and edit profile"""
    def setUp(self):
        """we need basic test data and mocks"""
        self.factory = RequestFactory()
        with patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"):
            self.local_user = models.User.objects.create_user(
                "*****@*****.**",
                "*****@*****.**",
                "password",
                local=True,
                localname="mouse",
            )
            self.rat = models.User.objects.create_user("*****@*****.**",
                                                       "*****@*****.**",
                                                       "password",
                                                       local=True,
                                                       localname="rat")

            self.book = models.Edition.objects.create(
                title="test",
                parent_work=models.Work.objects.create(title="test work"))
            with patch(
                    "bookwyrm.models.activitypub_mixin.broadcast_task.delay"):
                models.ShelfBook.objects.create(
                    book=self.book,
                    user=self.local_user,
                    shelf=self.local_user.shelf_set.first(),
                )

        models.SiteSettings.objects.create()
        self.anonymous_user = AnonymousUser
        self.anonymous_user.is_authenticated = False

    def test_edit_user_page(self, _):
        """there are so many views, this just makes sure it LOADS"""
        view = views.EditUser.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        result = view(request)
        self.assertIsInstance(result, TemplateResponse)
        result.render()
        self.assertEqual(result.status_code, 200)

    def test_edit_user(self, _):
        """use a form to update a user"""
        view = views.EditUser.as_view()
        form = forms.EditUserForm(instance=self.local_user)
        form.data["name"] = "New Name"
        form.data["email"] = "*****@*****.**"
        form.data["default_post_privacy"] = "public"
        form.data["preferred_timezone"] = "UTC"
        request = self.factory.post("", form.data)
        request.user = self.local_user

        self.assertIsNone(self.local_user.name)
        with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"
                   ) as delay_mock:
            view(request)
            self.assertEqual(delay_mock.call_count, 1)
        self.assertEqual(self.local_user.name, "New Name")
        self.assertEqual(self.local_user.email, "*****@*****.**")

    def test_edit_user_avatar(self, _):
        """use a form to update a user"""
        view = views.EditUser.as_view()
        form = forms.EditUserForm(instance=self.local_user)
        form.data["name"] = "New Name"
        form.data["email"] = "*****@*****.**"
        form.data["default_post_privacy"] = "public"
        form.data["preferred_timezone"] = "UTC"
        image_file = pathlib.Path(__file__).parent.joinpath(
            "../../static/images/no_cover.jpg")
        form.data["avatar"] = SimpleUploadedFile(image_file,
                                                 open(image_file, "rb").read(),
                                                 content_type="image/jpeg")
        request = self.factory.post("", form.data)
        request.user = self.local_user

        with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"
                   ) as delay_mock:
            view(request)
            self.assertEqual(delay_mock.call_count, 1)
        self.assertEqual(self.local_user.name, "New Name")
        self.assertEqual(self.local_user.email, "*****@*****.**")
        self.assertIsNotNone(self.local_user.avatar)
        self.assertEqual(self.local_user.avatar.width, 120)
        self.assertEqual(self.local_user.avatar.height, 120)

    def test_crop_avatar(self, _):
        """reduce that image size"""
        image_file = pathlib.Path(__file__).parent.joinpath(
            "../../static/images/no_cover.jpg")
        image = Image.open(image_file)

        result = views.edit_user.crop_avatar(image)
        self.assertIsInstance(result, ContentFile)
        image_result = Image.open(result)
        self.assertEqual(image_result.size, (120, 120))

    def test_delete_user_page(self, _):
        """there are so many views, this just makes sure it LOADS"""
        view = views.DeleteUser.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        result = view(request)
        self.assertIsInstance(result, TemplateResponse)
        result.render()
        self.assertEqual(result.status_code, 200)

    @patch("bookwyrm.suggested_users.rerank_suggestions_task")
    def test_delete_user(self, *_):
        """use a form to update a user"""
        view = views.DeleteUser.as_view()
        form = forms.DeleteUserForm()
        form.data["password"] = "******"
        request = self.factory.post("", form.data)
        request.user = self.local_user
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session.save()

        self.assertIsNone(self.local_user.name)
        with patch("bookwyrm.models.activitypub_mixin.broadcast_task.delay"
                   ) as delay_mock:
            view(request)
        self.assertEqual(delay_mock.call_count, 1)
        activity = json.loads(delay_mock.call_args[0][1])
        self.assertEqual(activity["type"], "Delete")
        self.assertEqual(activity["actor"], self.local_user.remote_id)
        self.assertEqual(activity["cc"][0],
                         "https://www.w3.org/ns/activitystreams#Public")

        self.local_user.refresh_from_db()
        self.assertFalse(self.local_user.is_active)
        self.assertEqual(self.local_user.deactivation_reason, "self_deletion")
Example #33
0
 def setUp(self):
     factory = RequestFactory()
     request = factory.get(reverse('test_adminsite:index'))
     request.user = self.u1
     self.ctx = site.each_context(request)
Example #34
0
class DeckTest(TestCase):
    def setUp(self):
        self.request_factory = RequestFactory()

    def test_flow(self):
        request = self.request_factory.get("/", {})
        response = new_deck(request)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['shuffled'], False)
        deck_id = resp['deck_id']

        request = self.request_factory.get("/", {})
        response = draw(request, deck_id)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        ace = resp['cards'][0]
        self.assertEqual(ace['suit'], 'SPADES')
        self.assertEqual(ace['value'], 'ACE')
        self.assertEqual(ace['code'], 'AS')
        self.assertEqual(resp['remaining'], 51)

        request = self.request_factory.get("/", {})
        response = shuffle(request, deck_id)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['shuffled'], True)
        self.assertEqual(resp['remaining'], 52)

        request = self.request_factory.get("/", {"count": 10})
        response = draw(request, deck_id)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['remaining'], 42)
        self.assertEqual(len(resp['cards']), 10)
        cards = resp['cards']

        card0 = cards[0]
        card1 = cards[1]

        request = self.request_factory.get(
            "/", {"cards": card0['code'] + ',' + card1['code']})
        response = add_to_pile(request, deck_id, 'chase')
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['remaining'], 42)
        piles = resp['piles']
        self.assertEqual(piles['chase']['remaining'], 2)

        request = self.request_factory.get("/", {"cards": card0['code']})
        response = draw_from_pile(request, deck_id, 'chase')
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        cards = resp['cards']
        self.assertEqual(cards[0]['code'], card0['code'])
        piles = resp['piles']
        self.assertEqual(piles['chase']['remaining'], 1)

        request = self.request_factory.get("/", {})
        response = draw_from_pile(request, deck_id, 'chase')
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))

        self.assertEqual(resp['success'], True)
        cards = resp['cards']
        self.assertEqual(cards[0]['code'], card1['code'])
        piles = resp['piles']
        self.assertEqual(piles['chase']['remaining'], 0)

    def test_partial_deck(self):
        #test to make sure a new partial deck is returned when requested
        request = self.request_factory.get("/", {'cards': 'AC,AD,AH,AS'})
        response = shuffle(request)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['shuffled'], True)
        deck_id = resp['deck_id']
        self.assertEqual(resp['remaining'], 4)

        #draw 4 cards and make sure they match the input data (and verify deck is empty)
        request = self.request_factory.get("/", {'count': 4})
        response = draw(request, deck_id)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        one, two, three, four = False, False, False, False
        for card in resp['cards']:
            if card['code'] == 'AS':
                one = True
            elif card['code'] == 'AD':
                two = True
            elif card['code'] == 'AH':
                three = True
            elif card['code'] == 'AC':
                four = True
        self.assertEqual(resp['remaining'], 0)
        self.assertEqual(one, True)
        self.assertEqual(two, True)
        self.assertEqual(three, True)
        self.assertEqual(four, True)

        #verify that reshuffling a partial deck returns a partial deck
        request = self.request_factory.get("/", {'cards': 'KC,KD,KH,KS'})
        response = shuffle(request)
        resp = json.loads(response.content.decode('utf-8'))
        deck_id = resp['deck_id']
        reshuffleRequest = self.request_factory.get("/", {})
        response = shuffle(reshuffleRequest, deck_id)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['remaining'], 4)

    def test_draw_new(self):
        request = self.request_factory.get("/", {'count': 5})
        response = draw(request)
        self.assertEqual(response.status_code, 200)
        resp = json.loads(response.content.decode('utf-8'))
        self.assertEqual(resp['success'], True)
        self.assertEqual(resp['remaining'], 47)
Example #35
0
class TestViews(ModuleStoreTestCase):
    """
    Tests related to class_dashboard/views.py
    """
    def setUp(self):
        super(TestViews, self).setUp()

        self.request_factory = RequestFactory()
        self.request = self.request_factory.get('')
        self.request.user = None
        self.simple_data = {'error': 'error'}

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_all_problem_grade_distribution_has_access(self, has_access):
        """
        Test returns proper value when have proper access
        """
        has_access.return_value = True
        response = views.all_problem_grade_distribution(
            self.request, 'test/test/test')

        self.assertEqual(json.dumps(self.simple_data), response.content)

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_all_problem_grade_distribution_no_access(self, has_access):
        """
        Test for no access
        """
        has_access.return_value = False
        response = views.all_problem_grade_distribution(
            self.request, 'test/test/test')

        self.assertEqual(
            "{\"error\": \"Access Denied: User does not have access to this course\'s data\"}",
            response.content)

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_all_sequential_open_distribution_has_access(self, has_access):
        """
        Test returns proper value when have proper access
        """
        has_access.return_value = True
        response = views.all_sequential_open_distrib(self.request,
                                                     'test/test/test')

        self.assertEqual(json.dumps(self.simple_data), response.content)

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_all_sequential_open_distribution_no_access(self, has_access):
        """
        Test for no access
        """
        has_access.return_value = False
        response = views.all_sequential_open_distrib(self.request,
                                                     'test/test/test')

        self.assertEqual(
            "{\"error\": \"Access Denied: User does not have access to this course\'s data\"}",
            response.content)

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_section_problem_grade_distribution_has_access(self, has_access):
        """
        Test returns proper value when have proper access
        """
        has_access.return_value = True
        response = views.section_problem_grade_distrib(self.request,
                                                       'test/test/test', '1')

        self.assertEqual(json.dumps(self.simple_data), response.content)

    @patch('class_dashboard.views.has_instructor_access_for_class')
    def test_section_problem_grade_distribution_no_access(self, has_access):
        """
        Test for no access
        """
        has_access.return_value = False
        response = views.section_problem_grade_distrib(self.request,
                                                       'test/test/test', '1')

        self.assertEqual(
            "{\"error\": \"Access Denied: User does not have access to this course\'s data\"}",
            response.content)

    def test_sending_deprecated_id(self):

        course = CourseFactory.create()
        instructor = AdminFactory.create()
        self.request.user = instructor

        response = views.all_sequential_open_distrib(self.request,
                                                     text_type(course.id))
        self.assertEqual('[]', response.content)

        response = views.all_problem_grade_distribution(
            self.request, text_type(course.id))
        self.assertEqual('[]', response.content)

        response = views.section_problem_grade_distrib(self.request,
                                                       text_type(course.id),
                                                       'no section')
        self.assertEqual('{"error": "error"}', response.content)
Example #36
0
 def setUp(self):
     factory = RequestFactory()
     self.request = factory.get(self.url)
     self.ajax_request = factory.get(self.url,
                                     HTTP_X_REQUESTED_WITH='XMLHttpRequest')
Example #37
0
class TestFirstRun(TestCase):
    def setUp(self):
        self.view = fx_views.FirstrunView.as_view()
        self.rf = RequestFactory()

    @override_settings(DEV=True)
    def test_fx_firstrun_40_0(self, render_mock):
        """Should use default firstrun template"""
        req = self.rf.get('/en-US/firefox/firstrun/')
        self.view(req, version='40.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/firstrun/index.html'])

    @override_settings(DEV=True)
    def test_fx_firstrun_56_0(self, render_mock):
        """Should use the default dev edition firstrun template"""
        req = self.rf.get('/en-US/firefox/firstrun/')
        self.view(req, version='56.0a2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/dev-firstrun.html'])

    @override_settings(DEV=True)
    def test_fxdev_firstrun_57_0(self, render_mock):
        """Should use 57 quantum dev edition firstrun template"""
        req = self.rf.get('/en-US/firefox/firstrun/')
        self.view(req, version='57.0a2')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/developer/firstrun.html'])

    @override_settings(DEV=True)
    def test_fx_firstrun_57_0(self, render_mock):
        """Should use 57 quantum firstrun template"""
        req = self.rf.get('/en-US/firefox/firstrun/')
        self.view(req, version='57.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/firstrun/firstrun-quantum.html'])

    # facebook container funnelcake - bug 1450106

    @override_settings(DEV=True)
    def test_fx_firstrun_fbcontainer(self, render_mock):
        """Should use facebook container template"""
        req = self.rf.get('/en-US/firefox/firstrun/?xv=facebook-container')
        self.view(req, version='59.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/firstrun/facebook-container.html'])

    @override_settings(DEV=True)
    def test_fx_firstrun_fbcontainer_non_enUS(self, render_mock):
        """Should use 57 quantum firstrun template for non en-US locales"""
        req = self.rf.get('/firefox/firstrun/?xv=facebook-container')
        req.locale = 'fr'
        self.view(req, version='59.0')
        template = render_mock.call_args[0][1]
        eq_(template, ['firefox/firstrun/firstrun-quantum.html'])

    # test redirect to /firefox/new/ for legacy /firstrun URLs - Bug 1343823

    @override_settings(DEV=True)
    def test_fx_firstrun_legacy_redirect(self, render_mock):
        req = self.rf.get('/firefox/firstrun/')
        req.locale = 'en-US'
        resp = self.view(req, version='39.0')
        assert resp.status_code == 301
        assert resp['location'].endswith('/firefox/new/')

    def test_fx_firstrun_dev_edition_legacy_redirect(self, render_mock):
        req = self.rf.get('/firefox/firstrun/')
        req.locale = 'en-US'
        resp = self.view(req, version='39.0a2')
        assert resp.status_code == 301
        assert resp['location'].endswith('/firefox/new/')
Example #38
0
 def setUp(self):
     factory = RequestFactory()
     self.request = factory.get('/')
     self.metadata = metadata(self.request)
Example #39
0
class TestFraudReport(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        with self.activate('en-US'):
            self.url = reverse('legal.fraud-report')

        self.data = {
            'input_url': 'http://www.test.com',
            'input_category': 'Charging for software',
            'input_product': 'Firefox',
            'input_specific_product': '',
            'input_details': 'test details',
            'input_attachment_desc': 'test attachment',
            'input_email': '*****@*****.**',
        }

    def tearDown(self):
        mail.outbox = []

    def test_view_post_valid_data(self):
        """
        A valid POST should 302 redirect.
        """

        request = self.factory.post(self.url, self.data)

        # make sure CSRF doesn't hold us up
        request._dont_enforce_csrf_checks = True

        response = legal_views.fraud_report(request)

        eq_(response.status_code, 302)
        eq_(response['Location'], '/en-US/about/legal/fraud-report/?submitted=True')

    def test_view_post_missing_data(self):
        """
        POST with missing data should return 200 and contain form
        errors in the template.
        """

        self.data.update(input_url='')  # remove required url

        request = self.factory.post(self.url, self.data)

        # make sure CSRF doesn't hold us up
        request._dont_enforce_csrf_checks = True

        response = legal_views.fraud_report(request)

        eq_(response.status_code, 200)
        self.assertIn('Please enter a URL.', response.content)

    def test_view_post_honeypot(self):
        """
        POST with honeypot text box filled should return 200 and
        contain general form error message.
        """

        self.data['office_fax'] = 'spammer'

        request = self.factory.post(self.url, self.data)

        # make sure CSRF doesn't hold us up
        request._dont_enforce_csrf_checks = True

        response = legal_views.fraud_report(request)

        eq_(response.status_code, 200)
        self.assertIn('An error has occurred', response.content)

    def test_form_valid_data(self):
        """
        Form should be valid.
        """
        form = FraudReportForm(self.data)

        # make sure form is valid
        ok_(form.is_valid())

    def test_form_invalid_data(self):
        """
        With incorrect data (missing url), form should not be valid and should
        have url in the errors hash.
        """
        self.data.update(input_url='')  # remove required url

        form = FraudReportForm(self.data)

        # make sure form is invalid
        eq_(False, form.is_valid())

        # make sure url errors are in form
        self.assertIn('input_url', form.errors)

    def test_form_honeypot(self):
        """
        Form with honeypot text box filled should not be valid.
        """
        self.data['office_fax'] = 'spammer!'

        form = FraudReportForm(self.data)

        eq_(False, form.is_valid())

    def test_form_valid_attachement(self):
        """
        Form should be valid when attachment under/at size limit.
        """
        # attachment within size limit
        mock_attachment = Mock(_size=legal_forms.FRAUD_REPORT_FILE_SIZE_LIMIT)

        form = FraudReportForm(self.data, {'input_attachment': mock_attachment})

        # make sure form is valid
        ok_(form.is_valid())

    def test_form_invalid_attachement(self):
        """
        Form should be invalid and contain attachment errors when attachment
        over size limit.
        """
        # attachment within size limit
        mock_attachment = Mock(
            _size=(legal_forms.FRAUD_REPORT_FILE_SIZE_LIMIT + 1))

        form = FraudReportForm(self.data, {'input_attachment': mock_attachment})

        # make sure form is not valid
        eq_(False, form.is_valid())

        # make sure attachment errors are in form
        self.assertIn('input_attachment', form.errors)

    @patch('bedrock.legal.views.jingo.render_to_string', return_value='jingo rendered')
    @patch('bedrock.legal.views.EmailMessage')
    def test_email(self, mock_email_message, mock_render_to_string):
        """
        Make sure email is sent with expected values.
        """
        mock_send = Mock()
        mock_email_message.return_value = Mock(send=mock_send)

        form = FraudReportForm(self.data)

        # submit form
        request = self.factory.get('/')
        submit_form(request, form)

        # make sure email was sent
        mock_send.assert_called_once_with()

        # make sure email values are correct
        mock_email_message.assert_called_once_with(
            legal_views.FRAUD_REPORT_EMAIL_SUBJECT,
            'jingo rendered',
            legal_views.FRAUD_REPORT_EMAIL_FROM,
            legal_views.FRAUD_REPORT_EMAIL_TO)

    @patch('bedrock.legal.views.jingo.render_to_string', return_value='jingo rendered')
    @patch('bedrock.legal.views.EmailMessage')
    def test_email_with_attachement(self, mock_email_message, mock_render_to_string):
        """
        Make sure email is sent with attachment.
        """
        mock_attachment = Mock(
            content_type='text/plain',
            _size=(legal_forms.FRAUD_REPORT_FILE_SIZE_LIMIT))

        # make sure name attribute is treated as string
        mock_attachment.name = 'img.jpg'

        form = FraudReportForm(self.data, {'input_attachment': mock_attachment})

        # submit form
        request = self.factory.get('/')
        submit_form(request, form)

        # make sure attachment was attached
        mock_email_message.return_value.attach.assert_called_once_with(
            'img.jpg',
            mock_attachment.read.return_value,
            'text/plain')

        mock_attachment.read.assert_called_once_with()

        # make sure email was sent
        mock_email_message.return_value.send.assert_called_once_with()

        # make sure email values are correct
        mock_email_message.assert_called_once_with(
            legal_views.FRAUD_REPORT_EMAIL_SUBJECT,
            'jingo rendered',
            legal_views.FRAUD_REPORT_EMAIL_FROM,
            legal_views.FRAUD_REPORT_EMAIL_TO)

    def test_emails_not_escaped(self):
        """
        Strings in the fraud report form should not be HTML escaped
        when inserted into the email, which is just text.

        E.g. if they entered

            J'adore le ''Renard de feu''

        the email should not contain

            J&#39;adore le &#39;&#39;Renard de feu&#39;&#39;

        Tags are still stripped, though.
        """

        STRING1 = u"<em>J'adore Citröns</em> & <Piñatas> so there"
        EXPECTED1 = u"J'adore Citröns &  so there"

        STRING2 = u"<em>J'adore Piñatas</em> & <fromage> so here"
        EXPECTED2 = u"J'adore Piñatas &  so here"

        STRING3 = u"J'adore <coffee>el café</coffee> también"
        EXPECTED3 = u"J'adore el café también"

        self.data.update(input_specific_product=STRING1, input_details=STRING2,
                         input_attachment_desc=STRING3)
        request = self.factory.post(self.url, self.data)

        # make sure CSRF doesn't hold us up
        request._dont_enforce_csrf_checks = True

        legal_views.fraud_report(request)

        eq_(len(mail.outbox), 1)

        m = mail.outbox[0]

        self.assertIn(EXPECTED1, m.body)
        self.assertIn(EXPECTED2, m.body)
        self.assertIn(EXPECTED3, m.body)
Example #40
0
class MailFormViewTest(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def test_dispatch_unknown_mail(self):
        request = self.factory.get(
            reverse('mail_factory_form', kwargs={'mail_name': 'unknown'}))
        view = views.MailFormView()
        with self.assertRaises(Http404):
            view.dispatch(request, 'unknown')

    def test_dispatch(self):
        request = self.factory.post(
            reverse('mail_factory_form', kwargs={'mail_name': 'no_custom'}), {
                'raw': 'foo',
                'send': 'foo',
                'email': 'email'
            })
        view = views.MailFormView()
        view.request = request
        view.dispatch(request, 'no_custom')
        self.assertEqual(view.mail_name, 'no_custom')
        self.assertEqual(view.mail_class, factory._registry['no_custom'])
        self.assertTrue(view.raw)
        self.assertTrue(view.send)
        self.assertEqual(view.email, 'email')

    def test_get_form_kwargs(self):
        request = self.factory.get(
            reverse('mail_factory_form', kwargs={'mail_name': 'unknown'}))
        view = views.MailFormView()
        view.mail_name = 'no_custom'
        view.mail_class = factory._registry['no_custom']
        view.request = request
        self.assertIn('mail_class', view.get_form_kwargs())
        self.assertEqual(view.get_form_kwargs()['mail_class'].__name__,
                         'NoCustomMail')

    def test_get_form_class(self):
        view = views.MailFormView()
        view.mail_name = 'no_custom'
        self.assertEqual(view.get_form_class(), MailForm)

    def test_form_valid_raw(self):
        class MockForm(object):
            cleaned_data = {'title': 'title', 'content': 'content'}

        view = views.MailFormView()
        view.mail_name = 'no_custom'
        view.raw = True
        response = view.form_valid(MockForm())
        self.assertEqual(response.status_code, 200)
        self.assertTrue(isinstance(response, HttpResponse))
        self.assertTrue(response.content.startswith(b'<pre>'))

    def test_form_valid_send(self):
        class MockForm(object):
            cleaned_data = {'title': 'title', 'content': 'content'}

        request = self.factory.get(
            reverse('mail_factory_form', kwargs={'mail_name': 'unknown'}))
        view = views.MailFormView()
        view.request = request
        view.mail_name = 'no_custom'
        view.raw = False
        view.send = True
        view.email = '*****@*****.**'
        old_factory_mail = factory.mail  # save current mail method
        # save current django.contrib.messages.success (imported in .views)
        old_messages_success = views.messages.success
        self.factory_send_called = False

        def mock_factory_mail(mail_name, to, context):
            self.factory_send_called = True  # noqa

        factory.mail = mock_factory_mail  # mock mail method
        views.messages.success = lambda x, y: True  # mock messages.success
        response = view.form_valid(MockForm())
        factory.mail = old_factory_mail  # restore mail method
        views.messages.success = old_messages_success  # restore messages
        self.assertTrue(self.factory_send_called)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['location'], reverse('mail_factory_list'))

    def test_form_valid_html(self):
        class MockForm(object):
            cleaned_data = {'title': 'title', 'content': 'content'}

            def get_context_data(self):
                return self.cleaned_data

        view = views.MailFormView()
        view.mail_name = 'custom_form'  # has templates for html alternative
        view.raw = False
        view.send = False
        response = view.form_valid(MockForm())
        self.assertEqual(response.status_code, 200)
        self.assertTrue(isinstance(response, HttpResponse))

    def test_get_context_data(self):
        request = self.factory.get(
            reverse('mail_factory_form', kwargs={'mail_name': 'unknown'}))
        view = views.MailFormView()
        view.mail_name = 'no_custom'
        view.mail_class = factory._registry['no_custom']
        view.request = request
        # save the current
        old_get_mail_preview = views.MailPreviewMixin.get_mail_preview
        # mock
        views.MailPreviewMixin.get_mail_preview = lambda x, y, z: 'mocked'
        data = view.get_context_data()
        # restore after mock
        views.MailPreviewMixin.get_mail_preview = old_get_mail_preview
        self.assertIn('mail_name', data)
        self.assertEqual(data['mail_name'], 'no_custom')
        self.assertIn('preview_messages', data)
        self.assertDictEqual(data['preview_messages'], {
            'fr': 'mocked',
            'en': 'mocked'
        })
Example #41
0
class TestRNAViews(TestCase):
    def setUp(self):
        self.factory = RequestFactory()
        self.request = self.factory.get('/')

        self.render_patch = patch(
            'bedrock.releasenotes.views.l10n_utils.render')
        self.mock_render = self.render_patch.start()
        self.mock_render.return_value.has_header.return_value = False

    def tearDown(self):
        self.render_patch.stop()

    @property
    def last_ctx(self):
        """
        Convenient way to access the context of the last rendered
        response.
        """
        return self.mock_render.call_args[0][2]

    @patch('bedrock.releasenotes.views.get_object_or_404')
    @patch('bedrock.releasenotes.views.Q')
    def test_get_release_or_404(self, Q, get_object_or_404):
        eq_(views.get_release_or_404('version', 'product'),
            get_object_or_404.return_value)
        get_object_or_404.assert_called_with(Release,
                                             Q.return_value,
                                             version='version')
        Q.assert_called_once_with(product='product')

    @patch('bedrock.releasenotes.views.get_object_or_404')
    @patch('bedrock.releasenotes.views.Q')
    def test_get_release_or_404_esr(self, Q, get_object_or_404):
        eq_(views.get_release_or_404('24.5.0', 'Firefox'),
            get_object_or_404.return_value)
        Q.assert_any_call(product='Firefox')
        Q.assert_any_call(product='Firefox Extended Support Release')

    @patch('bedrock.releasenotes.views.get_object_or_404')
    @patch('bedrock.releasenotes.views.Q')
    def test_get_release_or_404_endswith_esr(self, Q, get_object_or_404):
        eq_(views.get_release_or_404('45.0esr', 'Firefox'),
            get_object_or_404.return_value)
        Q.assert_any_call(product='Firefox')
        Q.assert_any_call(product='Firefox Extended Support Release')

    @override_settings(DEV=False)
    @patch('bedrock.releasenotes.views.release_notes_template')
    @patch('bedrock.releasenotes.views.get_release_or_404')
    @patch('bedrock.releasenotes.views.equivalent_release_url')
    def test_release_notes(self, mock_equiv_rel_url, get_release_or_404,
                           mock_release_notes_template):
        """
        Should use release returned from get_release_or_404 with the
        correct params and pass the correct context variables and
        template to l10n_utils.render.
        """
        mock_release = get_release_or_404.return_value
        mock_release.major_version.return_value = '34'
        mock_release.notes.return_value = ([Release(id=1),
                                            Release(id=2)],
                                           [Release(id=3),
                                            Release(id=4)])

        views.release_notes(self.request, '27.0')
        get_release_or_404.assert_called_with('27.0', 'Firefox')
        mock_release.notes.assert_called_with(public_only=True)
        eq_(self.last_ctx['version'], '27.0')
        eq_(self.last_ctx['release'], mock_release)
        eq_(self.last_ctx['new_features'], [Release(id=1), Release(id=2)])
        eq_(self.last_ctx['known_issues'], [Release(id=3), Release(id=4)])
        eq_(self.mock_render.call_args[0][1],
            mock_release_notes_template.return_value)
        mock_equiv_rel_url.assert_called_with(mock_release)
        mock_release_notes_template.assert_called_with(mock_release.channel,
                                                       'Firefox', 34)

    @patch('bedrock.releasenotes.views.get_release_or_404')
    @patch('bedrock.releasenotes.views.releasenotes_url')
    def test_release_notes_beta_redirect(self, releasenotes_url,
                                         get_release_or_404):
        """
        Should redirect to url for beta release
        """
        get_release_or_404.side_effect = [Http404, 'mock release']
        releasenotes_url.return_value = '/firefox/27.0beta/releasenotes/'
        response = views.release_notes(self.request, '27.0')
        eq_(response.status_code, 302)
        eq_(response['location'], '/firefox/27.0beta/releasenotes/')
        get_release_or_404.assert_called_with('27.0beta', 'Firefox')
        releasenotes_url.assert_called_with('mock release')

    @patch('bedrock.releasenotes.views.get_release_or_404')
    def test_system_requirements(self, get_release_or_404):
        """
        Should use release returned from get_release_or_404, with a
        default channel of Release and default product of Firefox,
        and pass the version to l10n_utils.render
        """
        views.system_requirements(self.request, '27.0.1')
        get_release_or_404.assert_called_with('27.0.1', 'Firefox')
        eq_(self.last_ctx['release'], get_release_or_404.return_value)
        eq_(self.last_ctx['version'], '27.0.1')
        eq_(self.mock_render.call_args[0][1],
            'firefox/releases/system_requirements.html')

    def test_release_notes_template(self):
        """
        Should return correct template name based on channel
        and product
        """
        eq_(views.release_notes_template('Nightly', 'Firefox'),
            'firefox/releases/nightly-notes.html')
        eq_(views.release_notes_template('Aurora', 'Firefox'),
            'firefox/releases/aurora-notes.html')
        eq_(views.release_notes_template('Aurora', 'Firefox', 35),
            'firefox/releases/dev-browser-notes.html')
        eq_(views.release_notes_template('Aurora', 'Firefox', 34),
            'firefox/releases/aurora-notes.html')
        eq_(views.release_notes_template('Beta', 'Firefox'),
            'firefox/releases/beta-notes.html')
        eq_(views.release_notes_template('Release', 'Firefox'),
            'firefox/releases/release-notes.html')
        eq_(views.release_notes_template('ESR', 'Firefox'),
            'firefox/releases/esr-notes.html')
        eq_(views.release_notes_template('Release', 'Thunderbird'),
            'thunderbird/releases/release-notes.html')
        eq_(views.release_notes_template('Beta', 'Thunderbird'),
            'thunderbird/releases/beta-notes.html')
        eq_(views.release_notes_template('', ''),
            'firefox/releases/release-notes.html')

    @override_settings(DEV=False)
    @patch('bedrock.releasenotes.views.get_object_or_404')
    def test_non_public_release(self, get_object_or_404):
        """
        Should raise 404 if not release.is_public and not settings.DEV
        """
        get_object_or_404.return_value = Release(is_public=False)
        with self.assertRaises(Http404):
            views.get_release_or_404('42', 'Firefox')

    @patch('bedrock.releasenotes.views.releasenotes_url')
    def test_no_equivalent_release_url(self, mock_releasenotes_url):
        """
        Should return None without calling releasenotes_url
        """
        release = Mock()
        release.equivalent_android_release.return_value = None
        release.equivalent_desktop_release.return_value = None
        eq_(views.equivalent_release_url(release), None)
        eq_(mock_releasenotes_url.called, 0)

    @patch('bedrock.releasenotes.views.releasenotes_url')
    def test_android_equivalent_release_url(self, mock_releasenotes_url):
        """
        Should return the url for the equivalent android release
        """
        release = Mock()
        eq_(views.equivalent_release_url(release),
            mock_releasenotes_url.return_value)
        mock_releasenotes_url.assert_called_with(
            release.equivalent_android_release.return_value)

    @patch('bedrock.releasenotes.views.releasenotes_url')
    def test_desktop_equivalent_release_url(self, mock_releasenotes_url):
        """
        Should return the url for the equivalent desktop release
        """
        release = Mock()
        release.equivalent_android_release.return_value = None
        eq_(views.equivalent_release_url(release),
            mock_releasenotes_url.return_value)
        mock_releasenotes_url.assert_called_with(
            release.equivalent_desktop_release.return_value)

    @patch('bedrock.releasenotes.views.android_builds')
    def test_get_download_url_android(self, mock_android_builds):
        """
        Shoud return the download link for the release.channel from
        android_builds
        """
        mock_android_builds.return_value = [{'download_link': '/download'}]
        release = Mock(product='Firefox for Android')
        link = views.get_download_url(release)
        eq_(link, '/download')
        mock_android_builds.assert_called_with(release.channel)

    def test_get_download_url_thunderbird(self):
        release = Mock(product='Thunderbird')
        link = views.get_download_url(release)
        eq_(link, '/en-US/thunderbird/')

    def test_get_download_url_thunderbird_beta(self):
        release = Mock(product='Thunderbird', channel='Beta')
        link = views.get_download_url(release)
        eq_(link, '/en-US/thunderbird/channel/')

    def test_check_url(self):
        eq_(
            views.check_url('Firefox for Android', '45.0'),
            'https://support.mozilla.org/kb/will-firefox-work-my-mobile-device'
        )
        eq_(views.check_url('Firefox for Android', '46.0'),
            '/en-US/firefox/android/46.0/system-requirements/')
        eq_(views.check_url('Firefox for iOS', '1.4'),
            '/en-US/firefox/ios/1.4/system-requirements/')
        eq_(views.check_url('Firefox', '42.0'),
            '/en-US/firefox/42.0/system-requirements/')
Example #42
0
class TestViews(TestCase):
    @override_settings(DEBUG=True)
    def test_login(self):
        """
        Login and logout
        """
        user = UserFactory()
        login_url = reverse('dashboard:login')
        response = self.client.post(login_url,
                                    data={
                                        'user': user.email,
                                        'password': user.password
                                    })
        self.assertEqual(response.status_code, 302)
        logout_url = reverse('dashboard:logout_start')
        response = self.client.get(logout_url)
        self.assertEqual(response.status_code, 302)

    def test_report(self):
        """
        Though dashboard.views.report is a view for test_api, it should be tested
        because a change here it could affect another test module
        """
        self.factory = RequestFactory()
        # site_id: 1
        # event_source_all
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'event_source_all'
                                   })
        response = views.reports(request)
        json_response = '[{"clicks": 1234, "shares": 3000, "label": "googlePlus"}, ' \
                        '{"clicks": 650, "shares": 12300, "label": "facebook"}, ' \
                        '{"clicks": 123, "shares": 1456, "label": "twitter"}, ' \
                        '{"clicks": 12, "shares": 102, "label": "pinterest"}, ' \
                        '{"clicks": 345, "shares": 2345, "label": "linkedin"}, ' \
                        '{"clicks": 5, "shares": 45, "label": "other"}]'
        self.assertEqual(response.content, json_response)
        # event_tool_all
        self.factory = RequestFactory()
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'event_tool_all'
                                   })
        response = views.reports(request)
        json_response = '[{"clicks": 123, "shares": 2345, "label": "copy-paste"}, ' \
                        '{"clicks": 1234, "shares": 5432, "label": "sharing-buttons"}, ' \
                        '{"clicks": 12, "shares": 878, "label": "address-bar"}]'
        self.assertEqual(response.content, json_response)
        # event_month
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'event_month'
                                   })
        response = views.reports(request)
        json_response = '[{"clicks": 234, "shares": 134, "month": 1401}, ' \
                        '{"clicks": 256, "shares": 178, "month": 1402}, ' \
                        '{"clicks": 345, "shares": 190, "month": 1403}, ' \
                        '{"clicks": 456, "shares": 185, "month": 1404}, ' \
                        '{"clicks": 256, "shares": 155, "month": 1405}, ' \
                        '{"clicks": 700, "shares": 256, "month": 1406}, ' \
                        '{"clicks": 987, "shares": 356, "month": 1407}, ' \
                        '{"clicks": 1056, "shares": 98, "month": 1408}, ' \
                        '{"clicks": 965, "shares": 15, "month": 1409}, ' \
                        '{"clicks": 865, "shares": 5, "month": 1410}, ' \
                        '{"clicks": 545, "shares": 1, "month": 1411}, ' \
                        '{"clicks": 325, "shares": 10, "month": 1412}, ' \
                        '{"clicks": 487, "shares": 0, "month": 1501}, ' \
                        '{"clicks": 65, "shares": 5, "month": 1502}]'
        self.assertEqual(response.content, json_response)
        # event_url_all
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'event_url_all'
                                   })

        response = views.reports(request)
        json_response = '[{"url": "http://gravity4.com/contact/", ' \
                        '"clicks": 2343, "shares": 1343, "title": "Contact"}, ' \
                        '{"url": "http://gravity4.com/g4team/", "clicks": 234, ' \
                        '"shares": 345, "title": "Team"}, ' \
                        '{"url": "http://gravity4.com/labs/", "clicks": 334, ' \
                        '"shares": 675, "title": "Labs"}, ' \
                        '{"url": "http://gravity4.com/app-center/", ' \
                        '"clicks": 6334, "shares": 4675, ' \
                        '"title": "App Center"}, ' \
                        '{"url": "http://gravity4.com/product/", ' \
                        '"clicks": 12334, "shares": 8675, ' \
                        '"title": "Product"}, ' \
                        '{"url": "http://gravity4.com/vision/", ' \
                        '"clicks": 334, "shares": 675, "title": "Vision"}, ' \
                        '{"url": "http://gravity4.com/blog/introducing-belimitless/", ' \
                        '"clicks": 7834, "shares": 1275, ' \
                        '"title": "Introducing #Belimitless"}, ' \
                        '{"url": "http://gravity4.com/blog/tom-brady-super-bowl-sunday-doesnt-rely-on-luck-why-do-you/", ' \
                        '"clicks": 3334, "shares": 7512, ' \
                        '"title": "Tom Brady Doesn\'t Rely on Luck. Why Do You?"}, ' \
                        '{"url": "http://gravity4.com/blog/imagination-by-gravity4/", ' \
                        '"clicks": 8753, "shares": 7125, "title": "Imagination by Gravity4"}, ' \
                        '{"url": "http://gravity4.com/blog/ibeacon/", "clicks": 33124, ' \
                        '"shares": 23675, "title": "iBeacon. Shop Smarter"}, ' \
                        '{"url": "http://gravity4.com/blog/g4labs/", ' \
                        '"clicks": 3334, "shares": 1675, ' \
                        '"title": "Introducing, Gravity4 Labs."}, ' \
                        '{"url": "http://gravity4.com/opt-out/", ' \
                        '"clicks": 0, "shares": 0, "title": "Opt-out"}]'
        self.assertEqual(response.content, json_response)
        # referring_domains
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'referring_domains'
                                   })
        response = views.reports(request)
        json_response = '[{"url": "http://addnow.com/2014/09/piwik-piwik-pro-trustradius-buyers-guide/", ' \
                        '"shares": 58}, {"url": "http://addnow.com/2014/10/clearcode-featured-agency-post/", ' \
                        '"shares": 11273}, ' \
                        '{"url": "http://addnow.com/2014/07/target-engaged-customers/", ' \
                        '"shares": 3235}, ' \
                        '{"url": "http://addnow.com/2014/07/rejoiner-ecommerce-solution-cart-abandonment/", ' \
                        '"shares": 612}, ' \
                        '{"url": "http://addnow.com/2014/08/hire-right-app-developers/", ' \
                        '"shares": 23}, {"url": "http://addnow.com/2014/12/agile-vs-waterfall-method/", ' \
                        '"shares": 725}, {"url": "http://addnow.com/2014/12/importance-of-branding-ux-ui-software-development/", ' \
                        '"shares": 8236}, {"url": "http://addnow.com/2014/10/programmers/", "shares": 826}, ' \
                        '{"url": "http://addnow.com/2014/10/hiring-process/", "shares": 269}, ' \
                        '{"url": "http://addnow.com/2014/09/computers/", "shares": 1252}]'
        self.assertEqual(response.content, json_response)
        # referring_searches
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'referring_searches'
                                   })
        response = views.reports(request)
        json_response = '[{"searches": 58, "query": "Development"}, ' \
                        '{"searches": 612, "query": "Clearcode"}, ' \
                        '{"searches": 23, "query": "Software House"}, ' \
                        '{"searches": 11273, "query": "Interactive agency"}, ' \
                        '{"searches": 3235, "query": "Carrer in IT"}, ' \
                        '{"searches": 8236, "query": "PHP Developer"}, ' \
                        '{"searches": 725, "query": "Programming"}, ' \
                        '{"searches": 8236, "query": "PHP Developer"}, ' \
                        '{"searches": 826, "query": "SEO"}, ' \
                        '{"searches": 269, "query": "UX Design"}, ' \
                        '{"searches": 1252, "query": "Continuos integration"}]'
        self.assertEqual(response.content, json_response)
        # copied_keywords
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'copied_keywords'
                                   })

        response = views.reports(request)
        json_response = '[{"keywords": "Development", "times": 58}, ' \
                        '{"keywords": "Interactive agency", "times": 11273}, ' \
                        '{"keywords": "Carrer in IT", "times": 3235}, ' \
                        '{"keywords": "Coding service", "times": 612}, ' \
                        '{"keywords": "Software House", "times": 23}, ' \
                        '{"keywords": "Programming", "times": 725}, ' \
                        '{"keywords": "PHP Developer", "times": 8236}, ' \
                        '{"keywords": "SEO", "times": 826}, ' \
                        '{"keywords": "UX Design", "times": 269}, ' \
                        '{"keywords": "Continuos integration", "times": 1252}]'
        self.assertEqual(response.content, json_response)
        # top_countries
        request = self.factory.get('report',
                                   data={
                                       'site_id': 1,
                                       'collection': 'top_countries'
                                   })
        response = views.reports(request)
        json_response = '[{"id": "NZ", "viral": 2, "clicks": 826, ' \
                        '"shares": 58, "country": "New Zealand"}, ' \
                        '{"id": "US", "viral": 62, "clicks": 25273, ' \
                        '"shares": 11273, "country": "United States"}, ' \
                        '{"id": "AU", "viral": 9, "clicks": 10264, ' \
                        '"shares": 3235, "country": "Australia"}, ' \
                        '{"id": "UK", "viral": 5, "clicks": 2746, ' \
                        '"shares": 612, "country": "United Kingdom"}, ' \
                        '{"id": "UK", "viral": 1, "clicks": 127, ' \
                        '"shares": 23, "country": "United Kingdom"}, ' \
                        '{"id": "BR", "viral": 7, "clicks": 5273, ' \
                        '"shares": 725, "country": "Brazil"}, ' \
                        '{"id": "CA", "viral": 21, "clicks": 17274, ' \
                        '"shares": 8236, "country": "Canada"}, ' \
                        '{"id": "AR", "viral": 3, "clicks": 1742, ' \
                        '"shares": 826, "country": "Argentina"}, ' \
                        '{"id": "MX", "viral": 4, "clicks": 742, ' \
                        '"shares": 269, "country": "Mexico"}, ' \
                        '{"id": "IN", "viral": 12, "clicks": 4242, ' \
                        '"shares": 1252, "country": "India"}]'
        self.assertEqual(response.content, json_response)
        # the same but for site_id=2
        # event_source_all
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'event_source_all'
                                   })

        response = views.reports(request)
        json_response = '[{"clicks": 34, "shares": 789, "label": "googlePlus"}, ' \
                        '{"clicks": 206, "shares": 1200, "label": "facebook"}, ' \
                        '{"clicks": 93, "shares": 543, "label": "twitter"}, ' \
                        '{"clicks": 57, "shares": 123, "label": "pinterest"}, ' \
                        '{"clicks": 38, "shares": 235, "label": "linkedin"}, ' \
                        '{"clicks": 0, "shares": 5, "label": "other"}]'
        self.assertEqual(response.content, json_response)
        # event_tool_all
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'event_tool_all'
                                   })

        response = views.reports(request)
        json_response = '[{"clicks": 765, "shares": 345, "label": "copy-paste"}, ' \
                        '{"clicks": 871, "shares": 45, "label": "sharing-buttons"}, ' \
                        '{"clicks": 91, "shares": 5, "label": "address-bar"}]'
        self.assertEqual(response.content, json_response)
        # event_month
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'event_month'
                                   })

        response = views.reports(request)
        json_response = '[{"clicks": 34, "shares": 13, "month": 1401}, ' \
                        '{"clicks": 56, "shares": 17, "month": 1402}, ' \
                        '{"clicks": 45, "shares": 19, "month": 1403}, ' \
                        '{"clicks": 56, "shares": 18, "month": 1404}, ' \
                        '{"clicks": 56, "shares": 15, "month": 1405}, ' \
                        '{"clicks": 30, "shares": 25, "month": 1406}, ' \
                        '{"clicks": 87, "shares": 35, "month": 1407}, ' \
                        '{"clicks": 56, "shares": 98, "month": 1408}, ' \
                        '{"clicks": 65, "shares": 1, "month": 1409}, ' \
                        '{"clicks": 65, "shares": 5, "month": 1410}, ' \
                        '{"clicks": 45, "shares": 1, "month": 1411}, ' \
                        '{"clicks": 25, "shares": 1, "month": 1412}, ' \
                        '{"clicks": 87, "shares": 0, "month": 1501}, ' \
                        '{"clicks": 5, "shares": 5, "month": 1502}]'
        self.assertEqual(response.content, json_response)
        # event_url_all
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'event_url_all'
                                   })

        response = views.reports(request)
        json_response = '[{"url": "http://demo.com/contact/", "clicks": 343, "shares": 343, "title": "Contact"}, ' \
                        '{"url": "http://demo.com/team/", "clicks": 234, "shares": 345, "title": "Team"}, ' \
                        '{"url": "http://demo.com/labs/", "clicks": 34, "shares": 75, "title": "Labs"}, ' \
                        '{"url": "http://demo.com/pricing/", "clicks": 633, "shares": 467, "title": "Pricing"}, ' \
                        '{"url": "http://demo.com/product/", "clicks": 34, "shares": 675, "title": "Product"}, ' \
                        '{"url": "http://demo.com/vision/", "clicks": 34, "shares": 75, "title": "Vision"}, ' \
                        '{"url": "http://demo.com/blog/title1/", "clicks": 834, "shares": 275, "title": "Title 1"}, ' \
                        '{"url": "http://demo.com/blog/title2/", "clicks": 34, "shares": 12, "title": "Tile 2"}, ' \
                        '{"url": "http://demo.com/blog/title3/", "clicks": 53, "shares": 25, "title": "Title 3"}, ' \
                        '{"url": "http://demo.com/blog/title4/", "clicks": 3324, "shares": 2375, "title": "Title 4"}, ' \
                        '{"url": "http://demo.com/blog/title4/", "clicks": 334, "shares": 675, "title": "Title 5"}, ' \
                        '{"url": "http://demo.com/opt-out/", "clicks": 0, "shares": 0, "title": "Opt-out"}]'
        self.assertEqual(response.content, json_response)
        # referring_domains
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'referring_domains'
                                   })

        response = views.reports(request)
        json_response = '[{"url": "http://addnow.com/2014/09/piwik-piwik-pro-trustradius-buyers-guide/", "shares": 581}, ' \
                        '{"url": "http://addnow.com/2014/10/clearcode-featured-agency-post/", "shares": 1273}, ' \
                        '{"url": "http://addnow.com/2014/07/target-engaged-customers/", "shares": 335}, ' \
                        '{"url": "http://addnow.com/2014/07/rejoiner-ecommerce-solution-cart-abandonment/", "shares": 1612}, ' \
                        '{"url": "http://addnow.com/2014/08/hire-right-app-developers/", "shares": 223}, ' \
                        '{"url": "http://addnow.com/2014/12/agile-vs-waterfall-method/", "shares": 75}, ' \
                        '{"url": "http://addnow.com/2014/12/importance-of-branding-ux-ui-software-development/", "shares": 836}, ' \
                        '{"url": "http://addnow.com/2014/10/programmers/", "shares": 8426}, ' \
                        '{"url": "http://addnow.com/2014/10/hiring-process/", "shares": 2619}, ' \
                        '{"url": "http://addnow.com/2014/09/computers/", "shares": 12}]'
        self.assertEqual(response.content, json_response)
        # referring_searches
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'referring_searches'
                                   })

        response = views.reports(request)
        json_response = '[{"searches": 158, "query": "Development"}, ' \
                        '{"searches": 2612, "query": "Clearcode"}, ' \
                        '{"searches": 230, "query": "Software House"}, ' \
                        '{"searches": 1273, "query": "Interactive agency"}, ' \
                        '{"searches": 13235, "query": "Carrer in IT"}, ' \
                        '{"searches": 823, "query": "PHP Developer"}, ' \
                        '{"searches": 1725, "query": "Programming"}, ' \
                        '{"searches": 836, "query": "PHP Developer"}, ' \
                        '{"searches": 8426, "query": "SEO"}, ' \
                        '{"searches": 2619, "query": "UX Design"}, ' \
                        '{"searches": 12, "query": "Continuos integration"}]'
        self.assertEqual(response.content, json_response)
        # copied_keywords
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'copied_keywords'
                                   })
        response = views.reports(request)
        json_response = '[{"keywords": "Development", "times": 581}, ' \
                        '{"keywords": "Interactive agency", "times": 1273}, ' \
                        '{"keywords": "Carrer in IT", "times": 335}, ' \
                        '{"keywords": "Coding service", "times": 1612}, ' \
                        '{"keywords": "Software House", "times": 223}, ' \
                        '{"keywords": "Programming", "times": 75}, ' \
                        '{"keywords": "PHP Developer", "times": 836}, ' \
                        '{"keywords": "SEO", "times": 8426}, ' \
                        '{"keywords": "UX Design", "times": 2619}, ' \
                        '{"keywords": "Continuos integration", "times": 12}]'
        self.assertEqual(response.content, json_response)
        # top_countries
        request = self.factory.get('report',
                                   data={
                                       'site_id': 2,
                                       'collection': 'top_countries'
                                   })

        response = views.reports(request)
        json_response = '[{"id": "NZ", "viral": 3, "clicks": 2826, "shares": 581, "country": "New Zealand"}, ' \
                        '{"id": "US", "viral": 26, "clicks": 5273, "shares": 1273, "country": "United States"}, ' \
                        '{"id": "AU", "viral": 11, "clicks": 1264, "shares": 335, "country": "Australia"}, ' \
                        '{"id": "UK", "viral": 5, "clicks": 2746, "shares": 1612, "country": "United Kingdom"}, ' \
                        '{"id": "UK", "viral": 1, "clicks": 1127, "shares": 223, "country": "United Kingdom"}, ' \
                        '{"id": "BR", "viral": 7, "clicks": 273, "shares": 75, "country": "Brazil"}, ' \
                        '{"id": "CA", "viral": 21, "clicks": 1274, "shares": 836, "country": "Canada"}, ' \
                        '{"id": "AR", "viral": 3, "clicks": 11742, "shares": 8326, "country": "Argentina"}, ' \
                        '{"id": "MX", "viral": 4, "clicks": 6742, "shares": 2619, "country": "Mexico"}, ' \
                        '{"id": "IN", "viral": 12, "clicks": 242, "shares": 12, "country": "India"}]'
        self.assertEqual(response.content, json_response)
Example #43
0
class SubmitFeedbackTest(EnterpriseServiceMockMixin, TestCase):
    """
    Class to test the submit_feedback function in views.
    """
    def setUp(self):
        """Set up data for the test case"""
        super(SubmitFeedbackTest, self).setUp()
        self._request_factory = RequestFactory()
        self._anon_user = AnonymousUser()
        self._auth_user = UserFactory.create(
            email="*****@*****.**",
            username="******",
            profile__name="Test User"
        )
        self._anon_fields = {
            "email": "*****@*****.**",
            "name": "Test User",
            "subject": "a subject",
            "details": "some details",
            "issue_type": "test_issue"
        }
        # This does not contain issue_type nor course_id to ensure that they are optional
        self._auth_fields = {"subject": "a subject", "details": "some details"}

        # Create a service user, because the track selection page depends on it
        UserFactory.create(
            username='******',
            email="*****@*****.**",
            password="******",
        )

    def _build_and_run_request(self, user, fields):
        """
        Generate a request and invoke the view, returning the response.

        The request will be a POST request from the given `user`, with the given
        `fields` in the POST body.
        """
        req = self._request_factory.post(
            "/submit_feedback",
            data=fields,
            HTTP_REFERER=TEST_REQUEST_HEADERS["HTTP_REFERER"],
            HTTP_USER_AGENT=TEST_REQUEST_HEADERS["HTTP_USER_AGENT"],
            REMOTE_ADDR=TEST_REQUEST_HEADERS["REMOTE_ADDR"],
            SERVER_NAME=TEST_REQUEST_HEADERS["SERVER_NAME"],
        )
        req.site = SiteFactory.create()
        req.user = user
        return views.submit_feedback(req)

    def _assert_bad_request(self, response, field, zendesk_mock_class, datadog_mock):
        """
        Assert that the given `response` contains correct failure data.

        It should have a 400 status code, and its content should be a JSON
        object containing the specified `field` and an `error`.
        """
        self.assertEqual(response.status_code, 400)
        resp_json = json.loads(response.content)
        self.assertIn("field", resp_json)
        self.assertEqual(resp_json["field"], field)
        self.assertIn("error", resp_json)
        # There should be absolutely no interaction with Zendesk
        self.assertFalse(zendesk_mock_class.return_value.mock_calls)
        self.assertFalse(datadog_mock.mock_calls)

    def _test_bad_request_omit_field(self, user, fields, omit_field, zendesk_mock_class, datadog_mock):
        """
        Invoke the view with a request missing a field and assert correctness.

        The request will be a POST request from the given `user`, with POST
        fields taken from `fields` minus the entry specified by `omit_field`.
        The response should have a 400 (bad request) status code and specify
        the invalid field and an error message, and the Zendesk API should not
        have been invoked.
        """
        filtered_fields = {k: v for (k, v) in fields.items() if k != omit_field}
        resp = self._build_and_run_request(user, filtered_fields)
        self._assert_bad_request(resp, omit_field, zendesk_mock_class, datadog_mock)

    def _test_bad_request_empty_field(self, user, fields, empty_field, zendesk_mock_class, datadog_mock):
        """
        Invoke the view with an empty field and assert correctness.

        The request will be a POST request from the given `user`, with POST
        fields taken from `fields`, replacing the entry specified by
        `empty_field` with the empty string. The response should have a 400
        (bad request) status code and specify the invalid field and an error
        message, and the Zendesk API should not have been invoked.
        """
        altered_fields = fields.copy()
        altered_fields[empty_field] = ""
        resp = self._build_and_run_request(user, altered_fields)
        self._assert_bad_request(resp, empty_field, zendesk_mock_class, datadog_mock)

    def _test_success(self, user, fields):
        """
        Generate a request, invoke the view, and assert success.

        The request will be a POST request from the given `user`, with the given
        `fields` in the POST body. The response should have a 200 (success)
        status code.
        """
        resp = self._build_and_run_request(user, fields)
        self.assertEqual(resp.status_code, 200)

    def _build_zendesk_ticket(self, recipient, name, email, subject, details, tags, custom_fields=None):
        """
        Build a Zendesk ticket that can be used in assertions to verify that the correct
        data was submitted to create a Zendesk ticket.
        """
        ticket = {
            "ticket": {
                "recipient": recipient,
                "requester": {"name": name, "email": email},
                "subject": subject,
                "comment": {"body": details},
                "tags": tags
            }
        }

        if custom_fields is not None:
            ticket["ticket"]["custom_fields"] = custom_fields

        return ticket

    def _build_zendesk_ticket_update(self, request_headers, username=None):
        """
        Build a Zendesk ticket update that can be used in assertions to verify that the correct
        data was submitted to update a Zendesk ticket.
        """
        body = []
        if username:
            body.append("username: {}".format(username))

        # FIXME the tests rely on the body string being built in this specific order, which doesn't seem
        # reliable given that the view builds the string by iterating over a dictionary.
        header_text_mapping = [
            ("Client IP", "REMOTE_ADDR"),
            ("Host", "SERVER_NAME"),
            ("Page", "HTTP_REFERER"),
            ("Browser", "HTTP_USER_AGENT")
        ]

        for text, header in header_text_mapping:
            body.append("{}: {}".format(text, request_headers[header]))

        body = "Additional information:\n\n" + "\n".join(body)
        return {"ticket": {"comment": {"public": False, "body": body}}}

    def _assert_zendesk_called(self, zendesk_mock, ticket_id, ticket, ticket_update):
        """Assert that Zendesk was called with the correct ticket and ticket_update."""
        expected_zendesk_calls = [mock.call.create_ticket(ticket), mock.call.update_ticket(ticket_id, ticket_update)]
        self.assertEqual(zendesk_mock.mock_calls, expected_zendesk_calls)

    def _assert_datadog_called(self, datadog_mock, tags):
        """Assert that datadog was called with the correct tags."""
        expected_datadog_calls = [mock.call.increment(views.DATADOG_FEEDBACK_METRIC, tags=tags)]
        self.assertEqual(datadog_mock.mock_calls, expected_datadog_calls)

    def test_bad_request_anon_user_no_name(self, zendesk_mock_class, datadog_mock):
        """Test a request from an anonymous user not specifying `name`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class, datadog_mock)

    def test_bad_request_anon_user_no_email(self, zendesk_mock_class, datadog_mock):
        """Test a request from an anonymous user not specifying `email`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class, datadog_mock)

    def test_bad_request_anon_user_invalid_email(self, zendesk_mock_class, datadog_mock):
        """Test a request from an anonymous user specifying an invalid `email`."""
        fields = self._anon_fields.copy()
        fields["email"] = "This is not a valid email address!"
        resp = self._build_and_run_request(self._anon_user, fields)
        self._assert_bad_request(resp, "email", zendesk_mock_class, datadog_mock)

    def test_bad_request_anon_user_no_subject(self, zendesk_mock_class, datadog_mock):
        """Test a request from an anonymous user not specifying `subject`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class, datadog_mock)

    def test_bad_request_anon_user_no_details(self, zendesk_mock_class, datadog_mock):
        """Test a request from an anonymous user not specifying `details`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class, datadog_mock)

    def test_valid_request_anon_user(self, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an anonymous user.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._anon_user
        fields = self._anon_fields

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        ticket = self._build_zendesk_ticket(
            recipient=TEST_SUPPORT_EMAIL,
            name=fields["name"],
            email=fields["email"],
            subject=fields["subject"],
            details=fields["details"],
            tags=[fields["issue_type"], "LMS"]
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)

        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(fields["issue_type"])])

    @mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_get_value)
    def test_valid_request_anon_user_configuration_override(self, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an anonymous user to a mocked out site with configuration override

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API with the additional
        tag that will come from site configuration override.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._anon_user
        fields = self._anon_fields

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        ticket = self._build_zendesk_ticket(
            recipient=fake_get_value("email_from_address"),
            name=fields["name"],
            email=fields["email"],
            subject=fields["subject"],
            details=fields["details"],
            tags=[fields["issue_type"], "LMS", "site_name_{}".format(fake_get_value("SITE_NAME").replace(".", "_"))]
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)

        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(fields["issue_type"])])

    @data("course-v1:testOrg+testCourseNumber+testCourseRun", "", None)
    @override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
    def test_valid_request_anon_user_with_custom_fields(self, course_id, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an anonymous user when configured to use Zendesk Custom Fields.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API. When course_id is
        present, it should be sent to Zendesk via a custom field. When course_id is blank or missing,
        the request should still be processed successfully.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._anon_user

        fields = self._anon_fields.copy()
        if course_id is not None:
            fields["course_id"] = course_id

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        zendesk_tags = [fields["issue_type"], "LMS"]
        datadog_tags = ["issue_type:{}".format(fields["issue_type"])]
        zendesk_custom_fields = None
        if course_id:
            # FIXME the tests rely on the tags being in this specific order, which doesn't seem
            # reliable given that the view builds the list by iterating over a dictionary.
            zendesk_tags.insert(0, course_id)
            datadog_tags.insert(0, "course_id:{}".format(course_id))
            zendesk_custom_fields = [
                {"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
            ]

        ticket = self._build_zendesk_ticket(
            recipient=TEST_SUPPORT_EMAIL,
            name=fields["name"],
            email=fields["email"],
            subject=fields["subject"],
            details=fields["details"],
            tags=zendesk_tags,
            custom_fields=zendesk_custom_fields
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)

        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, datadog_tags)

    def test_bad_request_auth_user_no_subject(self, zendesk_mock_class, datadog_mock):
        """Test a request from an authenticated user not specifying `subject`."""
        self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class, datadog_mock)

    def test_bad_request_auth_user_no_details(self, zendesk_mock_class, datadog_mock):
        """Test a request from an authenticated user not specifying `details`."""
        self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class, datadog_mock)
        self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class, datadog_mock)

    def test_valid_request_auth_user(self, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an authenticated user.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._auth_user
        fields = self._auth_fields

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        ticket = self._build_zendesk_ticket(
            recipient=TEST_SUPPORT_EMAIL,
            name=user.profile.name,
            email=user.email,
            subject=fields["subject"],
            details=fields["details"],
            tags=["LMS"]
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)

        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, [])

    @data(
        ("course-v1:testOrg+testCourseNumber+testCourseRun", True),
        ("course-v1:testOrg+testCourseNumber+testCourseRun", False),
        ("", None),
        (None, None)
    )
    @unpack
    @override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
    def test_valid_request_auth_user_with_custom_fields(self, course_id, enrolled, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an authenticated user when configured to use Zendesk Custom Fields.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API. When course_id is
        present, it should be sent to Zendesk via a custom field, along with the enrollment mode
        if the user has an active enrollment for that course. When course_id is blank or missing,
        the request should still be processed successfully.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._auth_user

        fields = self._auth_fields.copy()
        if course_id is not None:
            fields["course_id"] = course_id

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        zendesk_tags = ["LMS"]
        datadog_tags = []
        zendesk_custom_fields = None
        if course_id:
            # FIXME the tests rely on the tags being in this specific order, which doesn't seem
            # reliable given that the view builds the list by iterating over a dictionary.
            zendesk_tags.insert(0, course_id)
            datadog_tags.insert(0, "course_id:{}".format(course_id))
            zendesk_custom_fields = [
                {"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
            ]
            if enrolled is not None:
                enrollment = CourseEnrollmentFactory.create(
                    user=user,
                    course_id=course_id,
                    is_active=enrolled
                )
                if enrollment.is_active:
                    zendesk_custom_fields.append(
                        {"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
                    )

        ticket = self._build_zendesk_ticket(
            recipient=TEST_SUPPORT_EMAIL,
            name=user.profile.name,
            email=user.email,
            subject=fields["subject"],
            details=fields["details"],
            tags=zendesk_tags,
            custom_fields=zendesk_custom_fields
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)

        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, datadog_tags)

    @httpretty.activate
    @data(
        ("course-v1:testOrg+testCourseNumber+testCourseRun", True),
        ("course-v1:testOrg+testCourseNumber+testCourseRun", False),
    )
    @unpack
    @override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
    @mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
    def test_valid_request_auth_user_with_enterprise_info(self, course_id, enrolled, zendesk_mock_class, datadog_mock):
        """
        Test a valid request from an authenticated user with enterprise tags.
        """
        self.mock_enterprise_learner_api()
        zendesk_mock_instance = zendesk_mock_class.return_value
        user = self._auth_user

        fields = self._auth_fields.copy()
        if course_id is not None:
            fields["course_id"] = course_id

        ticket_id = 42
        zendesk_mock_instance.create_ticket.return_value = ticket_id

        zendesk_tags = ["enterprise_learner", "LMS"]
        datadog_tags = ['learner_type:enterprise_learner']
        zendesk_custom_fields = []

        if course_id:
            zendesk_tags.insert(0, course_id)
            datadog_tags.insert(0, "course_id:{}".format(course_id))
            zendesk_custom_fields.append({"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id})
            if enrolled is not None:
                enrollment = CourseEnrollmentFactory.create(
                    user=user,
                    course_id=course_id,
                    is_active=enrolled
                )
                if enrollment.is_active:
                    zendesk_custom_fields.append(
                        {"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
                    )

        zendesk_custom_fields.append(
            {
                "id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enterprise_customer_name"],
                "value": 'TestShib'
            }
        )

        ticket = self._build_zendesk_ticket(
            recipient=TEST_SUPPORT_EMAIL,
            name=user.profile.name,
            email=user.email,
            subject=fields["subject"],
            details=fields["details"],
            tags=zendesk_tags,
            custom_fields=zendesk_custom_fields
        )

        ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
        self._test_success(user, fields)
        self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
        self._assert_datadog_called(datadog_mock, datadog_tags)

    @httpretty.activate
    @override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
    @mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
    def test_request_with_anonymous_user_without_enterprise_info(self, zendesk_mock_class, datadog_mock):
        """
        Test tags related to enterprise should not be there in case an unauthenticated user.
        """
        ticket_id = 42
        self.mock_enterprise_learner_api()
        user = self._anon_user

        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.return_value = ticket_id
        datadog_valid_tags = ["issue_type:{}".format(self._anon_fields["issue_type"])]
        datadog_invalid_tags = ['learner_type:enterprise_learner']

        resp = self._build_and_run_request(user, self._anon_fields)
        self.assertEqual(resp.status_code, 200)

        expected_datadog_calls = [mock.call.increment(views.DATADOG_FEEDBACK_METRIC, tags=datadog_valid_tags)]
        self.assertEqual(datadog_mock.mock_calls, expected_datadog_calls)

        not_expected_datadog_calls = [mock.call.increment(views.DATADOG_FEEDBACK_METRIC, tags=datadog_invalid_tags)]
        self.assertNotEqual(datadog_mock.mock_calls, not_expected_datadog_calls)

    @httpretty.activate
    @override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
    @mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
    def test_tags_in_request_with_auth_user_with_enterprise_info(self, zendesk_mock_class, datadog_mock):
        """
        Test tags related to enterprise should be there in case the request is generated by an authenticated user.
        """
        ticket_id = 42
        self.mock_enterprise_learner_api()
        user = self._auth_user

        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.return_value = ticket_id
        datadog_valid_tags = ['learner_type:enterprise_learner']

        resp = self._build_and_run_request(user, self._auth_fields)
        self.assertEqual(resp.status_code, 200)
        self._assert_datadog_called(datadog_mock, datadog_valid_tags)

    def test_get_request(self, zendesk_mock_class, datadog_mock):
        """Test that a GET results in a 405 even with all required fields"""
        req = self._request_factory.get("/submit_feedback", data=self._anon_fields)
        req.user = self._anon_user
        resp = views.submit_feedback(req)
        self.assertEqual(resp.status_code, 405)
        self.assertIn("Allow", resp)
        self.assertEqual(resp["Allow"], "POST")
        # There should be absolutely no interaction with Zendesk
        self.assertFalse(zendesk_mock_class.mock_calls)
        self.assertFalse(datadog_mock.mock_calls)

    def test_zendesk_error_on_create(self, zendesk_mock_class, datadog_mock):
        """
        Test Zendesk returning an error on ticket creation.

        We should return a 500 error with no body
        """
        err = ZendeskError(msg="", error_code=404)
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.side_effect = err
        resp = self._build_and_run_request(self._anon_user, self._anon_fields)
        self.assertEqual(resp.status_code, 500)
        self.assertFalse(resp.content)
        self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(self._anon_fields["issue_type"])])

    def test_zendesk_error_on_update(self, zendesk_mock_class, datadog_mock):
        """
        Test for Zendesk returning an error on ticket update.

        If Zendesk returns any error on ticket update, we return a 200 to the
        browser because the update contains additional information that is not
        necessary for the user to have submitted their feedback.
        """
        err = ZendeskError(msg="", error_code=500)
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.update_ticket.side_effect = err
        resp = self._build_and_run_request(self._anon_user, self._anon_fields)
        self.assertEqual(resp.status_code, 200)
        self._assert_datadog_called(datadog_mock, ["issue_type:{}".format(self._anon_fields["issue_type"])])

    @mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
    def test_not_enabled(self, zendesk_mock_class, datadog_mock):
        """
        Test for Zendesk submission not enabled in `settings`.

        We should raise Http404.
        """
        with self.assertRaises(Http404):
            self._build_and_run_request(self._anon_user, self._anon_fields)

    def test_zendesk_not_configured(self, zendesk_mock_class, datadog_mock):
        """
        Test for Zendesk not fully configured in `settings`.

        For each required configuration parameter, test that setting it to
        `None` causes an otherwise valid request to return a 500 error.
        """
        def test_case(missing_config):
            with mock.patch(missing_config, None):
                with self.assertRaises(Exception):
                    self._build_and_run_request(self._anon_user, self._anon_fields)

        test_case("django.conf.settings.ZENDESK_URL")
        test_case("django.conf.settings.ZENDESK_USER")
        test_case("django.conf.settings.ZENDESK_API_KEY")

    @mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_support_backend_values)
    def test_valid_request_over_email(self, zendesk_mock_class, datadog_mock):  # pylint: disable=unused-argument
        with mock.patch("util.views.send_mail") as patched_send_email:
            resp = self._build_and_run_request(self._anon_user, self._anon_fields)
            self.assertEqual(patched_send_email.call_count, 1)
            self.assertIn(self._anon_fields["email"], str(patched_send_email.call_args))
        self.assertEqual(resp.status_code, 200)

    @mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_support_backend_values)
    def test_exception_request_over_email(self, zendesk_mock_class, datadog_mock):  # pylint: disable=unused-argument
        with mock.patch("util.views.send_mail", side_effect=SMTPException) as patched_send_email:
            resp = self._build_and_run_request(self._anon_user, self._anon_fields)
            self.assertEqual(patched_send_email.call_count, 1)
            self.assertIn(self._anon_fields["email"], str(patched_send_email.call_args))
        self.assertEqual(resp.status_code, 500)
Example #44
0
class TestGetProblemGradeDistribution(SharedModuleStoreTestCase):
    """
    Tests related to class_dashboard/dashboard_data.py
    """
    @classmethod
    def setUpClass(cls):
        super(TestGetProblemGradeDistribution, cls).setUpClass()
        cls.course = CourseFactory.create(
            display_name=u"test course omega \u03a9", )
        with cls.store.bulk_operations(cls.course.id, emit_signals=False):
            section = ItemFactory.create(
                parent_location=cls.course.location,
                category="chapter",
                display_name=u"test factory section omega \u03a9",
            )
            cls.sub_section = ItemFactory.create(
                parent_location=section.location,
                category="sequential",
                display_name=u"test subsection omega \u03a9",
            )
            cls.unit = ItemFactory.create(
                parent_location=cls.sub_section.location,
                category="vertical",
                metadata={
                    'graded': True,
                    'format': 'Homework'
                },
                display_name=u"test unit omega \u03a9",
            )
            cls.items = []
            for i in xrange(USER_COUNT - 1):
                item = ItemFactory.create(
                    parent_location=cls.unit.location,
                    category="problem",
                    data=StringResponseXMLFactory().build_xml(answer='foo'),
                    metadata={'rerandomize': 'always'},
                    display_name=u"test problem omega \u03a9 " + str(i))
                cls.items.append(item)
                cls.item = item

    def setUp(self):
        super(TestGetProblemGradeDistribution, self).setUp()

        self.request_factory = RequestFactory()
        self.instructor = AdminFactory.create()
        self.client.login(username=self.instructor.username, password='******')
        self.attempts = 3
        self.users = [
            UserFactory.create(username="******" + str(__))
            for __ in xrange(USER_COUNT)
        ]

        for user in self.users:
            CourseEnrollmentFactory.create(user=user, course_id=self.course.id)

        for i, item in enumerate(self.items):
            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    grade=1 if i < j else 0,
                    max_grade=1 if i < j else 0.5,
                    student=user,
                    course_id=self.course.id,
                    module_state_key=item.location,
                    state=json.dumps({'attempts': self.attempts}),
                )
            for j, user in enumerate(self.users):
                StudentModuleFactory.create(
                    course_id=self.course.id,
                    module_type='sequential',
                    module_state_key=item.location,
                )

    def test_get_problem_grade_distribution(self):

        prob_grade_distrib, total_student_count = get_problem_grade_distribution(
            self.course.id)

        for problem in prob_grade_distrib:
            max_grade = prob_grade_distrib[problem]['max_grade']
            self.assertEquals(1, max_grade)

        for val in total_student_count.values():
            self.assertEquals(USER_COUNT, val)

    def test_get_sequential_open_distibution(self):

        sequential_open_distrib = get_sequential_open_distrib(self.course.id)

        for problem in sequential_open_distrib:
            num_students = sequential_open_distrib[problem]
            self.assertEquals(USER_COUNT, num_students)

    def test_get_problemset_grade_distrib(self):

        prob_grade_distrib, __ = get_problem_grade_distribution(self.course.id)
        probset_grade_distrib = get_problem_set_grade_distrib(
            self.course.id, prob_grade_distrib)

        for problem in probset_grade_distrib:
            max_grade = probset_grade_distrib[problem]['max_grade']
            self.assertEquals(1, max_grade)

            grade_distrib = probset_grade_distrib[problem]['grade_distrib']
            sum_attempts = 0
            for item in grade_distrib:
                sum_attempts += item[1]
            self.assertEquals(USER_COUNT, sum_attempts)

    def test_get_d3_problem_grade_distrib(self):

        d3_data = get_d3_problem_grade_distrib(self.course.id)
        for data in d3_data:
            for stack_data in data['data']:
                sum_values = 0
                for problem in stack_data['stackData']:
                    sum_values += problem['value']
                self.assertEquals(USER_COUNT, sum_values)

    def test_get_d3_sequential_open_distrib(self):

        d3_data = get_d3_sequential_open_distrib(self.course.id)

        for data in d3_data:
            for stack_data in data['data']:
                for problem in stack_data['stackData']:
                    value = problem['value']
                self.assertEquals(0, value)

    def test_get_d3_section_grade_distrib(self):

        d3_data = get_d3_section_grade_distrib(self.course.id, 0)

        for stack_data in d3_data:
            sum_values = 0
            for problem in stack_data['stackData']:
                sum_values += problem['value']
            self.assertEquals(USER_COUNT, sum_values)

    def test_get_students_problem_grades(self):

        attributes = '?module_id=' + text_type(self.item.location)
        request = self.request_factory.get(
            reverse('get_students_problem_grades') + attributes)

        response = get_students_problem_grades(request)
        response_content = json.loads(response.content)['results']
        response_max_exceeded = json.loads(response.content)['max_exceeded']

        self.assertEquals(USER_COUNT, len(response_content))
        self.assertEquals(False, response_max_exceeded)
        for item in response_content:
            if item['grade'] == 0:
                self.assertEquals(0, item['percent'])
            else:
                self.assertEquals(100, item['percent'])

    def test_get_students_problem_grades_max(self):

        with patch('class_dashboard.dashboard_data.MAX_SCREEN_LIST_LENGTH', 2):
            attributes = '?module_id=' + text_type(self.item.location)
            request = self.request_factory.get(
                reverse('get_students_problem_grades') + attributes)

            response = get_students_problem_grades(request)
            response_results = json.loads(response.content)['results']
            response_max_exceeded = json.loads(
                response.content)['max_exceeded']

            # Only 2 students in the list and response_max_exceeded is True
            self.assertEquals(2, len(response_results))
            self.assertEquals(True, response_max_exceeded)

    def test_get_students_problem_grades_csv(self):

        tooltip = 'P1.2.1 Q1 - 3382 Students (100%: 1/1 questions)'
        attributes = '?module_id=' + text_type(
            self.item.location) + '&tooltip=' + tooltip + '&csv=true'
        request = self.request_factory.get(
            reverse('get_students_problem_grades') + attributes)

        response = get_students_problem_grades(request)
        # Check header and a row for each student in csv response
        self.assertContains(response, '"Name","Username","Grade","Percent"')
        self.assertContains(response, '"metric0","0.0","0.0"')
        self.assertContains(response, '"metric1","0.0","0.0"')
        self.assertContains(response, '"metric2","0.0","0.0"')
        self.assertContains(response, '"metric3","0.0","0.0"')
        self.assertContains(response, '"metric4","0.0","0.0"')
        self.assertContains(response, '"metric5","0.0","0.0"')
        self.assertContains(response, '"metric6","0.0","0.0"')
        self.assertContains(response, '"metric7","0.0","0.0"')
        self.assertContains(response, '"metric8","0.0","0.0"')
        self.assertContains(response, '"metric9","0.0","0.0"')
        self.assertContains(response, '"metric10","1.0","100.0"')

    def test_get_students_opened_subsection(self):

        attributes = '?module_id=' + text_type(self.item.location)
        request = self.request_factory.get(
            reverse('get_students_opened_subsection') + attributes)

        response = get_students_opened_subsection(request)
        response_results = json.loads(response.content)['results']
        response_max_exceeded = json.loads(response.content)['max_exceeded']
        self.assertEquals(USER_COUNT, len(response_results))
        self.assertEquals(False, response_max_exceeded)

    def test_get_students_opened_subsection_max(self):

        with patch('class_dashboard.dashboard_data.MAX_SCREEN_LIST_LENGTH', 2):

            attributes = '?module_id=' + text_type(self.item.location)
            request = self.request_factory.get(
                reverse('get_students_opened_subsection') + attributes)

            response = get_students_opened_subsection(request)
            response_results = json.loads(response.content)['results']
            response_max_exceeded = json.loads(
                response.content)['max_exceeded']

            # Only 2 students in the list and response_max_exceeded is True
            self.assertEquals(2, len(response_results))
            self.assertEquals(True, response_max_exceeded)

    def test_get_students_opened_subsection_csv(self):

        tooltip = '4162 students opened Subsection 5: Relational Algebra Exercises'
        attributes = '?module_id=' + text_type(
            self.item.location) + '&tooltip=' + tooltip + '&csv=true'
        request = self.request_factory.get(
            reverse('get_students_opened_subsection') + attributes)

        response = get_students_opened_subsection(request)
        self.assertContains(response, '"Name","Username"')
        # Check response contains 1 line for each user +1 for the header
        self.assertEquals(USER_COUNT + 1, len(response.content.splitlines()))

    def test_post_metrics_data_subsections_csv(self):

        url = reverse('post_metrics_data_csv')

        sections = json.dumps(["Introduction"])
        tooltips = json.dumps([[{
            "subsection_name": "Pre-Course Survey",
            "subsection_num": 1,
            "type": "subsection",
            "num_students": 18963
        }]])
        course_id = self.course.id
        data_type = 'subsection'

        data = json.dumps({
            'sections': sections,
            'tooltips': tooltips,
            'course_id': text_type(course_id),
            'data_type': data_type,
        })

        response = self.client.post(url, {'data': data})
        # Check response contains 1 line for header, 1 line for Section and 1 line for Subsection
        self.assertEquals(3, len(response.content.splitlines()))

    def test_post_metrics_data_problems_csv(self):

        url = reverse('post_metrics_data_csv')

        sections = json.dumps(["Introduction"])
        tooltips = json.dumps([[[
            {
                'student_count_percent': 0,
                'problem_name': 'Q1',
                'grade': 0,
                'percent': 0,
                'label': 'P1.2.1',
                'max_grade': 1,
                'count_grade': 26,
                'type': u'problem'
            },
            {
                'student_count_percent': 99,
                'problem_name': 'Q1',
                'grade': 1,
                'percent': 100,
                'label': 'P1.2.1',
                'max_grade': 1,
                'count_grade': 4763,
                'type': 'problem'
            },
        ]]])
        course_id = self.course.id
        data_type = 'problem'

        data = json.dumps({
            'sections': sections,
            'tooltips': tooltips,
            'course_id': text_type(course_id),
            'data_type': data_type,
        })

        response = self.client.post(url, {'data': data})
        # Check response contains 1 line for header, 1 line for Sections and 2 lines for problems
        self.assertEquals(4, len(response.content.splitlines()))

    def test_get_section_display_name(self):

        section_display_name = get_section_display_name(self.course.id)
        self.assertMultiLineEqual(section_display_name[0],
                                  u"test factory section omega \u03a9")

    def test_get_array_section_has_problem(self):

        b_section_has_problem = get_array_section_has_problem(self.course.id)
        self.assertEquals(b_section_has_problem[0], True)

    def test_has_instructor_access_for_class(self):
        """
        Test for instructor access
        """
        ret_val = bool(
            has_instructor_access_for_class(self.instructor, self.course.id))
        self.assertEquals(ret_val, True)
Example #45
0
class EmailChangeConfirmationTests(EmailTestMixin, TransactionTestCase):
    """Test that confirmation of email change requests function even in the face of exceptions thrown while sending email"""
    def setUp(self):
        super(EmailChangeConfirmationTests, self).setUp()
        self.user = UserFactory.create()
        self.profile = UserProfile.objects.get(user=self.user)
        self.req_factory = RequestFactory()
        self.request = self.req_factory.get('unused_url')
        self.request.user = self.user
        self.user.email_user = Mock()
        self.pending_change_request = PendingEmailChangeFactory.create(
            user=self.user)
        self.key = self.pending_change_request.activation_key

    def assertRolledBack(self):
        """Assert that no changes to user, profile, or pending email have been made to the db"""
        self.assertEquals(self.user.email,
                          User.objects.get(username=self.user.username).email)
        self.assertEquals(self.profile.meta,
                          UserProfile.objects.get(user=self.user).meta)
        self.assertEquals(1, PendingEmailChange.objects.count())

    def assertFailedBeforeEmailing(self, email_user):
        """Assert that the function failed before emailing a user"""
        self.assertRolledBack()
        self.assertFalse(email_user.called)

    def check_confirm_email_change(self, expected_template, expected_context):
        """Call `confirm_email_change` and assert that the content was generated as expected

        `expected_template`: The name of the template that should have been used
            to generate the content
        `expected_context`: The context dictionary that should have been used to
            generate the content
        """
        response = confirm_email_change(self.request, self.key)
        self.assertEquals(
            mock_render_to_response(expected_template,
                                    expected_context).content,
            response.content)

    def assertChangeEmailSent(self, email_user):
        """Assert that the correct email was sent to confirm an email change"""
        context = {
            'old_email': self.user.email,
            'new_email': self.pending_change_request.new_email,
        }
        self.assertEmailUser(email_user, 'emails/email_change_subject.txt',
                             context, 'emails/confirm_email_change.txt',
                             context)

        # Thorough tests for safe_get_host are elsewhere; here we just want a quick URL sanity check
        request = RequestFactory().post('unused_url')
        request.user = self.user
        request.META['HTTP_HOST'] = "aGenericValidHostName"
        self.append_allowed_hosts("aGenericValidHostName")

        mako_middleware_process_request(request)
        body = render_to_string('emails/confirm_email_change.txt', context)
        url = safe_get_host(request)

        self.assertIn(url, body)

    def test_not_pending(self, email_user):
        self.key = 'not_a_key'
        self.check_confirm_email_change('invalid_email_key.html', {})
        self.assertFailedBeforeEmailing(email_user)

    def test_duplicate_email(self, email_user):
        UserFactory.create(email=self.pending_change_request.new_email)
        self.check_confirm_email_change('email_exists.html', {})
        self.assertFailedBeforeEmailing(email_user)

    @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls',
                         "Test only valid in LMS")
    def test_old_email_fails(self, email_user):
        email_user.side_effect = [Exception, None]
        self.check_confirm_email_change('email_change_failed.html', {
            'email': self.user.email,
        })
        self.assertRolledBack()
        self.assertChangeEmailSent(email_user)

    @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls',
                         "Test only valid in LMS")
    def test_new_email_fails(self, email_user):
        email_user.side_effect = [None, Exception]
        self.check_confirm_email_change(
            'email_change_failed.html',
            {'email': self.pending_change_request.new_email})
        self.assertRolledBack()
        self.assertChangeEmailSent(email_user)

    @unittest.skipUnless(settings.ROOT_URLCONF == 'lms.urls',
                         "Test only valid in LMS")
    def test_successful_email_change(self, email_user):
        self.check_confirm_email_change(
            'email_change_successful.html', {
                'old_email': self.user.email,
                'new_email': self.pending_change_request.new_email
            })
        self.assertChangeEmailSent(email_user)
        meta = json.loads(UserProfile.objects.get(user=self.user).meta)
        self.assertIn('old_emails', meta)
        self.assertEquals(self.user.email, meta['old_emails'][0][0])
        self.assertEquals(self.pending_change_request.new_email,
                          User.objects.get(username=self.user.username).email)
        self.assertEquals(0, PendingEmailChange.objects.count())

    @patch('student.views.PendingEmailChange.objects.get',
           Mock(side_effect=TestException))
    @patch('student.views.transaction.rollback',
           wraps=django.db.transaction.rollback)
    def test_always_rollback(self, rollback, _email_user):
        with self.assertRaises(TestException):
            confirm_email_change(self.request, self.key)

        rollback.assert_called_with()
Example #46
0
class TestRedirectUrlPattern(TestCase):
    def setUp(self):
        self.rf = RequestFactory()

    def test_name(self):
        """
        Should return a RegexURLPattern with a matching name attribute
        """
        url_pattern = redirect(r'^the/dude$', 'abides', name='Lebowski')
        self.assertTrue(isinstance(url_pattern, RegexURLPattern))
        self.assertEqual(url_pattern.name, 'Lebowski')

    def test_no_query(self):
        """
        Should return a 301 redirect
        """
        pattern = redirect(r'^the/dude$', 'abides')
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides')

    def test_preserve_query(self):
        """
        Should preserve querys from the original request by default
        """
        pattern = redirect(r'^the/dude$', 'abides')
        request = self.rf.get('the/dude?aggression=not_stand')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides?aggression=not_stand')

    def test_replace_query(self):
        """
        Should replace query params if any are provided
        """
        pattern = redirect(r'^the/dude$', 'abides',
                           query={'aggression': 'not_stand'})
        request = self.rf.get('the/dude?aggression=unchecked')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides?aggression=not_stand')

    def test_merge_query(self):
        """
        Should merge query params if requested
        """
        pattern = redirect(r'^the/dude$', 'abides',
                           query={'aggression': 'not_stand'}, merge_query=True)
        request = self.rf.get('the/dude?hates=the-eagles')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        url = urlparse(response['location'])
        query_dict = parse_qs(url.query)
        self.assertTrue(url.path, 'abides')
        self.assertEqual(query_dict, {'aggression': ['not_stand'], 'hates': ['the-eagles']})

    def test_empty_query(self):
        """
        Should strip query params if called with empty query
        """
        pattern = redirect(r'^the/dude$', 'abides', query={})
        request = self.rf.get('the/dude?white=russian')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides')

    def test_temporary_redirect(self):
        """
        Should use a temporary redirect (status code 302) if permanent == False
        """
        pattern = redirect(r'^the/dude$', 'abides', permanent=False)
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], 'abides')

    def test_anchor(self):
        """
        Should append anchor text to the end, including after any querystring
        """
        pattern = redirect(r'^the/dude$', 'abides', anchor='toe')
        request = self.rf.get('the/dude?want=a')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides?want=a#toe')

    def test_callable(self):
        """
        Should use the return value of the callable as redirect location
        """
        def opinion(request):
            return '/just/your/opinion/man'

        pattern = redirect(r'^the/dude$', opinion)
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], '/just/your/opinion/man')

    @patch('redirect_urls.utils.reverse')
    def test_to_view(self, mock_reverse):
        """
        Should use return value of reverse as redirect location
        """
        mock_reverse.return_value = '/just/your/opinion/man'
        pattern = redirect(r'^the/dude$', 'yeah.well.you.know.thats')
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        mock_reverse.assert_called_with('yeah.well.you.know.thats', args=None, kwargs=None)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], '/just/your/opinion/man')

    @patch('redirect_urls.utils.reverse')
    def test_to_view_args_kwargs(self, mock_reverse):
        """
        Should call reverse with specified args and/or kwargs.
        """
        mock_reverse.return_value = '/just/your/opinion/man'
        pattern = redirect(r'^the/dude$', 'yeah.well.you.know.thats',
                           to_args=['dude'], to_kwargs={'tapes': 'credence'})
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        mock_reverse.assert_called_with('yeah.well.you.know.thats',
                                        args=['dude'], kwargs={'tapes': 'credence'})
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], '/just/your/opinion/man')

    def test_cache_headers(self):
        """
        Should add cache headers based on argument.
        """
        pattern = redirect(r'^the/dude$', 'abides', cache_timeout=2)
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides')
        self.assertEqual(response['cache-control'], 'max-age=7200')  # 2 hours

    def test_vary_header(self):
        """
        Should add vary header based on argument.
        """
        pattern = redirect(r'^the/dude$', 'abides', vary='Accept-Language')
        request = self.rf.get('the/dude')
        response = pattern.callback(request)
        self.assertEqual(response.status_code, 301)
        self.assertEqual(response['Location'], 'abides')
        self.assertEqual(response['Vary'], 'Accept-Language')

    def test_value_capture_and_substitution(self):
        """
        Should be able to capture info from URL and use in redirection.
        """
        resolver = get_resolver([redirect(r'^iam/the/(?P<name>.+)/$', '/donnie/the/{name}/')])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/donnie/the/walrus/')

    def test_locale_value_capture(self):
        """
        Should prepend locale value automatically.
        """
        resolver = get_resolver([redirect(r'^iam/the/(?P<name>.+)/$',
                                          '/donnie/the/{name}/')])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/pt-BR/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/pt-BR/donnie/the/walrus/')

    def test_locale_value_capture_no_locale(self):
        """
        Should get locale value in kwargs and not break if no locale in URL.
        """
        resolver = get_resolver([redirect(r'^iam/the/(?P<name>.+)/$',
                                          '/donnie/the/{name}/')])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/donnie/the/walrus/')

    def test_locale_value_capture_ignore_locale(self):
        """
        Should be able to ignore the original locale.
        """
        resolver = get_resolver([redirect(r'^iam/the/(?P<name>.+)/$',
                                          '/donnie/the/{name}/', prepend_locale=False)])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/zh-TW/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/donnie/the/walrus/')

    def test_no_locale_prefix(self):
        """
        Should be able to define a redirect that ignores locale prefix.

        Also when not using any named captures (like implied locale) unnamed
        captures should work. For some reason Django only allows unnamed captures
        to pass through if there are no named ones.
        """
        resolver = get_resolver([redirect(r'^iam/the/(.+)/$', '/donnie/the/{}/',
                                          locale_prefix=False)])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/donnie/the/walrus/')

    def test_empty_unnamed_captures(self):
        """
        Should be able to define an optional unnamed capture.
        """
        resolver = get_resolver([redirect(r'^iam/the(/.+)?/$', '/donnie/the{}/',
                                          locale_prefix=False)])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/iam/the/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/donnie/the/')

    def test_match_flags(self):
        """
        Should be able to set regex flags for redirect URL.
        """
        resolver = get_resolver([
            redirect(r'^iam/the/walrus/$', '/coo/coo/cachoo/'),
            redirect(r'^iam/the/walrus/$', '/dammit/donnie/', re_flags='i'),
        ])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/IAm/The/Walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/dammit/donnie/')

        # also with locale
        resp = middleware.process_request(self.rf.get('/es-ES/Iam/The/Walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/es-ES/dammit/donnie/')

        # sanity check
        resp = middleware.process_request(self.rf.get('/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/coo/coo/cachoo/')

    def test_non_ascii_strip_tags(self):
        """
        Should deal with non-ascii characters when there's a substitution as well as strip tags.

        This is from errors that happened on www.m.o. The following URL caused a 500:

        https://www.mozilla.org/editor/midasdemo/securityprefs.html%3C/span%3E%3C/a%3E%C2%A0
        """
        resolver = get_resolver([redirect(r'^editor/(?P<page>.*)$',
                                          'http://www-archive.mozilla.org/editor/{page}')])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/editor/midasdemo/securityprefs.html'
                                                      '%3C/span%3E%3C/a%3E%C2%A0'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], 'http://www-archive.mozilla.org/editor/midasdemo/'
                                           'securityprefs.html%C2%A0')

    @patch('redirect_urls.utils.reverse')
    def test_urls_dont_call_reverse(self, reverse_mock):
        """
        Should not call reverse() for an obvious URL.
        """
        resolver = get_resolver([
            redirect(r'^iam/the/walrus/$', '/coo/coo/cachoo/'),
            redirect(r'^iam/the/ape-man/$', 'https://example.com/egg-man/'),
        ])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/iam/the/walrus/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], '/coo/coo/cachoo/')
        resp = middleware.process_request(self.rf.get('/iam/the/ape-man/'))
        self.assertEqual(resp.status_code, 301)
        self.assertEqual(resp['Location'], 'https://example.com/egg-man/')
        reverse_mock.assert_not_called()

    def test_will_not_return_protocol_relative_redirect(self):
        """Allowing a protocol relative URL can allow an unintended domain redirect."""
        resolver = get_resolver([
            redirect(r'^(.+)/$', '/{}/', locale_prefix=False),
        ])
        middleware = RedirectsMiddleware(resolver)
        resp = middleware.process_request(self.rf.get('/%2fexample.com/'))
        self.assertEqual(resp['Location'], '/example.com/')
Example #47
0
class VerifyTests(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    def verify(self, request_type, **kwargs):
        """
        Call the verify view function. Kwargs are passed as GET or POST
        arguments.
        """
        if request_type == 'get':
            request = self.factory.get('/browserid/verify', kwargs)
        else:
            request = self.factory.post('/browserid/verify', kwargs)

        verify_view = views.Verify.as_view()
        with patch.object(auth, 'login'):
            response = verify_view(request)

        return response

    def test_no_assertion(self):
        """If no assertion is given, return a failure result."""
        with self.settings(LOGIN_REDIRECT_URL_FAILURE='/fail'):
            response = self.verify('post', blah='asdf')
        self.assertEqual(response.status_code, 403)
        self.assert_json_equals(response.content, {'redirect': '/fail'})

    @mock_browserid(None)
    def test_auth_fail(self):
        """If authentication fails, redirect to the failure URL."""
        with self.settings(LOGIN_REDIRECT_URL_FAILURE='/fail'):
            response = self.verify('post', assertion='asdf')
        self.assertEqual(response.status_code, 403)
        self.assert_json_equals(response.content, {'redirect': '/fail'})

    @mock_browserid('*****@*****.**')
    def test_auth_success_redirect_success(self):
        """If authentication succeeds, redirect to the success URL."""
        user = auth.models.User.objects.create_user('asdf', '*****@*****.**')

        request = self.factory.post('/browserid/verify', {'assertion': 'asdf'})
        with self.settings(LOGIN_REDIRECT_URL='/success'):
            with patch('django_browserid.views.auth.login') as login:
                verify = views.Verify.as_view()
                response = verify(request)

        login.assert_called_with(request, user)
        self.assertEqual(response.status_code, 200)
        self.assert_json_equals(response.content, {
            'email': '*****@*****.**',
            'redirect': '/success'
        })

    def test_sanity_checks(self):
        """Run sanity checks on all incoming requests."""
        with patch('django_browserid.views.sanity_checks') as sanity_checks:
            self.verify('post')
        self.assertTrue(sanity_checks.called)

    @patch('django_browserid.views.auth.login')
    def test_login_success_no_next(self, *args):
        """
        If _get_next returns None, use success_url for the redirect
        parameter.
        """
        view = views.Verify()
        view.request = self.factory.post('/')
        view.user = Mock(email='*****@*****.**')

        with patch('django_browserid.views._get_next',
                   return_value=None) as _get_next:
            with patch.object(views.Verify, 'success_url', '/?asdf'):
                response = view.login_success()

        self.assert_json_equals(response.content, {
            'email': '*****@*****.**',
            'redirect': '/?asdf'
        })
        _get_next.assert_called_with(view.request)

    @patch('django_browserid.views.auth.login')
    def test_login_success_next(self, *args):
        """
        If _get_next returns a URL, use it for the redirect parameter.
        """
        view = views.Verify()
        view.request = self.factory.post('/')
        view.user = Mock(email='*****@*****.**')

        with patch('django_browserid.views._get_next',
                   return_value='/?qwer') as _get_next:
            with patch.object(views.Verify, 'success_url', '/?asdf'):
                response = view.login_success()

        self.assert_json_equals(response.content, {
            'email': '*****@*****.**',
            'redirect': '/?qwer'
        })
        _get_next.assert_called_with(view.request)
Example #48
0
class TestSubscriptionPaymentRequired(TestCase):
    def setUp(self):
        self.settings(ROOT_URLCONF='tests.test_urls')
        self.factory = RequestFactory()

    def test_direct(self):
        subscription_payment_required(function=None)

    def test_anonymous(self):
        @subscription_payment_required
        def a_view(request):
            return HttpResponse()

        request = self.factory.get('/account/')
        request.user = AnonymousUser()
        self.assertRaises(ImproperlyConfigured, a_view, request)

    def test_user_unpaid(self):
        # create customer object with no subscription
        user = get_user_model().objects.create_user(username="******",
                                                    email="*****@*****.**")
        Customer.objects.create(subscriber=user,
                                stripe_id="cus_xxxxxxxxxxxxxxx",
                                card_fingerprint="YYYYYYYY",
                                card_last_4="2342",
                                card_kind="Visa")

        @subscription_payment_required
        def a_view(request):
            return HttpResponse()

        request = self.factory.get('/account/')
        request.user = user

        response = a_view(request)
        self.assertEqual(response.status_code, 302)

    def test_user_active_subscription(self):
        period_start = datetime.datetime(2013, 4, 1, tzinfo=timezone.utc)
        period_end = datetime.datetime(2030, 4, 30, tzinfo=timezone.utc)
        start = datetime.datetime(2013, 1, 1, tzinfo=timezone.utc)
        user = get_user_model().objects.create_user(username="******",
                                                    email="*****@*****.**")

        customer = Customer.objects.create(subscriber=user,
                                           stripe_id="cus_xxxxxxxxxxxxxxx",
                                           card_fingerprint="YYYYYYYY",
                                           card_last_4="2342",
                                           card_kind="Visa")
        CurrentSubscription.objects.create(customer=customer,
                                           plan="test",
                                           current_period_start=period_start,
                                           current_period_end=period_end,
                                           amount=(500 /
                                                   decimal.Decimal("100.0")),
                                           status="active",
                                           start=start,
                                           quantity=1)

        @subscription_payment_required
        def a_view(request):
            return HttpResponse()

        request = self.factory.get('/account/')
        request.user = user
        response = a_view(request)
        self.assertEqual(response.status_code, 200)
Example #49
0
class SubmitFeedbackViaZendeskTest(TestCase):
    def setUp(self):
        """Set up data for the test case"""
        self._request_factory = RequestFactory()
        self._anon_user = AnonymousUser()
        self._auth_user = UserFactory.create(
            email="*****@*****.**",
            username="******",
            profile__name="Test User"
        )
        # This contains a tag to ensure that tags are submitted correctly
        self._anon_fields = {
            "email": "*****@*****.**",
            "name": "Test User",
            "subject": "a subject",
            "details": "some details",
            "tag": "a tag"
        }
        # This does not contain a tag to ensure that tag is optional
        self._auth_fields = {"subject": "a subject", "details": "some details"}

    def _test_request(self, user, fields):
        """
        Generate a request and invoke the view, returning the response.

        The request will be a POST request from the given `user`, with the given
        `fields` in the POST body.
        """
        req = self._request_factory.post(
            "/submit_feedback",
            data=fields,
            HTTP_REFERER="test_referer",
            HTTP_USER_AGENT="test_user_agent"
        )
        req.user = user
        return views.submit_feedback_via_zendesk(req)

    def _assert_bad_request(self, response, field, zendesk_mock_class):
        """
        Assert that the given `response` contains correct failure data.

        It should have a 400 status code, and its content should be a JSON
        object containing the specified `field` and an `error`.
        """
        self.assertEqual(response.status_code, 400)
        resp_json = json.loads(response.content)
        self.assertTrue("field" in resp_json)
        self.assertEqual(resp_json["field"], field)
        self.assertTrue("error" in resp_json)
        # There should be absolutely no interaction with Zendesk
        self.assertFalse(zendesk_mock_class.return_value.mock_calls)

    def _test_bad_request_omit_field(self, user, fields, omit_field, zendesk_mock_class):
        """
        Invoke the view with a request missing a field and assert correctness.

        The request will be a POST request from the given `user`, with POST
        fields taken from `fields` minus the entry specified by `omit_field`.
        The response should have a 400 (bad request) status code and specify
        the invalid field and an error message, and the Zendesk API should not
        have been invoked.
        """
        filtered_fields = {k: v for (k, v) in fields.items() if k != omit_field}
        resp = self._test_request(user, filtered_fields)
        self._assert_bad_request(resp, omit_field, zendesk_mock_class)

    def _test_bad_request_empty_field(self, user, fields, empty_field, zendesk_mock_class):
        """
        Invoke the view with an empty field and assert correctness.

        The request will be a POST request from the given `user`, with POST
        fields taken from `fields`, replacing the entry specified by
        `empty_field` with the empty string. The response should have a 400
        (bad request) status code and specify the invalid field and an error
        message, and the Zendesk API should not have been invoked.
        """
        altered_fields = fields.copy()
        altered_fields[empty_field] = ""
        resp = self._test_request(user, altered_fields)
        self._assert_bad_request(resp, empty_field, zendesk_mock_class)

    def _test_success(self, user, fields):
        """
        Generate a request, invoke the view, and assert success.

        The request will be a POST request from the given `user`, with the given
        `fields` in the POST body. The response should have a 200 (success)
        status code.
        """
        resp = self._test_request(user, fields)
        self.assertEqual(resp.status_code, 200)

    def test_bad_request_anon_user_no_name(self, zendesk_mock_class):
        """Test a request from an anonymous user not specifying `name`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)

    def test_bad_request_anon_user_no_email(self, zendesk_mock_class):
        """Test a request from an anonymous user not specifying `email`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)

    def test_bad_request_anon_user_no_subject(self, zendesk_mock_class):
        """Test a request from an anonymous user not specifying `subject`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)

    def test_bad_request_anon_user_no_details(self, zendesk_mock_class):
        """Test a request from an anonymous user not specifying `details`."""
        self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)
        self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)

    def test_valid_request_anon_user(self, zendesk_mock_class):
        """
        Test a valid request from an anonymous user.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.return_value = 42
        self._test_success(self._anon_user, self._anon_fields)
        expected_calls = [
            mock.call.create_ticket(
                {
                    "ticket": {
                        "requester": {"name": "Test User", "email": "*****@*****.**"},
                        "subject": "a subject",
                        "comment": {"body": "some details"},
                        "tags": ["a tag"]
                    }
                }
            ),
            mock.call.update_ticket(
                42,
                {
                    "ticket": {
                        "comment": {
                            "public": False,
                            "body":
                            "Additional information:\n\n"
                            "HTTP_USER_AGENT: test_user_agent\n"
                            "HTTP_REFERER: test_referer"
                        }
                    }
                }
            )
        ]
        self.assertEqual(zendesk_mock_instance.mock_calls, expected_calls)

    def test_bad_request_auth_user_no_subject(self, zendesk_mock_class):
        """Test a request from an authenticated user not specifying `subject`."""
        self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)
        self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)

    def test_bad_request_auth_user_no_details(self, zendesk_mock_class):
        """Test a request from an authenticated user not specifying `details`."""
        self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)
        self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)

    def test_valid_request_auth_user(self, zendesk_mock_class):
        """
        Test a valid request from an authenticated user.

        The response should have a 200 (success) status code, and a ticket with
        the given information should have been submitted via the Zendesk API.
        """
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.return_value = 42
        self._test_success(self._auth_user, self._auth_fields)
        expected_calls = [
            mock.call.create_ticket(
                {
                    "ticket": {
                        "requester": {"name": "Test User", "email": "*****@*****.**"},
                        "subject": "a subject",
                        "comment": {"body": "some details"},
                        "tags": []
                    }
                }
            ),
            mock.call.update_ticket(
                42,
                {
                    "ticket": {
                        "comment": {
                            "public": False,
                            "body":
                            "Additional information:\n\n"
                            "username: test\n"
                            "HTTP_USER_AGENT: test_user_agent\n"
                            "HTTP_REFERER: test_referer"
                        }
                    }
                }
            )
        ]
        self.assertEqual(zendesk_mock_instance.mock_calls, expected_calls)

    def test_get_request(self, zendesk_mock_class):
        """Test that a GET results in a 405 even with all required fields"""
        req = self._request_factory.get("/submit_feedback", data=self._anon_fields)
        req.user = self._anon_user
        resp = views.submit_feedback_via_zendesk(req)
        self.assertEqual(resp.status_code, 405)
        self.assertIn("Allow", resp)
        self.assertEqual(resp["Allow"], "POST")
        # There should be absolutely no interaction with Zendesk
        self.assertFalse(zendesk_mock_class.mock_calls)

    def test_zendesk_error_on_create(self, zendesk_mock_class):
        """
        Test Zendesk returning an error on ticket creation.

        We should return a 500 error with no body
        """
        err = ZendeskError(msg="", error_code=404)
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.create_ticket.side_effect = err
        resp = self._test_request(self._anon_user, self._anon_fields)
        self.assertEqual(resp.status_code, 500)
        self.assertFalse(resp.content)

    def test_zendesk_error_on_update(self, zendesk_mock_class):
        """
        Test for Zendesk returning an error on ticket update.

        If Zendesk returns any error on ticket update, we return a 200 to the
        browser because the update contains additional information that is not
        necessary for the user to have submitted their feedback.
        """
        err = ZendeskError(msg="", error_code=500)
        zendesk_mock_instance = zendesk_mock_class.return_value
        zendesk_mock_instance.update_ticket.side_effect = err
        resp = self._test_request(self._anon_user, self._anon_fields)
        self.assertEqual(resp.status_code, 200)

    @mock.patch.dict("django.conf.settings.MITX_FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
    def test_not_enabled(self, zendesk_mock_class):
        """
        Test for Zendesk submission not enabled in `settings`.

        We should raise Http404.
        """
        with self.assertRaises(Http404):
            self._test_request(self._anon_user, self._anon_fields)

    def test_zendesk_not_configured(self, zendesk_mock_class):
        """
        Test for Zendesk not fully configured in `settings`.

        For each required configuration parameter, test that setting it to
        `None` causes an otherwise valid request to return a 500 error.
        """
        def test_case(missing_config):
            with mock.patch(missing_config, None):
                with self.assertRaises(Exception):
                    self._test_request(self._anon_user, self._anon_fields)

        test_case("django.conf.settings.ZENDESK_URL")
        test_case("django.conf.settings.ZENDESK_USER")
        test_case("django.conf.settings.ZENDESK_API_KEY")
class TestPrefixer(TestCase):
    def setUp(self):
        self.factory = RequestFactory()

    @override_settings(LANGUAGE_CODE='en-US')
    def test_get_language_default_language_code(self):
        """
        Should return default set by settings.LANGUAGE_CODE if no 'lang'
        url parameter and no Accept-Language header
        """
        request = self.factory.get('/')
        self.assertFalse('lang' in request.GET)
        self.assertFalse(request.META.get('HTTP_ACCEPT_LANGUAGE'))
        prefixer = Prefixer(request)
        eq_(prefixer.get_language(), 'en-US')

    @override_settings(LANGUAGE_URL_MAP={'en-us': 'en-US', 'de': 'de'})
    def test_get_language_valid_lang_param(self):
        """
        Should return lang param value if it is in settings.LANGUAGE_URL_MAP
        """
        request = self.factory.get('/?lang=de')
        eq_(request.GET.get('lang'), 'de')
        ok_('de' in settings.LANGUAGE_URL_MAP)
        prefixer = Prefixer(request)
        eq_(prefixer.get_language(), 'de')

    @override_settings(LANGUAGE_CODE='en-US',
                       LANGUAGE_URL_MAP={'en-us': 'en-US'})
    def test_get_language_invalid_lang_param(self):
        """
        Should return default set by settings.LANGUAGE_CODE if lang
        param value is not in settings.LANGUAGE_URL_MAP
        """
        request = self.factory.get('/?lang=de')
        ok_('lang' in request.GET)
        self.assertFalse('de' in settings.LANGUAGE_URL_MAP)
        prefixer = Prefixer(request)
        eq_(prefixer.get_language(), 'en-US')

    def test_get_language_returns_best(self):
        """
        Should pass Accept-Language header value to get_best_language
        and return result
        """
        request = self.factory.get('/')
        request.META['HTTP_ACCEPT_LANGUAGE'] = 'de, es' 
        prefixer = Prefixer(request)
        prefixer.get_best_language = Mock(return_value='de')
        eq_(prefixer.get_language(), 'de')
        prefixer.get_best_language.assert_called_once_with('de, es')

    @override_settings(LANGUAGE_CODE='en-US')
    def test_get_language_no_best(self):
        """
        Should return default set by settings.LANGUAGE_CODE if
        get_best_language return value is None
        """
        request = self.factory.get('/')
        request.META['HTTP_ACCEPT_LANGUAGE'] = 'de, es' 
        prefixer = Prefixer(request)
        prefixer.get_best_language = Mock(return_value=None)
        eq_(prefixer.get_language(), 'en-US')
        prefixer.get_best_language.assert_called_once_with('de, es')

    @override_settings(LANGUAGE_URL_MAP={'en-us': 'en-US', 'de': 'de'})
    def test_get_best_language_exact_match(self):
        """
        Should return exact match if it is in settings.LANGUAGE_URL_MAP
        """
        request = self.factory.get('/')
        prefixer = Prefixer(request)
        eq_(prefixer.get_best_language('de, es'), 'de')

    @override_settings(LANGUAGE_URL_MAP={'en-us': 'en-US', 'es-ar': 'es-AR'})
    def test_get_best_language_prefix_match(self):
        """
        Should return a language with a matching prefix from
        settings.LANGUAGE_URL_MAP if it exists but no exact match does
        """
        request = self.factory.get('/')
        prefixer = Prefixer(request)
        eq_(prefixer.get_best_language('es-CL'), 'es-AR')

    @override_settings(LANGUAGE_URL_MAP={'en-us': 'en-US'})
    def test_get_best_language_no_match(self):
        """
        Should return None if there is no exact match or matching
        prefix
        """
        request = self.factory.get('/')
        prefixer = Prefixer(request)
        eq_(prefixer.get_best_language('de'), None)

    @override_settings(LANGUAGE_URL_MAP={'en-us': 'en-US'})
    def test_get_best_language_handles_parse_accept_lang_header_error(self):
        """
        Should return None despite error raised by bug described in
        https://code.djangoproject.com/ticket/21078
        """
        request = self.factory.get('/')
        prefixer = Prefixer(request)
        eq_(prefixer.get_best_language('en; q=1,'), None)
Example #51
0
class BaseDueDateTests(ModuleStoreTestCase):
    """
    Base class that verifies that due dates are rendered correctly on a page
    """
    __test__ = False

    def get_text(self, course):  # pylint: disable=unused-argument
        """Return the rendered text for the page to be verified"""
        raise NotImplementedError

    def set_up_course(self, **course_kwargs):
        """
        Create a stock course with a specific due date.

        :param course_kwargs: All kwargs are passed to through to the :class:`CourseFactory`
        """
        course = CourseFactory.create(**course_kwargs)
        chapter = ItemFactory.create(category='chapter', parent_location=course.location)
        section = ItemFactory.create(category='sequential', parent_location=chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
        vertical = ItemFactory.create(category='vertical', parent_location=section.location)
        ItemFactory.create(category='problem', parent_location=vertical.location)

        course = modulestore().get_course(course.id)
        self.assertIsNotNone(course.get_children()[0].get_children()[0].due)
        CourseEnrollmentFactory(user=self.user, course_id=course.id)
        return course

    def setUp(self):
        super(BaseDueDateTests, self).setUp()
        self.request_factory = RequestFactory()
        self.user = UserFactory.create()
        self.request = self.request_factory.get("foo")
        self.request.user = self.user

        self.time_with_tz = "due Sep 18, 2013 at 11:30 UTC"
        self.time_without_tz = "due Sep 18, 2013 at 11:30"

    def test_backwards_compatability(self):
        # The test course being used has show_timezone = False in the policy file
        # (and no due_date_display_format set). This is to test our backwards compatibility--
        # in course_module's init method, the date_display_format will be set accordingly to
        # remove the timezone.
        course = self.set_up_course(due_date_display_format=None, show_timezone=False)
        text = self.get_text(course)
        self.assertIn(self.time_without_tz, text)
        self.assertNotIn(self.time_with_tz, text)
        # Test that show_timezone has been cleared (which means you get the default value of True).
        self.assertTrue(course.show_timezone)

    def test_defaults(self):
        course = self.set_up_course()
        text = self.get_text(course)
        self.assertIn(self.time_with_tz, text)

    def test_format_none(self):
        # Same for setting the due date to None
        course = self.set_up_course(due_date_display_format=None)
        text = self.get_text(course)
        self.assertIn(self.time_with_tz, text)

    def test_format_plain_text(self):
        # plain text due date
        course = self.set_up_course(due_date_display_format="foobar")
        text = self.get_text(course)
        self.assertNotIn(self.time_with_tz, text)
        self.assertIn("due foobar", text)

    def test_format_date(self):
        # due date with no time
        course = self.set_up_course(due_date_display_format=u"%b %d %y")
        text = self.get_text(course)
        self.assertNotIn(self.time_with_tz, text)
        self.assertIn("due Sep 18 13", text)

    def test_format_hidden(self):
        # hide due date completely
        course = self.set_up_course(due_date_display_format=u"")
        text = self.get_text(course)
        self.assertNotIn("due ", text)

    def test_format_invalid(self):
        # improperly formatted due_date_display_format falls through to default
        # (value of show_timezone does not matter-- setting to False to make that clear).
        course = self.set_up_course(due_date_display_format=u"%%%", show_timezone=False)
        text = self.get_text(course)
        self.assertNotIn("%%%", text)
        self.assertIn(self.time_with_tz, text)
Example #52
0
class SignUpTests(TestCase):
    """
    Tests signup functionality.
    """

    def setUp(self):
        # By default it will end-up being '*' which breaks multitier tests.
        settings.ALLOWED_HOSTS = ('localhost',)
        # Every test needs access to the request factory.
        self.factory = RequestFactory()

    def test_redirect_ok(self):
        """
        Tests to validate the redirect URL.
        """
        request = self.factory.get('/?next=/example/')
        url = validate_redirect(request)
        self.assertTrue(url == "/example/")

    def test_redirect_fail1(self):
        """
        Tests to validate the redirect URL.
        """
        request = self.factory.get('/?next=http://example.com/example/')
        url = validate_redirect(request)
        if '*' in settings.ALLOWED_HOSTS:
            self.assertTrue(url == "/example/")
        else:
            self.assertTrue(url is None)

    def test_redirect_url_ok(self):
        """
        Tests to validate the redirect URL.
        """
        url = validate_redirect_url("/example/")
        self.assertTrue(url == "/example/")

    def test_redirect_url_fail1(self):
        """
        Tests to validate the redirect URL.
        """
        url = validate_redirect_url("http://example.com/example/")
        if '*' in settings.ALLOWED_HOSTS:
            self.assertTrue(url == "/example/")
        else:
            self.assertTrue(url is None)

    def test_activate_password(self):
        user = ActivatedUser.objects.create_inactive_user(REGISTRATION_EMAIL)
        client = Client()
        response = client.get(reverse('registration_activate',
                                      args=(user.email_verification_key,)),
                              follow=True)
        # pylint: disable=maybe-no-member
        self.assertTrue(response.status_code == 200)
        self.assertTrue(re.match(
     r'\S+/accounts/activate/(?P<verification_key>%s)/password/(?P<token>.+)/$'
            % signup_settings.EMAIL_VERIFICATION_PAT,
            response.redirect_chain[-1][0]))

    def test_register(self):
        client = Client()
        response = client.post(reverse('registration_register'),
                     {'full_name': 'John Smith', 'email': REGISTRATION_EMAIL},
                               follow=True)
        # XXX Haven't found out how to get this assertion to pass,
        # status_code 302 vs 200 expected.
        # self.assertRedirects(response, settings.LOGIN_REDIRECT_URL)
        self.assertTrue(re.match(r'\S+/app/[\w.@+-]+/',
                                 response.redirect_chain[-1][0]))
Example #53
0
class TestNewslettersAPI(TestCase):
    def setUp(self):
        self.url = reverse('newsletters_api')
        self.rf = RequestFactory()

    def test_newsletters_view(self):
        # We can fetch the newsletter data
        nl1 = models.Newsletter.objects.create(
            slug='slug',
            title='title',
            active=False,
            languages='en-US,fr',
            vendor_id='VENDOR1',
        )

        models.Newsletter.objects.create(slug='slug2', vendor_id='VENDOR2')
        models.Newsletter.objects.create(slug='slug3',
                                         vendor_id='VENDOR3',
                                         private=True)

        req = self.rf.get(self.url)
        resp = views.newsletters(req)
        data = json.loads(resp.content)
        newsletters = data['newsletters']
        self.assertEqual(3, len(newsletters))
        # Find the 'slug' newsletter in the response
        obj = newsletters['slug']

        self.assertTrue(newsletters['slug3']['private'])
        self.assertEqual(nl1.title, obj['title'])
        self.assertEqual(nl1.active, obj['active'])
        for lang in ['en-US', 'fr']:
            self.assertIn(lang, obj['languages'])

    def test_strip_languages(self):
        # If someone edits Newsletter and puts whitespace in the languages
        # field, we strip it on save
        nl1 = models.Newsletter.objects.create(
            slug='slug',
            title='title',
            active=False,
            languages='en-US, fr, de ',
            vendor_id='VENDOR1',
        )
        nl1 = models.Newsletter.objects.get(id=nl1.id)
        self.assertEqual('en-US,fr,de', nl1.languages)

    def test_newsletter_languages(self):
        # newsletter_languages() returns the set of languages
        # of the newsletters
        # (Note that newsletter_languages() is not part of the external
        # API, but is used internally)
        models.Newsletter.objects.create(
            slug='slug',
            title='title',
            active=False,
            languages='en-US',
            vendor_id='VENDOR1',
        )
        models.Newsletter.objects.create(
            slug='slug2',
            title='title',
            active=False,
            languages='fr, de ',
            vendor_id='VENDOR2',
        )
        models.Newsletter.objects.create(
            slug='slug3',
            title='title',
            active=False,
            languages='en-US, fr',
            vendor_id='VENDOR3',
        )
        expect = set(['en-US', 'fr', 'de'])
        self.assertEqual(expect, newsletter_languages())

    def test_newsletters_cached(self):
        models.Newsletter.objects.create(
            slug='slug',
            title='title',
            vendor_id='VEND1',
            active=False,
            languages='en-US, fr, de ',
        )
        # This should get the data cached
        newsletter_fields()
        # Now request it again and it shouldn't have to generate the
        # data from scratch.
        with patch('basket.news.newsletters._get_newsletters_data') as get:
            newsletter_fields()
        self.assertFalse(get.called)

    def test_cache_clearing(self):
        # Our caching of newsletter data doesn't result in wrong answers
        # when newsletters change
        models.Newsletter.objects.create(
            slug='slug',
            title='title',
            vendor_id='VEND1',
            active=False,
            languages='en-US, fr, de ',
        )
        vendor_ids = newsletter_fields()
        self.assertEqual([u'VEND1'], vendor_ids)
        # Now add another newsletter
        models.Newsletter.objects.create(
            slug='slug2',
            title='title2',
            vendor_id='VEND2',
            active=False,
            languages='en-US, fr, de ',
        )
        vendor_ids2 = set(newsletter_fields())
        self.assertEqual(set([u'VEND1', u'VEND2']), vendor_ids2)

    def test_cache_clear_on_delete(self):
        # Our caching of newsletter data doesn't result in wrong answers
        # when newsletters are deleted
        nl1 = models.Newsletter.objects.create(
            slug='slug',
            title='title',
            vendor_id='VEND1',
            active=False,
            languages='en-US, fr, de ',
        )
        vendor_ids = newsletter_fields()
        self.assertEqual([u'VEND1'], vendor_ids)
        # Now delete it
        nl1.delete()
        vendor_ids = newsletter_fields()
        self.assertEqual([], vendor_ids)
Example #54
0
class ProgressPageTests(ModuleStoreTestCase):
    """
    Tests that verify that the progress page works correctly.
    """

    def setUp(self):
        super(ProgressPageTests, self).setUp()
        self.request_factory = RequestFactory()
        self.user = UserFactory.create()
        self.request = self.request_factory.get("foo")
        self.request.user = self.user

        mako_middleware_process_request(self.request)

        self.setup_course()

    def setup_course(self, **options):
        """Create the test course."""
        course = CourseFactory.create(
            start=datetime(2013, 9, 16, 7, 17, 28),
            grade_cutoffs={u'çü†øƒƒ': 0.75, 'Pass': 0.5},
            **options
        )

        # pylint: disable=attribute-defined-outside-init
        self.course = modulestore().get_course(course.id)
        CourseEnrollmentFactory(user=self.user, course_id=self.course.id)

        self.chapter = ItemFactory.create(category='chapter', parent_location=self.course.location)
        self.section = ItemFactory.create(category='sequential', parent_location=self.chapter.location)
        self.vertical = ItemFactory.create(category='vertical', parent_location=self.section.location)

    @ddt.data('"><script>alert(1)</script>', '<script>alert(1)</script>', '</script><script>alert(1)</script>')
    def test_progress_page_xss_prevent(self, malicious_code):
        """
        Test that XSS attack is prevented
        """
        resp = views.progress(self.request, course_id=unicode(self.course.id), student_id=self.user.id)
        self.assertEqual(resp.status_code, 200)
        # Test that malicious code does not appear in html
        self.assertNotIn(malicious_code, resp.content)

    def test_pure_ungraded_xblock(self):
        ItemFactory.create(category='acid', parent_location=self.vertical.location)

        resp = views.progress(self.request, course_id=self.course.id.to_deprecated_string())
        self.assertEqual(resp.status_code, 200)

    @ddt.data(ModuleStoreEnum.Type.mongo, ModuleStoreEnum.Type.split)
    def test_student_progress_with_valid_and_invalid_id(self, default_store):
        """
         Check that invalid 'student_id' raises Http404 for both old mongo and
         split mongo courses.
        """

        # Create new course with respect to 'default_store'
        self.course = CourseFactory.create(default_store=default_store)

        # Invalid Student Ids (Integer and Non-int)
        invalid_student_ids = [
            991021,
            'azU3N_8$',
        ]
        for invalid_id in invalid_student_ids:

            self.assertRaises(
                Http404, views.progress,
                self.request,
                course_id=unicode(self.course.id),
                student_id=invalid_id
            )

        # Enroll student into course
        CourseEnrollment.enroll(self.user, self.course.id, mode='honor')
        resp = views.progress(self.request, course_id=self.course.id.to_deprecated_string(), student_id=self.user.id)
        # Assert that valid 'student_id' returns 200 status
        self.assertEqual(resp.status_code, 200)

    def test_non_asci_grade_cutoffs(self):
        resp = views.progress(self.request, course_id=self.course.id.to_deprecated_string())

        self.assertEqual(resp.status_code, 200)

    def test_generate_cert_config(self):
        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertNotContains(resp, 'Request Certificate')

        # Enable the feature, but do not enable it for this course
        CertificateGenerationConfiguration(enabled=True).save()
        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertNotContains(resp, 'Request Certificate')

        # Enable certificate generation for this course
        certs_api.set_cert_generation_enabled(self.course.id, True)
        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertNotContains(resp, 'Request Certificate')

    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': True})
    @patch('courseware.grades.grade', Mock(return_value={'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [],
                                                         'grade_breakdown': []}))
    def test_view_certificate_link(self):
        """
        If certificate web view is enabled then certificate web view button should appear for user who certificate is
        available/generated
        """
        certificate = GeneratedCertificateFactory.create(
            user=self.user,
            course_id=self.course.id,
            status=CertificateStatuses.downloadable,
            download_url="http://www.example.com/certificate.pdf",
            mode='honor'
        )

        # Enable the feature, but do not enable it for this course
        CertificateGenerationConfiguration(enabled=True).save()

        # Enable certificate generation for this course
        certs_api.set_cert_generation_enabled(self.course.id, True)

        #course certificate configurations
        certificates = [
            {
                'id': 1,
                'name': 'Name 1',
                'description': 'Description 1',
                'course_title': 'course_title_1',
                'signatories': [],
                'version': 1,
                'is_active': True
            }
        ]

        self.course.certificates = {'certificates': certificates}
        self.course.cert_html_view_enabled = True
        self.course.save()
        self.store.update_item(self.course, self.user.id)

        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertContains(resp, u"View Certificate")

        self.assertContains(resp, u"You can keep working for a higher grade")
        cert_url = certs_api.get_certificate_url(
            user_id=self.user.id,
            course_id=self.course.id
        )
        self.assertContains(resp, cert_url)

        # when course certificate is not active
        certificates[0]['is_active'] = False
        self.store.update_item(self.course, self.user.id)

        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertNotContains(resp, u"View Your Certificate")
        self.assertNotContains(resp, u"You can now view your certificate")
        self.assertContains(resp, u"We're creating your certificate.")

    @patch.dict('django.conf.settings.FEATURES', {'CERTIFICATES_HTML_VIEW': False})
    @patch('courseware.grades.grade', Mock(return_value={'grade': 'Pass', 'percent': 0.75, 'section_breakdown': [],
                                                         'grade_breakdown': []}))
    def test_view_certificate_link_hidden(self):
        """
        If certificate web view is disabled then certificate web view button should not appear for user who certificate
        is available/generated
        """
        GeneratedCertificateFactory.create(
            user=self.user,
            course_id=self.course.id,
            status=CertificateStatuses.downloadable,
            download_url="http://www.example.com/certificate.pdf",
            mode='honor'
        )

        # Enable the feature, but do not enable it for this course
        CertificateGenerationConfiguration(enabled=True).save()

        # Enable certificate generation for this course
        certs_api.set_cert_generation_enabled(self.course.id, True)

        resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertContains(resp, u"Download Your Certificate")

    @ddt.data(
        *itertools.product(((18, 4, True), (18, 4, False)), (True, False))
    )
    @ddt.unpack
    def test_query_counts(self, (sql_calls, mongo_calls, self_paced), self_paced_enabled):
        """Test that query counts remain the same for self-paced and instructor-paced courses."""
        SelfPacedConfiguration(enabled=self_paced_enabled).save()
        self.setup_course(self_paced=self_paced)
        with self.assertNumQueries(sql_calls), check_mongo_calls(mongo_calls):
            resp = views.progress(self.request, course_id=unicode(self.course.id))
        self.assertEqual(resp.status_code, 200)
Example #55
0
class ProyectosTest(TestCase):
    """
    Clase que realiza el Test del modulo de administracion de proyectos
    """
    def setUp(self):
        """
        Funcion que inicializa el RequestFactory y un usuario de prueba para
        realizar los test
        """
        # Se crea el Request factory pars simular peticiones
        self.factory = RequestFactory()
        # Se crea el User que realiza las peticiones
        self.user = User.objects.create_user(username='******',
                                             email='*****@*****.**',
                                             password='******')

    def test_view_IndexView(self):
        """
        Funcion que realiza el test sobre la vista UserIndexView que genera
        lista de proyectos
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crean 10 proyectos para controlar que se retorne la lista completa de proyectos, que seran 11 en total
        for i in range(10):
            proyecto = Proyecto.objects.create(codigo='co%s' % i,
                                               nombre_corto='test%s' % i,
                                               nombre_largo='test%s' % i,
                                               cancelado=False,
                                               scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get('/proyectos/')
        view = IndexView.as_view()
        response = view(request)
        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.template_name[0], 'proyectos/index.html')
        # verificamos los proyectos retornados
        self.assertEqual(len(response.context_data['object_list']), 10)

        print 'Test de IndexView de Proyecto realizado exitosamente'

    def test_view_ProyectoCreate(self):
        """
        Funcion que realiza el test sobre la vista ProyectoCreate que crea
        un nuevo proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)

        user3 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crea un proyecto
        proyecto = Proyecto.objects.create(codigo='codi',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user3)

        self.assertEqual(proyecto.codigo, 'codi')
        self.assertEqual(proyecto.nombre_corto, 'test')

        print 'Test de ProyectoCreate realizado exitosamente'

    def test_view_ProyectoUpdate(self):
        """
        Funcion que realiza el test sobre la vista ProyectoUpdate que modifica
        un proyecto existente
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)

        user4 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crea un proyecto
        proyecto = Proyecto.objects.create(codigo='codi',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user4)

        # se crean nuevos valores para los atributos
        nuevo_codigo = 'new'
        new_nombre = 'Hola'

        # Se modifican los atributos del proyecto
        proyecto.codigo = nuevo_codigo
        proyecto.nombre_corto = new_nombre
        proyecto.save()

        self.assertEqual(proyecto.codigo, 'new')
        self.assertEqual(proyecto.nombre_corto, 'Hola')

        print 'Test de ProyectoUpdate realizado exitosamente'

    def test_view_cancelar_proyecto(self):
        """
        Funcion que realiza el test sobre la vista cancelar_proyecto que cambia el estado
        de un proyecto a cancelado
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)

        user5 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crea un proyecto
        proyecto = Proyecto.objects.create(codigo='codi',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user5)
        # se marca al proyecto
        proyecto.cancelado = True
        proyecto.save()

        self.assertEqual(proyecto.cancelado, True)

        print 'Test de cancelarProyecto realizado exitosamente'

    def test_view_proyecto_index(self):
        """
        Funcion que realiza el test sobre la vista proyecto_index que genera
        el index del proyecto seleccionado
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:proyecto_index', args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_index
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_index realizado exitosamente'

    def test_view_listar_equipo(self):
        """
        Funcion que realiza el test sobre la vista listar_equipo que genera
        lista de usuarios que se encuentran en el equipo del proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        lista_usuarios = []
        for i in range(10):
            user = User.objects.create_user(username='******' % i,
                                            email='*****@*****.**' % i,
                                            password='******')
            user.save()
            lista_usuarios.append(user)

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)
        proyecto.equipo = lista_usuarios
        proyecto.save()

        cantidad = len(lista_usuarios)
        cantidad_equipo = proyecto.equipo.all().count()

        self.assertEqual(cantidad_equipo, cantidad)

        print 'Test de listar_equipo realizado exitosamente'

    def test_view_AddMiembro(self):
        """
        Funcion que realiza el test sobre la vista AddMiembro que agrega
        un usuario al equipo del proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        lista_usuarios = []
        for i in range(10):
            user = User.objects.create_user(username='******' % i,
                                            email='*****@*****.**' % i,
                                            password='******')
            user.save()
            lista_usuarios.append(user)

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)
        proyecto.equipo = lista_usuarios
        proyecto.save()

        user_nuevo = User.objects.create_user(username='******',
                                              email='*****@*****.**',
                                              password='******')

        proyecto.equipo.add(user_nuevo)
        proyecto.save()
        lista_usuarios.append(user_nuevo)
        cantidad = len(lista_usuarios)
        cantidad_equipo = proyecto.equipo.all().count()

        self.assertEqual(cantidad_equipo, cantidad)

        print 'Test de AddMiembro realizado exitosamente'

    def test_view_delete_miembro(self):
        """
        Funcion que realiza el test sobre la vista delete_miembro que elimina
        un usuario del equipo del proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        lista_usuarios = []
        for i in range(10):
            user = User.objects.create_user(username='******' % i,
                                            email='*****@*****.**' % i,
                                            password='******')
            user.save()
            lista_usuarios.append(user)

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)
        proyecto.equipo = lista_usuarios
        proyecto.save()

        user_eliminar = User.objects.get(username='******')

        proyecto.equipo.remove(user_eliminar)
        proyecto.save()
        lista_usuarios.remove(user_eliminar)
        cantidad = len(lista_usuarios)
        cantidad_equipo = proyecto.equipo.all().count()

        self.assertEqual(cantidad_equipo, cantidad)

        print 'Test de delete_miembro realizado exitosamente'

    def test_view_proyecto_reportes(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reportes que genera
        el index de los reportes del proyecto seleccionado
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:proyecto_reportes', args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reportes
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reportes realizado exitosamente'

    def test_view_proyecto_reporte_trabajos_equipo(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reporte_trabajos_equipo que genera
        el reporte de los trabajos realizados por cada equipo
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:reporte_trabajo_equipo', args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reporte_trabajos_equipo
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reporte_trabajos_equipo realizado exitosamente'

    def test_view_reporte_grafico_reportlab(self):
        """
        Funcion que realiza el test sobre la vista reporte_grafico_reportlab que genera
        el reporte de los burndown_chart de los sprints
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:reporte_grafico_sprints', args=[proyecto.pk]))
        request.user = self.user
        view = reporte_grafico_reportlab
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de reporte_grafico_reportlab realizado exitosamente'

    def test_view_proyecto_reporte_trabajos_usuario(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reporte_trabajos_usuario que genera
        el reporte de los trabajos realizados por cada usuario
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        for i in range(10):
            sprint_s = Sprint.objects.create(nombre='sprint%s' % i,
                                             duracion='%d' % i,
                                             proyecto=proyecto,
                                             estado='Activo')
            sprint_s.save()

        sprint = Sprint.objects.filter(estado='Activo')

        group = Group.objects.create(name='Developer')
        group.save()
        rolProyecto = RolProyecto(group=group, es_rol_proyecto=True)
        rolProyecto.save()

        row_rol = RolProyecto_Proyecto(user=self.user,
                                       rol_proyecto=rolProyecto,
                                       proyecto=proyecto)
        row_rol.save()

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:reporte_trabajo_usuario', args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reporte_trabajos_usuario
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reporte_trabajos_usuario realizado exitosamente'

    def test_view_proyecto_reporte_actividades(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reporte_actividades que genera
        el reporte de las actividades a realizar en el proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:proyecto_reporte_actividades',
                    args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reporte_actividades
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reporte_actividades realizado exitosamente'

    def test_view_proyecto_reporte_product_backlog(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reporte_product_backlog que genera
        el reporte de los user stories del product backlog del proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:proyecto_reporte_product_backlog',
                    args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reporte_product_backlog
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reporte_product_backlog realizado exitosamente'

    def test_view_proyecto_reporte_sprint_backlog(self):
        """
        Funcion que realiza el test sobre la vista proyecto_reporte_sprint_backlog que genera
        el reporte de los user stories del sprint backlog del sprint actual
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)
        user2 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')

        proyecto = Proyecto.objects.create(codigo='co',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user2)

        for i in range(10):
            sprint_s = Sprint.objects.create(nombre='sprint%s' % i,
                                             duracion='%d' % i,
                                             proyecto=proyecto,
                                             estado='Activo')
            sprint_s.save()

        sprint = Sprint.objects.filter(estado='Activo')

        # verificamos que la vista devuelva el template adecuado
        request = self.factory.get(
            reverse('proyectos:proyecto_reporte_sprint_backlog',
                    args=[proyecto.pk]))
        request.user = self.user
        view = proyecto_reporte_sprint_backlog
        response = view(request, pk=proyecto.pk)
        self.assertEqual(response.status_code, 200)

        print 'Test de proyecto_reporte_sprint_backlog realizado exitosamente'

    def test_view_iniciar_proyecto(self):
        """
        Funcion que realiza el test sobre la vista iniciar_proyecto que inicia
        el proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)

        user3 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crea un proyecto
        proyecto = Proyecto.objects.create(codigo='codi',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user3)

        proyecto.save()
        proyecto.estado = "Activo"
        proyecto.save()

        self.assertEqual(proyecto.codigo, 'codi')
        self.assertEqual(proyecto.nombre_corto, 'test')
        self.assertEqual(proyecto.estado, 'Activo')

        print 'Test de iniciar_proyecto realizado exitosamente'

    def test_view_finalizar_proyecto(self):
        """
        Funcion que realiza el test sobre la vista finalizar_proyecto que inicia
        el proyecto
        """
        # se loguea el usuario testuser
        user = self.client.login(username='******', password='******')
        self.assertTrue(user)

        user3 = User.objects.create_user(username='******',
                                         email='*****@*****.**',
                                         password='******')
        # se crea un proyecto
        proyecto = Proyecto.objects.create(codigo='codi',
                                           nombre_corto='test',
                                           nombre_largo='test',
                                           cancelado=False,
                                           scrum_master=user3)

        proyecto.save()
        proyecto.estado = "Finalizado"
        proyecto.save()

        self.assertEqual(proyecto.codigo, 'codi')
        self.assertEqual(proyecto.nombre_corto, 'test')
        self.assertEqual(proyecto.estado, 'Finalizado')

        print 'Test de finalizar_proyecto realizado exitosamente'
Example #56
0
class ViewsTestCase(ModuleStoreTestCase):
    """
    Tests for views.py methods.
    """
    def setUp(self):
        super(ViewsTestCase, self).setUp()
        self.course = CourseFactory.create()
        self.chapter = ItemFactory.create(category='chapter', parent_location=self.course.location)
        self.section = ItemFactory.create(category='sequential', parent_location=self.chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
        self.vertical = ItemFactory.create(category='vertical', parent_location=self.section.location)
        self.component = ItemFactory.create(category='problem', parent_location=self.vertical.location)

        self.course_key = self.course.id
        self.user = UserFactory(username='******', password='******', email='*****@*****.**')
        self.date = datetime(2013, 1, 22, tzinfo=UTC)
        self.enrollment = CourseEnrollment.enroll(self.user, self.course_key)
        self.enrollment.created = self.date
        self.enrollment.save()
        self.request_factory = RequestFactory()
        chapter = 'Overview'
        self.chapter_url = '%s/%s/%s' % ('/courses', self.course_key, chapter)

        self.org = u"ꜱᴛᴀʀᴋ ɪɴᴅᴜꜱᴛʀɪᴇꜱ"
        self.org_html = "<p>'+Stark/Industries+'</p>"

    @unittest.skipUnless(settings.FEATURES.get('ENABLE_SHOPPING_CART'), "Shopping Cart not enabled in settings")
    @patch.dict(settings.FEATURES, {'ENABLE_PAID_COURSE_REGISTRATION': True})
    def test_course_about_in_cart(self):
        in_cart_span = '<span class="add-to-cart">'
        # don't mock this course due to shopping cart existence checking
        course = CourseFactory.create(org="new", number="unenrolled", display_name="course")
        request = self.request_factory.get(reverse('about_course', args=[course.id.to_deprecated_string()]))
        request.user = AnonymousUser()
        mako_middleware_process_request(request)
        response = views.course_about(request, course.id.to_deprecated_string())
        self.assertEqual(response.status_code, 200)
        self.assertNotIn(in_cart_span, response.content)

        # authenticated user with nothing in cart
        request.user = self.user
        response = views.course_about(request, course.id.to_deprecated_string())
        self.assertEqual(response.status_code, 200)
        self.assertNotIn(in_cart_span, response.content)

        # now add the course to the cart
        cart = shoppingcart.models.Order.get_cart_for_user(self.user)
        shoppingcart.models.PaidCourseRegistration.add_to_order(cart, course.id)
        response = views.course_about(request, course.id.to_deprecated_string())
        self.assertEqual(response.status_code, 200)
        self.assertIn(in_cart_span, response.content)

    def test_user_groups(self):
        # depreciated function
        mock_user = MagicMock()
        mock_user.is_authenticated.return_value = False
        self.assertEqual(views.user_groups(mock_user), [])

    def test_get_current_child(self):
        self.assertIsNone(views.get_current_child(MagicMock()))
        mock_xmodule = MagicMock()
        mock_xmodule.position = -1
        mock_xmodule.get_display_items.return_value = ['one', 'two']
        self.assertEqual(views.get_current_child(mock_xmodule), 'one')
        mock_xmodule_2 = MagicMock()
        mock_xmodule_2.position = 3
        mock_xmodule_2.get_display_items.return_value = []
        self.assertIsNone(views.get_current_child(mock_xmodule_2))

    def test_redirect_to_course_position(self):
        mock_module = MagicMock()
        mock_module.descriptor.id = 'Underwater Basketweaving'
        mock_module.position = 3
        mock_module.get_display_items.return_value = []
        self.assertRaises(Http404, views.redirect_to_course_position,
                          mock_module, views.CONTENT_DEPTH)

    def test_invalid_course_id(self):
        response = self.client.get('/courses/MITx/3.091X/')
        self.assertEqual(response.status_code, 404)

    def test_incomplete_course_id(self):
        response = self.client.get('/courses/MITx/')
        self.assertEqual(response.status_code, 404)

    def test_index_invalid_position(self):
        request_url = '/'.join([
            '/courses',
            self.course.id.to_deprecated_string(),
            'courseware',
            self.chapter.location.name,
            self.section.location.name,
            'f'
        ])
        self.client.login(username=self.user.username, password="******")
        response = self.client.get(request_url)
        self.assertEqual(response.status_code, 404)

    def test_unicode_handling_in_url(self):
        url_parts = [
            '/courses',
            self.course.id.to_deprecated_string(),
            'courseware',
            self.chapter.location.name,
            self.section.location.name,
            '1'
        ]
        self.client.login(username=self.user.username, password="******")
        for idx, val in enumerate(url_parts):
            url_parts_copy = url_parts[:]
            url_parts_copy[idx] = val + u'χ'
            request_url = '/'.join(url_parts_copy)
            response = self.client.get(request_url)
            self.assertEqual(response.status_code, 404)

    def test_registered_for_course(self):
        self.assertFalse(views.registered_for_course('Basketweaving', None))
        mock_user = MagicMock()
        mock_user.is_authenticated.return_value = False
        self.assertFalse(views.registered_for_course('dummy', mock_user))
        mock_course = MagicMock()
        mock_course.id = self.course_key
        self.assertTrue(views.registered_for_course(mock_course, self.user))

    @override_settings(PAID_COURSE_REGISTRATION_CURRENCY=["USD", "$"])
    def test_get_cosmetic_display_price(self):
        """
        Check that get_cosmetic_display_price() returns the correct price given its inputs.
        """
        registration_price = 99
        self.course.cosmetic_display_price = 10
        # Since registration_price is set, it overrides the cosmetic_display_price and should be returned
        self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "$99")

        registration_price = 0
        # Since registration_price is not set, cosmetic_display_price should be returned
        self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "$10")

        self.course.cosmetic_display_price = 0
        # Since both prices are not set, there is no price, thus "Free"
        self.assertEqual(views.get_cosmetic_display_price(self.course, registration_price), "Free")

    def test_jump_to_invalid(self):
        # TODO add a test for invalid location
        # TODO add a test for no data *
        request = self.request_factory.get(self.chapter_url)
        self.assertRaisesRegexp(Http404, 'Invalid course_key or usage_key', views.jump_to,
                                request, 'bar', ())

    @unittest.skip
    def test_no_end_on_about_page(self):
        # Toy course has no course end date or about/end_date blob
        self.verify_end_date('edX/toy/TT_2012_Fall')

    @unittest.skip
    def test_no_end_about_blob(self):
        # test_end has a course end date, no end_date HTML blob
        self.verify_end_date("edX/test_end/2012_Fall", "Sep 17, 2015")

    @unittest.skip
    def test_about_blob_end_date(self):
        # test_about_blob_end_date has both a course end date and an end_date HTML blob.
        # HTML blob wins
        self.verify_end_date("edX/test_about_blob_end_date/2012_Fall", "Learning never ends")

    def verify_end_date(self, course_id, expected_end_text=None):
        """
        Visits the about page for `course_id` and tests that both the text "Classes End", as well
        as the specified `expected_end_text`, is present on the page.

        If `expected_end_text` is None, verifies that the about page *does not* contain the text
        "Classes End".
        """
        request = self.request_factory.get("foo")
        request.user = self.user

        # TODO: Remove the dependency on MakoMiddleware (by making the views explicitly supply a RequestContext)
        mako_middleware_process_request(request)

        result = views.course_about(request, course_id)
        if expected_end_text is not None:
            self.assertContains(result, "Classes End")
            self.assertContains(result, expected_end_text)
        else:
            self.assertNotContains(result, "Classes End")

    def test_submission_history_accepts_valid_ids(self):
        # log into a staff account
        admin = AdminFactory()

        self.client.login(username=admin.username, password='******')

        url = reverse('submission_history', kwargs={
            'course_id': self.course_key.to_deprecated_string(),
            'student_username': '******',
            'location': self.component.location.to_deprecated_string(),
        })
        response = self.client.get(url)
        # Tests that we do not get an "Invalid x" response when passing correct arguments to view
        self.assertFalse('Invalid' in response.content)

    def test_submission_history_xss(self):
        # log into a staff account
        admin = AdminFactory()

        self.client.login(username=admin.username, password='******')

        # try it with an existing user and a malicious location
        url = reverse('submission_history', kwargs={
            'course_id': self.course_key.to_deprecated_string(),
            'student_username': '******',
            'location': '<script>alert("hello");</script>'
        })
        response = self.client.get(url)
        self.assertFalse('<script>' in response.content)

        # try it with a malicious user and a non-existent location
        url = reverse('submission_history', kwargs={
            'course_id': self.course_key.to_deprecated_string(),
            'student_username': '******',
            'location': 'dummy'
        })
        response = self.client.get(url)
        self.assertFalse('<script>' in response.content)

    def test_submission_history_contents(self):
        # log into a staff account
        admin = AdminFactory.create()

        self.client.login(username=admin.username, password='******')

        usage_key = self.course_key.make_usage_key('problem', 'test-history')
        state_client = DjangoXBlockUserStateClient(admin)

        # store state via the UserStateClient
        state_client.set(
            username=admin.username,
            block_key=usage_key,
            state={'field_a': 'x', 'field_b': 'y'}
        )

        set_score(admin.id, usage_key, 0, 3)

        state_client.set(
            username=admin.username,
            block_key=usage_key,
            state={'field_a': 'a', 'field_b': 'b'}
        )
        set_score(admin.id, usage_key, 3, 3)

        url = reverse('submission_history', kwargs={
            'course_id': unicode(self.course_key),
            'student_username': admin.username,
            'location': unicode(usage_key),
        })
        response = self.client.get(url)
        response_content = HTMLParser().unescape(response.content)

        # We have update the state 4 times: twice to change content, and twice
        # to set the scores. We'll check that the identifying content from each is
        # displayed (but not the order), and also the indexes assigned in the output
        # #1 - #4

        self.assertIn('#1', response_content)
        self.assertIn(json.dumps({'field_a': 'a', 'field_b': 'b'}, sort_keys=True, indent=2), response_content)
        self.assertIn("Score: 0.0 / 3.0", response_content)
        self.assertIn(json.dumps({'field_a': 'x', 'field_b': 'y'}, sort_keys=True, indent=2), response_content)
        self.assertIn("Score: 3.0 / 3.0", response_content)
        self.assertIn('#4', response_content)

    def _email_opt_in_checkbox(self, response, org_name_string=None):
        """Check if the email opt-in checkbox appears in the response content."""
        checkbox_html = '<input id="email-opt-in" type="checkbox" name="opt-in" class="email-opt-in" value="true" checked>'
        if org_name_string:
            # Verify that the email opt-in checkbox appears, and that the expected
            # organization name is displayed.
            self.assertContains(response, checkbox_html, html=True)
            self.assertContains(response, org_name_string)
        else:
            # Verify that the email opt-in checkbox does not appear
            self.assertNotContains(response, checkbox_html, html=True)
class FieldOverridePerformanceTestCase(ProceduralCourseTestMixin,
                                       ModuleStoreTestCase):
    """
    Base class for instrumenting SQL queries and Mongo reads for field override
    providers.
    """
    __test__ = False
    # Tell Django to clean out all databases, not just default
    multi_db = True

    # TEST_DATA must be overridden by subclasses
    TEST_DATA = None

    ENABLED_CACHES = ['default', 'mongo_metadata_inheritance', 'loc_cache']

    def setUp(self):
        """
        Create a test client, course, and user.
        """
        super(FieldOverridePerformanceTestCase, self).setUp()

        self.request_factory = RequestFactory()
        self.student = UserFactory.create()
        self.request = self.request_factory.get("foo")
        self.request.user = self.student

        patcher = mock.patch('edxmako.request_context.get_current_request',
                             return_value=self.request)
        patcher.start()
        self.addCleanup(patcher.stop)
        self.course = None
        self.ccx = None

    def setup_course(self, size, enable_ccx, view_as_ccx):
        """
        Build a gradable course where each node has `size` children.
        """
        grading_policy = {
            "GRADER": [{
                "drop_count": 2,
                "min_count": 12,
                "short_label": "HW",
                "type": "Homework",
                "weight": 0.15
            }, {
                "drop_count": 2,
                "min_count": 12,
                "type": "Lab",
                "weight": 0.15
            }, {
                "drop_count": 0,
                "min_count": 1,
                "short_label": "Midterm",
                "type": "Midterm Exam",
                "weight": 0.3
            }, {
                "drop_count": 0,
                "min_count": 1,
                "short_label": "Final",
                "type": "Final Exam",
                "weight": 0.4
            }],
            "GRADE_CUTOFFS": {
                "Pass": 0.5
            }
        }

        self.course = CourseFactory.create(
            graded=True,
            start=datetime.now(UTC),
            grading_policy=grading_policy,
            enable_ccx=enable_ccx,
        )
        self.populate_course(size)

        course_key = self.course.id
        if enable_ccx:
            self.ccx = CcxFactory.create(course_id=self.course.id)
            if view_as_ccx:
                course_key = CCXLocator.from_course_locator(
                    self.course.id, self.ccx.id)

        CourseEnrollment.enroll(self.student, course_key)

    def grade_course(self, course, view_as_ccx):
        """
        Renders the progress page for the given course.
        """
        course_key = course.id
        if view_as_ccx:
            course_key = CCXLocator.from_course_locator(
                course_key, self.ccx.id)

        return progress(self.request,
                        course_id=unicode(course_key),
                        student_id=self.student.id)

    def assertMongoCallCount(self, calls):
        """
        Assert that mongodb is queried ``calls`` times in the surrounded
        context.
        """
        return check_mongo_calls_range(max_finds=calls)

    def assertXBlockInstantiations(self, instantiations):
        """
        Assert that exactly ``instantiations`` XBlocks are instantiated in
        the surrounded context.
        """
        return check_sum_of_calls(XBlock, ['__init__'],
                                  instantiations,
                                  instantiations,
                                  include_arguments=False)

    def instrument_course_progress_render(self, course_width, enable_ccx,
                                          view_as_ccx, default_queries,
                                          history_queries, reads, xblocks):
        """
        Renders the progress page, instrumenting Mongo reads and SQL queries.
        """
        self.setup_course(course_width, enable_ccx, view_as_ccx)

        # Switch to published-only mode to simulate the LMS
        with self.settings(MODULESTORE_BRANCH='published-only'):
            # Clear all caches before measuring
            for cache in settings.CACHES:
                caches[cache].clear()

            # Refill the metadata inheritance cache
            modulestore().get_course(self.course.id, depth=None)

            # We clear the request cache to simulate a new request in the LMS.
            RequestCache.clear_request_cache()

            # Reset the list of provider classes, so that our django settings changes
            # can actually take affect.
            OverrideFieldData.provider_classes = None

            with self.assertNumQueries(default_queries, using='default'):
                with self.assertNumQueries(history_queries,
                                           using='student_module_history'):
                    with self.assertMongoCallCount(reads):
                        with self.assertXBlockInstantiations(xblocks):
                            self.grade_course(self.course, view_as_ccx)

    @ddt.data(*itertools.product(('no_overrides', 'ccx'), range(1, 4),
                                 (True, False), (True, False)))
    @ddt.unpack
    @override_settings(
        FIELD_OVERRIDE_PROVIDERS=(), )
    def test_field_overrides(self, overrides, course_width, enable_ccx,
                             view_as_ccx):
        """
        Test without any field overrides.
        """
        providers = {
            'no_overrides': (),
            'ccx': ('ccx.overrides.CustomCoursesForEdxOverrideProvider', )
        }
        if overrides == 'no_overrides' and view_as_ccx:
            raise SkipTest(
                "Can't view a ccx course if field overrides are disabled.")

        if not enable_ccx and view_as_ccx:
            raise SkipTest(
                "Can't view a ccx course if ccx is disabled on the course")

        if self.MODULESTORE == TEST_DATA_MONGO_MODULESTORE and view_as_ccx:
            raise SkipTest("Can't use a MongoModulestore test as a CCX course")

        with self.settings(FIELD_OVERRIDE_PROVIDERS=providers[overrides]):
            default_queries, history_queries, reads, xblocks = self.TEST_DATA[(
                overrides, course_width, enable_ccx, view_as_ccx)]
            self.instrument_course_progress_render(course_width, enable_ccx,
                                                   view_as_ccx,
                                                   default_queries,
                                                   history_queries, reads,
                                                   xblocks)
class BaseTestCase(TestCase):
    """
    Test case for users app
    """
    def setUp(self):
        self.test_user = data_user.copy()
        user = User.objects.create_user(username=data_user['email'],
                                        email=data_user['email'],
                                        password=data_user['password1'])

    def test_1_privacy(self):
        """
        Test for privacy policy view
        """
        response = self.client.get(reverse('privacy-policy'), follow=True)
        self.assertEqual(response.status_code, 200)

    def test_2_group_required(self):
        """
        Test case for group anonymous required
        """
        func = base_views.BlogDetailView
        anonymous_required(func)

    def test_3_group_required_none(self):
        """
        Test case for group required decorator
        """
        func = base_views.BlogDetailView
        group_required(func)

    def test_4_is_valid_password(self):
        """
        Test case for is_valid_password utils
        """
        self.factory = RequestFactory()
        response = self.factory.post('',
                                     data={'password': '******'},
                                     HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        response = is_valid_password(response)
        self.assertContains(response, 'The password is invalid')

        response = self.factory.post('',
                                     data={'password': '******'},
                                     HTTP_X_REQUESTED_WITH='XMLHttpRequest')
        response = is_valid_password(response)
        self.assertContains(response, 'The password is correct')

        self.factory = RequestFactory()
        response = self.factory.post('', data={'password': '******'})

    def test_5_group_required(self):
        """
        Test case for group required decorator
        """
        user = User.objects.get(email=data_user['email'])
        self.factory = RequestFactory()

        @group_required('default')
        def test(request):
            return 200

        request = self.factory.get('/foo')
        request.user = user
        response = test(request)
        self.assertEqual(response.status_code, 302)

        group = Group.objects.create(name='default', )

        user.groups.add(group)
        request = self.factory.get('/foo')
        request.user = user
        response = test(request)
        self.assertEqual(response, 200)

    def test_6_contact(self):
        """
        Test for contact view
        """
        response = self.client.get(reverse('contact'), follow=True)
        self.assertEqual(response.status_code, 200)

        data = {
            'contact_email': '*****@*****.**',
            'content': 'test content',
            'contact_name': 'john doe'
        }
        response = self.client.post(reverse('contact'), data, follow=True)
        self.assertEqual(response.status_code, 200)
Example #59
0
class UserViews(TestCase):
    """view user and edit profile"""
    def setUp(self):
        """we need basic test data and mocks"""
        self.factory = RequestFactory()
        with patch(
                "bookwyrm.suggested_users.rerank_suggestions_task.delay"
        ), patch("bookwyrm.activitystreams.populate_stream_task.delay"), patch(
                "bookwyrm.lists_stream.populate_lists_task.delay"):
            self.local_user = models.User.objects.create_user(
                "*****@*****.**",
                "*****@*****.**",
                "password",
                local=True,
                localname="mouse",
            )
            self.rat = models.User.objects.create_user("*****@*****.**",
                                                       "*****@*****.**",
                                                       "password",
                                                       local=True,
                                                       localname="rat")
        self.book = models.Edition.objects.create(
            title="test",
            parent_work=models.Work.objects.create(title="test work"))
        with patch(
                "bookwyrm.models.activitypub_mixin.broadcast_task.apply_async"
        ), patch("bookwyrm.suggested_users.rerank_suggestions_task.delay"
                 ), patch(
                     "bookwyrm.activitystreams.add_book_statuses_task.delay"):
            models.ShelfBook.objects.create(
                book=self.book,
                user=self.local_user,
                shelf=self.local_user.shelf_set.first(),
            )

        models.SiteSettings.objects.create()
        self.anonymous_user = AnonymousUser
        self.anonymous_user.is_authenticated = False

    def test_user_page(self):
        """there are so many views, this just makes sure it LOADS"""
        # extras that are rendered on the user page
        models.AnnualGoal.objects.create(user=self.local_user,
                                         goal=12,
                                         privacy="followers")

        view = views.User.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

        request.user = self.anonymous_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = True
            result = view(request, "mouse")
        self.assertIsInstance(result, ActivitypubResponse)
        self.assertEqual(result.status_code, 200)

    def test_user_page_domain(self):
        """when the user domain has dashes in it"""
        with patch("bookwyrm.models.user.set_remote_server"):
            models.User.objects.create_user(
                "nutria",
                "",
                "nutriaword",
                local=False,
                remote_id="https://ex--ample.co----m/users/nutria",
                inbox="https://ex--ample.co----m/users/nutria/inbox",
                outbox="https://ex--ample.co----m/users/nutria/outbox",
            )

        view = views.User.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "[email protected]")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

    def test_user_page_blocked(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.User.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        self.rat.blocks.add(self.local_user)
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            with self.assertRaises(Http404):
                view(request, "rat")

    def test_followers_page(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Followers.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = True
            result = view(request, "mouse")
        self.assertIsInstance(result, ActivitypubResponse)
        self.assertEqual(result.status_code, 200)

    def test_followers_page_anonymous(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Followers.as_view()
        request = self.factory.get("")
        request.user = self.anonymous_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

    @patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
    @patch("bookwyrm.activitystreams.populate_stream_task.delay")
    def test_followers_page_blocked(self, *_):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Followers.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        self.rat.blocks.add(self.local_user)
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            with self.assertRaises(Http404):
                view(request, "rat")

    def test_following_page(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Following.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = True
            result = view(request, "mouse")
        self.assertIsInstance(result, ActivitypubResponse)
        self.assertEqual(result.status_code, 200)

    def test_following_page_anonymous(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Following.as_view()
        request = self.factory.get("")
        request.user = self.anonymous_user
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            result = view(request, "mouse")
        self.assertIsInstance(result, TemplateResponse)
        validate_html(result.render())
        self.assertEqual(result.status_code, 200)

    def test_following_page_blocked(self):
        """there are so many views, this just makes sure it LOADS"""
        view = views.Following.as_view()
        request = self.factory.get("")
        request.user = self.local_user
        self.rat.blocks.add(self.local_user)
        with patch("bookwyrm.views.user.is_api_request") as is_api:
            is_api.return_value = False
            with self.assertRaises(Http404):
                view(request, "rat")

    def test_hide_suggestions(self):
        """update suggestions settings"""
        self.assertTrue(self.local_user.show_suggested_users)
        request = self.factory.post("")
        request.user = self.local_user

        result = views.hide_suggestions(request)
        self.assertEqual(result.status_code, 302)

        self.local_user.refresh_from_db()
        self.assertFalse(self.local_user.show_suggested_users)

    def test_user_redirect(self):
        """test the basic redirect"""
        request = self.factory.get("@mouse")
        request.user = self.anonymous_user
        result = views.user_redirect(request, "mouse")

        self.assertEqual(result.status_code, 302)
Example #60
0
class ViewTestCase(RepoTestCase):
    fake_search = True

    def setUp(self):
        super(ViewTestCase, self).setUp()
        if self.fake_search:
            Fulltext.FAKE = True
        # Many tests needs access to the request factory.
        self.factory = RequestFactory()
        # Create user
        self.user = create_test_user()
        group = Group.objects.get(name='Users')
        self.user.groups.add(group)
        # Create project to have some test base
        self.component = self.create_component()
        self.project = self.component.project
        # Invalidate caches
        self.project.stats.invalidate()
        cache.clear()
        # Login
        self.client.login(username='******', password='******')
        # Prepopulate kwargs
        self.kw_project = {
            'project': self.project.slug
        }
        self.kw_component = {
            'project': self.project.slug,
            'component': self.component.slug,
        }
        self.kw_translation = {
            'project': self.project.slug,
            'component': self.component.slug,
            'lang': 'cs',
        }
        self.kw_lang_project = {
            'project': self.project.slug,
            'lang': 'cs',
        }

        # Store URL for testing
        self.translation_url = self.get_translation().get_absolute_url()
        self.project_url = self.project.get_absolute_url()
        self.component_url = self.component.get_absolute_url()

    def tearDown(self):
        super(ViewTestCase, self).tearDown()
        if self.fake_search:
            Fulltext.FAKE = False

    def update_fulltext_index(self):
        wait_for_celery()

    def make_manager(self):
        """Make user a Manager."""
        # Sitewide privileges
        self.user.groups.add(
            Group.objects.get(name='Managers')
        )
        # Project privileges
        self.project.add_user(self.user, '@Administration')

    def get_request(self, *args, **kwargs):
        """Wrapper to get fake request object."""
        request = self.factory.get(*args, **kwargs)
        request.user = self.user
        setattr(request, 'session', 'session')
        messages = FallbackStorage(request)
        setattr(request, '_messages', messages)
        return request

    def get_translation(self):
        return self.component.translation_set.get(
            language_code='cs'
        )

    def get_unit(self, source='Hello, world!\n'):
        translation = self.get_translation()
        return translation.unit_set.get(source__startswith=source)

    def change_unit(self, target):
        unit = self.get_unit()
        unit.target = target
        unit.save_backend(self.get_request('/'))

    def edit_unit(self, source, target, **kwargs):
        """Do edit single unit using web interface."""
        unit = self.get_unit(source)
        params = {
            'checksum': unit.checksum,
            'contentsum': hash_to_checksum(unit.content_hash),
            'translationsum': hash_to_checksum(unit.get_target_hash()),
            'target_0': target,
            'review': '20',
        }
        params.update(kwargs)
        return self.client.post(
            self.get_translation().get_translate_url(),
            params
        )

    def assert_redirects_offset(self, response, exp_path, exp_offset):
        """Assert that offset in response matches expected one."""
        self.assertEqual(response.status_code, 302)

        # We don't use all variables
        # pylint: disable=unused-variable
        scheme, netloc, path, query, fragment = urlsplit(response['Location'])

        self.assertEqual(path, exp_path)

        exp_offset = 'offset={0:d}'.format(exp_offset)
        self.assertTrue(
            exp_offset in query,
            'Offset {0} not in {1}'.format(exp_offset, query)
        )

    def assert_png(self, response):
        """Check whether response contains valid PNG image."""
        # Check response status code
        self.assertEqual(response.status_code, 200)
        self.assert_png_data(response.content)

    def assert_png_data(self, content):
        """Check whether data is PNG image"""
        # Try to load PNG with PIL
        image = Image.open(BytesIO(content))
        self.assertEqual(image.format, 'PNG')

    def assert_svg(self, response):
        """Check whether response is a SVG image."""
        # Check response status code
        self.assertEqual(response.status_code, 200)
        dom = minidom.parseString(response.content)
        self.assertEqual(dom.firstChild.nodeName, 'svg')

    def assert_backend(self, expected_translated):
        """Check that backend has correct data."""
        translation = self.get_translation()
        translation.commit_pending('test', None)
        store = translation.component.file_format_cls(
            translation.get_filename(),
            None
        )
        messages = set()
        translated = 0

        for unit in store.all_units():
            if not unit.is_translatable():
                continue
            id_hash = unit.get_id_hash()
            self.assertFalse(
                id_hash in messages,
                'Duplicate string in in backend file!'
            )
            if unit.is_translated():
                translated += 1

        self.assertEqual(
            translated,
            expected_translated,
            'Did not found expected number of ' +
            'translations ({0} != {1}).'.format(
                translated, expected_translated
            )
        )