Ejemplo n.º 1
0
class EventsViewsTest(test_utils.TestCase):
    fixtures = ['calendar.json']

    def setUp(self):
        self.client = LocalizingClient()
        calendar_reload()

    def test_events(self):
        url = reverse('events')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_events_map_flag(self):
        url = reverse('events')

        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)
        doc = pq(r.content)
        eq_([], doc.find('#map_canvas'))
        ok_("maps.google.com" not in r.content)

        events_map_flag = Flag.objects.create(name='events_map', everyone=True)
        events_map_flag.save()

        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)
        doc = pq(r.content)
        eq_(1, len(doc.find('#map_canvas')))
        ok_("maps.google.com" in r.content)
Ejemplo n.º 2
0
class AccountEmailTests(test_utils.TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    def test_account_email_page_requires_signin(self):
        url = reverse('account_email')
        r = self.client.get(url, follow=True)

        eq_(200, r.status_code)
        ok_(len(r.redirect_chain) > 0)
        ok_('Sign In' in r.content)

    def test_account_email_page(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        url = reverse('account_email')
        r = self.client.get(url)
        test_strings = ['Make Primary', 'Re-send Verification', 'Remove',
                        'Add Email', 'Edit profile']

        eq_(200, r.status_code)
        for test_string in test_strings:
            ok_(test_string in r.content)
Ejemplo n.º 3
0
class SocialAccountConnectionsTests(test_utils.TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    def test_account_connections_page_requires_signin(self):
        url = reverse('socialaccount_connections')
        r = self.client.get(url, follow=True)

        eq_(200, r.status_code)
        ok_(len(r.redirect_chain) > 0)
        ok_('Sign In' in r.content)

    def test_account_connections_page(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        url = reverse('socialaccount_connections')
        r = self.client.get(url)
        test_strings = ['Disconnect', 'Connect a new account', 'Edit profile']

        eq_(200, r.status_code)
        for test_string in test_strings:
            ok_(test_string in r.content,
                msg="Expected %s in content" % test_string)
Ejemplo n.º 4
0
def test_breadcrumb():
    """Make sure breadcrumb links start with /."""
    c = LocalizingClient()
    response = c.get(reverse('search'))

    doc = pq(response.content)
    href = doc('.breadcrumbs a')[0]
    eq_('/', href.attrib['href'][0])
Ejemplo n.º 5
0
class LandingViewsTest(test_utils.TestCase):
    fixtures = ['test_data.json', ]

    def setUp(self):
        self.client = LocalizingClient()

    def test_home(self):
        url = reverse('landing.views.home')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_promote_buttons(self):
        url = reverse('landing.views.promote_buttons')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)
Ejemplo n.º 6
0
class ViewTests(TestCase):
    fixtures = ["test_users.json", "wiki/documents.json"]

    def setUp(self):
        self.client = LocalizingClient()

    def mk_request(self, user=None, ip="192.168.123.123", user_agent="FakeBrowser 1.0"):
        request = HttpRequest()
        request.user = user and user or AnonymousUser()
        request.method = "GET"
        request.META["REMOTE_ADDR"] = ip
        request.META["HTTP_USER_AGENT"] = user_agent
        return request

    def test_flagged_view(self):
        request = self.mk_request()
        objects_to_flag = [
            {"obj": save_valid_submission(), "flag_type": "notworking", "explanation": "I am not good at computer."},
            {"obj": Document.objects.get(pk=4), "flag_type": "bad", "explanation": "This is in fact not a pipe."},
            {
                "obj": Document.objects.get(pk=8),
                "flag_type": "unneeded",
                "explanation": "Camels are for Perl, not Python.",
            },
        ]
        for o in objects_to_flag:
            flag, created = ContentFlag.objects.flag(
                request=request, object=o["obj"], flag_type=o["flag_type"], explanation=o["explanation"]
            )
        resp = self.client.get(reverse("contentflagging.flagged"))
        eq_(200, resp.status_code)
Ejemplo n.º 7
0
class HomeTests(test_utils.TestCase):
    def setUp(self):
        self.client = LocalizingClient()

    def test_google_analytics(self):
        url = reverse('landing.views.home')

        with override_constance_settings(GOOGLE_ANALYTICS_ACCOUNT='0'):
            r = self.client.get(url, follow=True)
            eq_(200, r.status_code)
            ok_('ga(\'create' not in r.content)

        with override_constance_settings(GOOGLE_ANALYTICS_ACCOUNT='UA-99999999-9'):
            r = self.client.get(url, follow=True)
            eq_(200, r.status_code)
            ok_('ga(\'create' in r.content)
Ejemplo n.º 8
0
class ViewTests(TestCase):
    fixtures = ['test_users.json', 'wiki/documents.json']

    def setUp(self):
        self.client = LocalizingClient()

    def mk_request(self, user=None, ip='192.168.123.123', 
            user_agent='FakeBrowser 1.0'):
        request = HttpRequest()
        request.user = user and user or AnonymousUser()
        request.method = 'GET'
        request.META['REMOTE_ADDR'] = ip
        request.META['HTTP_USER_AGENT'] = user_agent
        return request

    def test_flagged_view(self):
        request = self.mk_request()
        objects_to_flag = [
            {'obj': save_valid_submission(),
             'flag_type': 'notworking',
             'explanation': 'I am not good at computer.'},
            {'obj': Document.objects.get(pk=4),
             'flag_type': 'bad',
             'explanation': 'This is in fact not a pipe.'},
            {'obj': Document.objects.get(pk=8),
             'flag_type': 'unneeded',
             'explanation': 'Camels are for Perl, not Python.'},
        ]
        for o in objects_to_flag:
            flag, created = ContentFlag.objects.flag(request=request,
                                                     object=o['obj'],
                                                     flag_type=o['flag_type'],
                                                     explanation=o['explanation'])
        resp = self.client.get(reverse('contentflagging.flagged'))
        eq_(200, resp.status_code)
Ejemplo n.º 9
0
class ReminderEmailTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    @mock.patch_object(Site.objects, 'get_current')
    def test_reminder_email(self, get_current):
        """Should send simple email reminder to user."""
        get_current.return_value.domain = 'dev.mo.org'

        response = self.client.post(reverse('users.send_email_reminder'),
                                    {'username': '******'},
                                    follow=True)
        eq_(200, response.status_code)
        eq_(1, len(mail.outbox))
        email = mail.outbox[0]
        assert email.subject.find('Email Address Reminder') == 0
        assert 'testuser' in email.body

    @mock.patch_object(Site.objects, 'get_current')
    def test_unknown_user_no_email_sent(self, get_current):
        """Should send simple email reminder to user."""
        get_current.return_value.domain = 'dev.mo.org'

        response = self.client.post(reverse('users.send_email_reminder'),
                                    {'username': '******'},
                                    follow=True)
        eq_(200, response.status_code)
        eq_(0, len(mail.outbox))

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_without_email_message(self, get_current):
        """Should send simple email reminder to user."""
        get_current.return_value.domain = 'dev.mo.org'

        u = User.objects.get(username='******')
        u.email = ''
        u.save()

        response = self.client.post(reverse('users.send_email_reminder'),
                                    {'username': '******'},
                                    follow=True)
        eq_(200, response.status_code)
        eq_(0, len(mail.outbox))
        ok_('Could not find email' in response.content)
        ok_('file a bug' in response.content)
Ejemplo n.º 10
0
    def test_ban_middleware(self):
        """Ban middleware functions correctly."""
        client = LocalizingClient()
        client.login(username='******', password='******')

        resp = client.get('/')
        self.assertTemplateNotUsed(resp, 'users/user_banned.html')

        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')
        ban = UserBan(user=testuser, by=admin,
                      reason='Banned by unit test.',
                      is_active=True)
        ban.save()

        resp = client.get('/')
        self.assertTemplateUsed(resp, 'users/user_banned.html')
Ejemplo n.º 11
0
class LoginTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.client = LocalizingClient()
        self.client.logout()

    def tearDown(self):
        settings.DEBUG = self.old_debug

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_request_properties(self, get_current):
        '''_clean_next_url checks POST, GET, and REFERER'''
        get_current.return_value.domain = 'dev.mo.org'

        r = RequestFactory().get('/users/login', {'next': '/demos/submit'},
                                 HTTP_REFERER='referer-trumped-by-get')
        eq_('/demos/submit', _clean_next_url(r))
        r = RequestFactory().post('/users/login', {'next': '/demos/submit'})
        eq_('/demos/submit', _clean_next_url(r))
        r = RequestFactory().get('/users/login', HTTP_REFERER='/demos/submit')
        eq_('/demos/submit', _clean_next_url(r))

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_no_self_redirects(self, get_current):
        '''_clean_next_url checks POST, GET, and REFERER'''
        get_current.return_value.domain = 'dev.mo.org'

        for next in [settings.LOGIN_URL, settings.LOGOUT_URL]:
            r = RequestFactory().get('/users/login', {'next': next})
            eq_(None, _clean_next_url(r))

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_invalid_next_parameter(self, get_current):
        '''_clean_next_url cleans invalid urls'''
        get_current.return_value.domain = 'dev.mo.org'

        for next in self._invalid_nexts():
            r = RequestFactory().get('/users/login', {'next': next})
            eq_(None, _clean_next_url(r))

    def _invalid_nexts(self):
        return ['http://foobar.com/evil/', '//goo.gl/y-bad']
Ejemplo n.º 12
0
class AppsViewsTest(SkippedTestCase):

    def setUp(self):
        self.client = LocalizingClient()
        super(AppsViewsTest, self).setUp()

    def _good_newsletter_post(self):
        url = reverse('landing.views.apps_newsletter')

        r = self.client.post(url,
                {'format': 'html',
                 'country': 'pt',
                 'email': '*****@*****.**',
                 'agree': 'checked'},
            follow=True)
        eq_(200, r.status_code)

        return r

    @patch('landing.views.basket.subscribe')
    def test_apps_subscription(self, subscribe):
        subscribe.return_value = {'status': 'success'}
        r = self._good_newsletter_post()
        # assert thank you message
        self.assertContains(r, 'Thank you')
        eq_(1, subscribe.call_count)

    @patch('landing.views.basket.subscribe')
    def test_apps_subscription_bad_values(self, subscribe):
        subscribe.return_value = True
        url = reverse('landing.views.apps_newsletter')
        r = self.client.post(url, {'format': 1, 'email': 'nope'})
        eq_(200, r.status_code)
        # assert error
        self.assertContains(r, 'Enter a valid e-mail address.')
        self.assertContains(r, 'Select a valid choice.')
        self.assertContains(r, 'You must agree to the privacy policy.')

    @patch('landing.views.basket.subscribe')
    def test_apps_subscription_exception_retry(self, subscribe):
        subscribe.side_effect = basket.base.BasketException("500!")
        subscribe.return_value = True
        self._good_newsletter_post()
        eq_(constance.config.BASKET_RETRIES, subscribe.call_count)
Ejemplo n.º 13
0
    def setUp(self):
        # Ensure @ssl_required goes unenforced.
        settings.DEBUG = True
        # Set up some easily-testable redirects.
        settings.LOGIN_REDIRECT_URL = 'SUCCESS'
        settings.LOGIN_REDIRECT_URL_FAILURE = 'FAILURE'
        # BrowserID will squawk if this isn't set
        settings.SITE_URL = 'http://testserver'
        self.client = LocalizingClient()

        # TODO: upgrade mock to 0.8.0 so we can do this.
        """
Ejemplo n.º 14
0
class LandingViewsTest(test_utils.TestCase):
    fixtures = ['test_data.json', ]

    def setUp(self):
        self.client = LocalizingClient()

    def test_home(self):
        url = reverse('landing.views.home')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_search(self):
        raise SkipTest('Search test disabled until we switch to kuma wiki')
        url = reverse('landing.views.search')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_promote_buttons(self):
        url = reverse('landing.views.promote_buttons')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)
Ejemplo n.º 15
0
class DemoListViewsTest(test_utils.TestCase):
    fixtures = ["test_users.json"]

    def setUp(self):
        self.user, self.admin_user, self.other_user = make_users()
        self.client = LocalizingClient()

    def test_all_demos_includes_hidden_for_staff(self):
        build_submission(self.user)
        build_hidden_submission(self.user)

        r = self.client.get(reverse("demos_all"))
        count = pq(r.content)("h2.count").text()
        eq_(count, "1 Demo")

        self.client.login(username=self.admin_user.username, password="******")
        r = self.client.get(reverse("demos_all"))
        count = pq(r.content)("h2.count").text()
        eq_(count, "2 Demos")

    @attr("bug882709")
    def test_search_view(self):
        try:
            self.client.get(reverse("demos_search"))
        except:
            self.fail("Search should not ISE.")
Ejemplo n.º 16
0
    def test_ban_view(self):
        testuser = User.objects.get(username='******')
        admin = User.objects.get(username='******')

        client = LocalizingClient()
        client.login(username='******', password='******')

        data = {'reason': 'Banned by unit test.'}
        ban_url = reverse('users.ban_user',
                          kwargs={'user_id': testuser.id})

        resp = client.post(ban_url, data)
        eq_(302, resp.status_code)
        ok_(testuser.get_absolute_url() in resp['Location'])

        testuser_banned = User.objects.get(username='******')
        ok_(not testuser_banned.is_active)

        bans = UserBan.objects.filter(user=testuser,
                                      by=admin,
                                      reason='Banned by unit test.')
        ok_(bans.count())
Ejemplo n.º 17
0
class LandingViewsTest(test_utils.TestCase):
    fixtures = ['test_data.json']

    def setUp(self):
        self.client = LocalizingClient()

    def test_home(self):
        url = reverse('landing.views.home')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_promote_buttons(self):
        url = reverse('landing.views.promote_buttons')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_contribute_json(self):
        # using the non-localizing client here as contribute.json
        # is not-localizable
        client = Client()
        r = client.get(reverse('contribute_json'))
        eq_(200, r.status_code)
        ok_('application/json' in r['Content-Type'])
Ejemplo n.º 18
0
class LearnViewsTest(test_utils.TestCase):

    def setUp(self):
        self.client = LocalizingClient()

    def test_learn(self):
        url = reverse('landing.views.learn')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_learn_html(self):
        url = reverse('landing.views.learn_html')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_learn_css(self):
        url = reverse('landing.views.learn_css')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)

    def test_learn_javascript(self):
        url = reverse('landing.views.learn_javascript')
        r = self.client.get(url, follow=True)
        eq_(200, r.status_code)
Ejemplo n.º 19
0
    def test_ban_permission(self):
        """The ban permission controls access to the ban view."""
        client = LocalizingClient()
        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')

        # testuser doesn't have ban permission, can't ban.
        client.login(username='******',
                     password='******')
        ban_url = reverse('users.ban_user',
                          kwargs={'user_id': admin.id})
        resp = client.get(ban_url)
        eq_(302, resp.status_code)
        ok_(settings.LOGIN_URL in resp['Location'])
        client.logout()

        # admin has ban permission, can ban.
        client.login(username='******',
                     password='******')
        ban_url = reverse('users.ban_user',
                          kwargs={'user_id': testuser.id})
        resp = client.get(ban_url)
        eq_(200, resp.status_code)
Ejemplo n.º 20
0
    def test_404_already_logged_in(self):
        """The login buttons should not display on the 404 page when the user is logged in"""
        client = LocalizingClient()

        # View page as a logged in user
        client.login(username='******',
                     password='******')
        response = client.get('/something-doesnt-exist', follow=True)
        doc = pq(response.content)

        login_block = doc.find('.socialaccount_providers')
        eq_(len(login_block), 0)
        eq_(404, response.status_code)
        client.logout()
Ejemplo n.º 21
0
 def setUp(self):
     self.user, self.admin_user, self.other_user = make_users()
     self.client = LocalizingClient()
Ejemplo n.º 22
0
 def setUp(self):
     self.client = LocalizingClient()
Ejemplo n.º 23
0
 def setUp(self):
     self.client = LocalizingClient()
Ejemplo n.º 24
0
 def setUp(self):
     super(TestCaseBase, self).setUp()
     self.client = LocalizingClient()
Ejemplo n.º 25
0
class ProfileViewsTest(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.client = LocalizingClient()
        self.client.logout()

    def tearDown(self):
        settings.DEBUG = self.old_debug

    def _get_current_form_field_values(self, doc):
        # Scrape out the existing significant form field values.
        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                   'irc_nickname', 'bio', 'interests', 'country', 'format'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()
        form['country'] = 'us'
        form['format'] = 'html'
        return form

    @attr('docs_activity')
    def test_profile_view(self):
        """A user profile can be viewed"""
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.user.username,
            doc.find('#profile-head.vcard .nickname').text())
        eq_(profile.fullname, doc.find('#profile-head.vcard .fn').text())
        eq_(profile.title, doc.find('#profile-head.vcard .title').text())
        eq_(profile.organization, doc.find('#profile-head.vcard .org').text())
        eq_(profile.location, doc.find('#profile-head.vcard .loc').text())
        eq_('IRC: ' + profile.irc_nickname,
            doc.find('#profile-head.vcard .irc').text())
        eq_(profile.bio, doc.find('#profile-head.vcard .bio').text())

    def test_my_profile_view(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/')
        eq_(302, resp.status_code)
        ok_(
            reverse('devmo.views.profile_view', args=(
                u.username, )) in resp['Location'])

    def test_bug_698971(self):
        """A non-numeric page number should not cause an error"""
        (user, profile) = create_profile()

        url = '%s?page=asdf' % reverse('devmo.views.profile_view',
                                       args=(user.username, ))

        try:
            self.client.get(url, follow=True)
        except PageNotAnInteger:
            ok_(False, "Non-numeric page number should not cause an error")

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(0, doc.find('#profile-head .edit .button').length)

        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_view', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        edit_button = doc.find('#profile-head .edit #edit-profile')
        eq_(1, edit_button.length)

        url = edit_button.attr('href')
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.fullname,
            doc.find('#profile-edit input[name="fullname"]').val())
        eq_(profile.title, doc.find('#profile-edit input[name="title"]').val())
        eq_(profile.organization,
            doc.find('#profile-edit input[name="organization"]').val())
        eq_(profile.location,
            doc.find('#profile-edit input[name="location"]').val())
        eq_(profile.irc_nickname,
            doc.find('#profile-edit input[name="irc_nickname"]').val())

        new_attrs = dict(email='*****@*****.**',
                         fullname="Another Name",
                         title="Another title",
                         organization="Another org",
                         country="us",
                         format="html")

        r = self.client.post(url, new_attrs, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)
        eq_(new_attrs['fullname'], doc.find('#profile-head .main .fn').text())
        eq_(new_attrs['title'], doc.find('#profile-head .info .title').text())
        eq_(new_attrs['organization'],
            doc.find('#profile-head .info .org').text())

        profile = UserProfile.objects.get(user__username=user.username)
        eq_(new_attrs['fullname'], profile.fullname)
        eq_(new_attrs['title'], profile.title)
        eq_(new_attrs['organization'], profile.organization)

    def test_my_profile_edit(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/edit')
        eq_(302, resp.status_code)
        ok_(
            reverse('devmo.views.profile_edit', args=(
                u.username, )) in resp['Location'])

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_beta(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(None, doc.find('input#id_beta').attr('checked'))

        form = self._get_current_form_field_values(doc)
        form['beta'] = True

        r = self.client.post(url, form, follow=True)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_('checked', doc.find('input#id_beta').attr('checked'))

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_websites(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True

        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_sites = {
            u'website': u'http://example.com/',
            u'twitter': u'http://twitter.com/lmorchard',
            u'github': u'http://github.com/lmorchard',
            u'stackoverflow': u'http://stackoverflow.com/users/lmorchard',
            u'linkedin': u'https://www.linkedin.com/in/testuser',
            u'mozillians': u'https://mozillians.org/u/testuser',
            u'facebook': u'https://www.facebook.com/test.user'
        }

        form = self._get_current_form_field_values(doc)

        # Fill out the form with websites.
        form.update(dict(
            ('websites_%s' % k, v) for k, v in test_sites.items()))

        # Submit the form, verify redirect to profile detail
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        # Verify the websites are saved in the profile.
        eq_(test_sites, p.websites)

        # Verify the saved websites appear in the editing form
        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        for k, v in test_sites.items():
            eq_(v, doc.find('#profile-edit *[name="websites_%s"]' % k).val())

        # Come up with some bad sites, either invalid URL or bad URL prefix
        bad_sites = {
            u'website': u'HAHAHA WHAT IS A WEBSITE',
            u'twitter': u'http://facebook.com/lmorchard',
            u'stackoverflow': u'http://overqueueblah.com/users/lmorchard',
        }
        form.update(dict(('websites_%s' % k, v) for k, v in bad_sites.items()))

        # Submit the form, verify errors for all of the bad sites
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-edit').length)
        tmpl = '#profile-edit #elsewhere .%s .errorlist'
        for n in ('website', 'twitter', 'stackoverflow'):
            eq_(1, doc.find(tmpl % n).length)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_interests(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True

        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = ['javascript', 'css', 'canvas', 'html', 'homebrewing']

        form = self._get_current_form_field_values(doc)

        form['interests'] = ', '.join(test_tags)

        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:interest:', '')
            for t in p.tags.all_ns('profile:interest:')
        ]
        result_tags.sort()
        test_tags.sort()
        eq_(test_tags, result_tags)

        test_expertise = ['css', 'canvas']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [
            t.name.replace('profile:expertise:', '')
            for t in p.tags.all_ns('profile:expertise')
        ]
        result_tags.sort()
        test_expertise.sort()
        eq_(test_expertise, result_tags)

        # Now, try some expertise tags not covered in interests
        test_expertise = ['css', 'canvas', 'mobile', 'movies']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('.error #id_expertise').length)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_bug_709938_interests(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = [
            u'science,Technology,paradox,knowledge,modeling,big data,'
            u'vector,meme,heuristics,harmony,mathesis universalis,'
            u'symmetry,mathematics,computer graphics,field,chemistry,'
            u'religion,astronomy,physics,biology,literature,'
            u'spirituality,Art,Philosophy,Psychology,Business,Music,'
            u'Computer Science'
        ]

        form = self._get_current_form_field_values(doc)

        form['interests'] = test_tags

        r = self.client.post(url, form, follow=True)
        eq_(200, r.status_code)
        doc = pq(r.content)
        eq_(1, doc.find('ul.errorlist li').length)
        assert ('Ensure this value has at most 255 characters'
                in doc.find('ul.errorlist li').text())

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_bug_698126_l10n(self, unsubscribe, subscribe, lookup_user):
        """Test that the form field names are localized"""
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username, password=TESTUSER_PASSWORD)

        url = reverse('devmo.views.profile_edit', args=(user.username, ))
        r = self.client.get(url, follow=True)
        for field in r.context['form'].fields:
            # if label is localized it's a lazy proxy object
            ok_(
                not isinstance(r.context['form'].fields[field].label,
                               basestring), 'Field %s is a string!' % field)

    def _break(self, url, r):
        logging.debug("URL  %s" % url)
        logging.debug("STAT %s" % r.status_code)
        logging.debug("HEAD %s" % r.items())
        logging.debug("CONT %s" % r.content)
        ok_(False)
Ejemplo n.º 26
0
class BrowserIDTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        # Ensure @ssl_required goes unenforced.
        settings.DEBUG = True
        # Set up some easily-testable redirects.
        settings.LOGIN_REDIRECT_URL = 'SUCCESS'
        settings.LOGIN_REDIRECT_URL_FAILURE = 'FAILURE'
        # BrowserID will squawk if this isn't set
        settings.SITE_URL = 'http://testserver'
        self.client = LocalizingClient()

        # TODO: upgrade mock to 0.8.0 so we can do this.
        """
        self.lookup = mock.patch('basket.lookup_user')
        self.subscribe = mock.patch('basket.subscribe')
        self.unsubscribe = mock.patch('basket.unsubscribe')

        self.lookup.return_value = mock_lookup_user()
        self.subscribe.return_value = True
        self.unsubscribe.return_value = True

        self.lookup.start()
        self.subscribe.start()
        self.unsubscribe.start()

    def tearDown(self):
        self.lookup.stop()
        self.subscribe.stop()
        self.unsubscribe.stop()
        """

    def test_invalid_post(self):
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'))
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock.patch('users.views._verify_browserid')
    def test_invalid_assertion(self, _verify_browserid):
        _verify_browserid.return_value = None

        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'bad data'})
        eq_(302, resp.status_code)
        ok_('FAILURE' in resp['Location'])

    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_django_user(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('SUCCESS' in resp['Location'])

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

    @mock.patch('users.views._verify_browserid')
    def test_explain_popup(self, _verify_browserid):
        _verify_browserid.return_value = {'email': '*****@*****.**'}
        resp = self.client.get(reverse('home', locale='en-US'))

        # Posting the fake assertion to browserid_verify should work, with the
        # actual verification method mocked out.
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_('1', resp.cookies.get('browserid_explained').value)

        resp = self.client.get(reverse('users.logout'), locale='en-US')

        # even after logout, cookie should prevent the toggle
        resp = self.client.get(reverse('home', locale='en-US'))
        eq_('1', self.client.cookies.get('browserid_explained').value)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    @mock.patch('users.views._verify_browserid')
    @override_settings(CELERY_ALWAYS_EAGER=True)
    def test_valid_assertion_with_new_account_creation(self,
                                                       _verify_browserid,
                                                       unsubscribe,
                                                       subscribe,
                                                       lookup_user):
        Switch.objects.create(name='welcome_email', active=True)

        new_username = '******'
        new_email = '*****@*****.**'
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        _verify_browserid.return_value = {'email': new_email}

        try:
            user = User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#create_user')
        eq_(1, form.length)

        # There should be no error lists on first load
        eq_(0, page.find('.errorlist').length)

        # Submit the create_user form, with a chosen username
        resp = self.client.post(redir_url, {'username': '******',
                                            'action': 'register',
                                            'country': 'us',
                                            'format': 'html'})

        # The submission should result in a redirect to the session's redirect
        # value
        eq_(302, resp.status_code)
        redir_url = resp['Location']
        ok_('SUCCESS' in redir_url)

        # The session should look logged in, now.
        ok_('_auth_user_id' in self.client.session.keys())
        eq_('django_browserid.auth.BrowserIDBackend',
            self.client.session.get('_auth_user_backend', ''))

        # Ensure that the user was created, and with the submitted username and
        # verified email address
        try:
            user = User.objects.get(email=new_email)
            eq_(new_username, user.username)
            eq_(new_email, user.email)
        except User.DoesNotExist:
            ok_(False, "New user should have been created")

        # Ensure the user was sent a welcome email
        welcome_email = mail.outbox[0]
        expected_subject = u'Take the next step to get involved on MDN!'
        expected_to = [new_email]
        eq_(expected_subject, welcome_email.subject)
        eq_(expected_to, welcome_email.to)
        ok_(u'Hi %s' % new_username in welcome_email.body)

    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_with_existing_account_login(self,
                                                         _verify_browserid):
        """ Removed the existing user form: we don't auth the password with
        MindTouch anymore """
        new_email = '*****@*****.**'
        _verify_browserid.return_value = {'email': new_email}

        try:
            User.objects.get(email=new_email)
            ok_(False, "User for email should not yet exist")
        except User.DoesNotExist:
            pass

        # Sign in with a verified email, but with no existing account
        resp = self.client.post(reverse('users.browserid_verify',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)

        # This should be a redirect to the BrowserID registration page.
        redir_url = resp['Location']
        reg_url = reverse('users.browserid_register', locale='en-US')
        ok_(reg_url in redir_url)

        # And, as part of the redirect, the verified email address should be in
        # our session now.
        ok_(SESSION_VERIFIED_EMAIL in self.client.session.keys())
        verified_email = self.client.session[SESSION_VERIFIED_EMAIL]
        eq_(new_email, verified_email)

        # Grab the redirect, assert that there's a create_user form present
        resp = self.client.get(redir_url)
        page = pq(resp.content)
        form = page.find('form#existing_user')
        eq_(0, form.length)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_changing_email(self, _verify_browserid,
                                                        unsubscribe,
                                                        subscribe,
                                                        lookup_user):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        resp = self.client.post(reverse('users.browserid_change_email',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('profiles/testuser/edit' in resp['Location'])

        resp = self.client.get(reverse('devmo_profile_edit', locale='en-US',
                                       args=['testuser', ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    @mock.patch('users.views._verify_browserid')
    def test_valid_assertion_doesnt_steal_email(self, _verify_browserid,
                                                        unsubscribe,
                                                        subscribe,
                                                        lookup_user):
        # just need to be authenticated, not necessarily BrowserID
        self.client.login(username='******', password='******')

        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        _verify_browserid.return_value = {'email': '*****@*****.**'}

        # doesn't change email if the new email already belongs to another user
        resp = self.client.post(reverse('users.browserid_change_email',
                                        locale='en-US'),
                                {'assertion': 'PRETENDTHISISVALID'})
        eq_(302, resp.status_code)
        ok_('change_email' in resp['Location'])

        resp = self.client.get(reverse('devmo_profile_edit', locale='en-US',
                                       args=['testuser', ]))
        eq_(200, resp.status_code)
        doc = pq(resp.content)
        ok_('*****@*****.**' in doc.find('li#field_email').text())
Ejemplo n.º 27
0
 def setUp(self):
     self.old_debug = settings.DEBUG
     settings.DEBUG = True
     self.client = LocalizingClient()
     self.client.logout()
Ejemplo n.º 28
0
class DemoViewsTest(test_utils.TestCase):
    fixtures = ["test_users.json"]

    def setUp(self):
        self.testuser = User.objects.get(username="******")
        self.testuser.set_password(TESTUSER_PASSWORD)
        self.testuser.save()
        self.client = LocalizingClient()

    def test_submit_loggedout(self):
        r = self.client.get(reverse("demos_submit"))
        choices = pq(r.content)('p.choices a[href*="login"]')
        eq_(choices.length, 1)

    @logged_in
    def test_submit_loggedin(self):
        r = self.client.get(reverse("demos_submit"))
        assert pq(r.content)("form#demo-submit")

    @logged_in
    def test_submit_post_invalid(self):
        r = self.client.post(reverse("demos_submit"), data={})
        d = pq(r.content)
        assert d("form#demo-submit")
        assert d("li#field_title ul.errorlist")
        assert d("li#field_summary ul.errorlist")
        assert d("li#field_screenshot_1 ul.errorlist")
        assert d("li#field_demo_package ul.errorlist")
        assert d("li#field_license_name ul.errorlist")
        assert d("li#field_captcha ul.errorlist")
        assert d("li#field_accept_terms ul.errorlist")

    @logged_in
    @disable_captcha
    def test_submit_post_valid(self):

        # Create a valid demo zip file
        zf_fout = StringIO()
        zf = zipfile.ZipFile(zf_fout, "w")
        zf.writestr("index.html", """<html></html>""")
        zf.close()

        # Create a new file for input
        zf_fin = StringIO(zf_fout.getvalue())
        zf_fin.name = "demo.zip"

        r = self.client.post(
            reverse("demos_submit"),
            data=dict(
                title="Test submission",
                summary="This is a test demo submission",
                description="Some description goes here",
                tech_tags=("tech:audio", "tech:video", "tech:websockets"),
                screenshot_1=open(SCREENSHOT_PATH),
                demo_package=zf_fin,
                license_name="gpl",
                accept_terms="1",
            ),
        )

        eq_(302, r.status_code)
        assert "Location" in r
        assert "test-submission" in r["Location"]

        try:
            obj = Submission.objects.get(slug="test-submission")
            eq_("Test submission", obj.title)
        except Submission.DoesNotExist:
            assert False

        result_tags = [t.name for t in obj.taggit_tags.all_ns("tech:")]
        result_tags.sort()
        eq_(["tech:audio", "tech:video", "tech:websockets"], result_tags)

    @logged_in
    def test_edit_invalid(self):
        s = save_valid_submission()
        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.post(edit_url, data=dict())
        d = pq(r.content)
        assert d("form#demo-submit")
        assert d("li#field_title ul.errorlist")
        assert d("li#field_summary ul.errorlist")
        assert d("li#field_license_name ul.errorlist")

    @logged_in
    def test_edit_valid(self):
        s = save_valid_submission()
        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.post(
            edit_url,
            data=dict(
                title=s.title,
                summary="This is a test demo submission",
                description="Some description goes here",
                tech_tags=("tech:audio", "tech:video", "tech:websockets"),
                license_name="gpl",
                accept_terms="1",
            ),
        )

        eq_(302, r.status_code)
        assert "Location" in r
        assert "hello-world" in r["Location"]

        try:
            obj = Submission.objects.get(slug="hello-world")
            eq_("This is a test demo submission", obj.summary)
        except Submission.DoesNotExist:
            assert False

    def test_detail(self):
        s = save_valid_submission("hello world")

        url = reverse("demos_detail", args=[s.slug])
        r = self.client.get(url)
        d = pq(r.content)
        eq_(s.title, d("h1.page-title").text())
        edit_link = d("ul.manage a.edit")
        assert not edit_link

    def test_detail_censored(self):
        s = save_valid_submission("hello world")
        s.censored = True
        s.save()

        url = reverse("demos_detail", args=[s.slug])
        r = self.client.get(url)
        d = pq(r.content)
        eq_("Permission Denied", d("h1.page-title").text())

    def test_detail_censored_url(self):
        s = save_valid_submission("hello world")
        s.censored = True
        s.censored_url = "http://developer.mozilla.org"
        s.save()

        url = reverse("demos_detail", args=[s.slug])
        r = self.client.get(url)
        eq_(302, r.status_code)
        eq_("http://developer.mozilla.org", r["Location"])

    @logged_in
    def test_creator_can_edit(self):
        s = save_valid_submission("hello world")

        url = reverse("demos_detail", args=[s.slug])
        r = self.client.get(url)
        d = pq(r.content)
        edit_link = d("ul#demo-manage a.edit")
        assert edit_link
        edit_url = reverse("demos_edit", args=[s.slug], locale="en-US")
        eq_(edit_url, edit_link.attr("href"))

        r = self.client.get(edit_url)
        assert pq(r.content)("form#demo-submit")
        eq_("Save changes", pq(r.content)('p.fm-submit button[type="submit"]').text())

    @logged_in
    def test_hidden_field(self):
        s = save_valid_submission("hello world")

        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.get(edit_url)
        assert pq(r.content)('input[name="hidden"][type="checkbox"]')

    @logged_in
    def test_derby_field(self):
        s = save_valid_submission("hello world")

        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.get(edit_url)
        assert pq(r.content)("fieldset#devderby-submit")

    @logged_in
    def test_edit_no_tags(self):
        s = save_valid_submission("hello world")
        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.post(
            edit_url,
            data=dict(
                title=s.title,
                summary="This is a test edit",
                description="Some description goes here",
                license_name="gpl",
                accept_terms="1",
            ),
        )
        eq_(r.status_code, 302)
        r = self.client.get(edit_url)
        eq_(r.status_code, 200)

    @logged_in
    def test_edit_with_challenge_tag(self):
        s = save_valid_submission("hello world")
        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.post(
            edit_url,
            data=dict(
                title=s.title,
                summary="This is a test edit",
                description="Some description goes here",
                tech_tags=("tech:audio",),
                challenge_tags=parse_tags(constance.config.DEMOS_DEVDERBY_CHALLENGE_CHOICE_TAGS)[0],
                license_name="gpl",
                accept_terms="1",
            ),
        )
        eq_(r.status_code, 302)
        r = self.client.get(edit_url)
        eq_(r.status_code, 200)

    def test_challenge_tag_to_date_parts(self):
        tag = "challenge:2011:october"
        eq_(challenge_utils.challenge_tag_to_date_parts(tag), (2011, 10))

    def test_challenge_tag_to_end_date(self):
        tag = "challenge:2011:october"
        eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 10, 31))
        tag = "challenge:2011:february"
        eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2011, 2, 28))
        tag = "challenge:2012:february"
        eq_(challenge_utils.challenge_tag_to_end_date(tag), datetime.date(2012, 2, 29))

    def test_challenge_closed(self):
        open_tag = "challenge:%s" % make_challenge_tag()
        closed_dt = datetime.date.today() - datetime.timedelta(days=32)
        closed_tag = "challenge:%s" % closed_dt.strftime("%Y:%B").lower()
        assert not challenge_utils.challenge_closed([open_tag])
        assert challenge_utils.challenge_closed([closed_tag])

    def test_challenge_closed_model(self):
        s = save_valid_submission("hellow world")
        assert not s.challenge_closed()
        s.taggit_tags.set_ns("challenge:", make_challenge_tag())
        assert not s.challenge_closed()
        closed_dt = datetime.date.today() - datetime.timedelta(days=32)
        s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower())
        assert s.challenge_closed()

    def test_derby_before_deadline(self):
        s = save_valid_submission("hello world")
        s.taggit_tags.set_ns("challenge:", make_challenge_tag())
        form = SubmissionEditForm(instance=s)
        assert "demo_package" in form.fields
        assert "challenge_tags" in form.fields

    def test_derby_after_deadline(self):
        s = save_valid_submission("hello world")
        closed_dt = datetime.date.today() - datetime.timedelta(days=32)
        s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower())
        form = SubmissionEditForm(instance=s)
        assert "demo_package" not in form.fields
        assert "challenge_tags" not in form.fields

    @logged_in
    def test_derby_tag_saving(self):
        """
        There's some tricky bits in the handling of editing and saving
        challenge tags; this test just exercises a cycle of edit/save
        a couple times in a row to make sure we don't go foul in
        there.

        """
        s = save_valid_submission("hello world")
        closed_dt = datetime.date.today() - datetime.timedelta(days=32)
        s.taggit_tags.set_ns("challenge:", closed_dt.strftime("%Y:%B").lower())
        edit_url = reverse("demos_edit", args=[s.slug])
        r = self.client.get(edit_url)
        eq_(r.status_code, 200)

        r = self.client.post(
            edit_url,
            data=dict(
                title=s.title,
                summary="This is a test demo submission",
                description="Some description goes here",
                tech_tags=("tech:audio", "tech:video", "tech:websockets"),
                license_name="gpl",
                accept_terms="1",
            ),
        )

        eq_(302, r.status_code)
        assert "Location" in r
        assert s.slug in r["Location"]

        r = self.client.get(edit_url)
        eq_(r.status_code, 200)

        r = self.client.post(
            edit_url,
            data=dict(
                title=s.title,
                summary="This is a test demo submission",
                description="Some description goes here",
                tech_tags=("tech:audio", "tech:video", "tech:websockets"),
                license_name="gpl",
                accept_terms="1",
            ),
        )

        eq_(302, r.status_code)
        assert "Location" in r
        assert s.slug in r["Location"]

        r = self.client.get(edit_url)
        eq_(r.status_code, 200)

    @attr("bug702156")
    def test_missing_screenshots_no_exceptions(self):
        """Demo with missing screenshots should not cause exceptions in
        views"""
        # Create the submission...
        s = save_valid_submission("hello world")
        s.taggit_tags.set_ns("tech:", "javascript")
        s.featured = True
        s.save()

        # Ensure the new screenshot and thumbnail URL code works when there's a
        # screenshot present.
        try:
            r = self.client.get(reverse("demos_all"))
            r = self.client.get(reverse("demos_tag", args=["tech:javascript"]))
            r = self.client.get(reverse("demos_detail", args=[s.slug]))
            r = self.client.get(reverse("demos_feed_recent", args=["atom"]))
            r = self.client.get(reverse("demos_feed_featured", args=["json"]))
        except:
            ok_(False, "No exceptions should have been thrown")

        # Forcibly delete the screenshot - should not be possible from
        # user-facing UI per form validation, but we should at least not throw
        # exceptions.
        s.screenshot_1.storage.delete(s.screenshot_1.name)
        s.screenshot_1 = None
        s.save()

        # Big bucks, no whammies...
        try:
            r = self.client.get(reverse("demos_all"))
            r = self.client.get(reverse("demos_tag", args=["tech:javascript"]))
            r = self.client.get(reverse("demos_detail", args=[s.slug]))
            r = self.client.get(reverse("demos_feed_recent", args=["atom"]))
            r = self.client.get(reverse("demos_feed_featured", args=["json"]))
        except:
            ok_(False, "No exceptions should have been thrown")

    @attr("bug745902")
    def test_long_slug(self):
        """
        A title longer than 50 characters should truncate to a
        50-character slug during (python-level) save, not on DB
        insertion, so that anything that wants the slug to build a URL
        has the value that actually ends up in the DB.

        """
        s = save_valid_submission("AudioVisualizer for Alternative Music Notation Systems")
        s.taggit_tags.set_ns("tech:", "javascript")
        s.save()
        ok_(len(s.slug) == 50)
        r = self.client.get(reverse("demos.views.detail", args=(s.slug,)))
        ok_(r.status_code == 200)

    @attr("bug781823")
    def test_unicode(self):
        """
        Unicode characters in the summary or description doesn't brick the feed
        """
        s = save_valid_submission("ΦOTOS ftw", "ΦOTOS ΦOTOS ΦOTOS")
        s.featured = 1
        s.save()
        r = self.client.get(reverse("demos_feed_featured", args=["json"]))
        ok_(r.status_code == 200)

    def test_make_unique_slug(self):
        """
        Ensure that unique slugs are generated even from titles whose
        first 50 characters are identical.
        """
        s = save_valid_submission(
            "This is a really long title whose only purpose in life is to be " "longer than fifty characters"
        )
        s2 = save_valid_submission(
            "This is a really long title whose only purpose in life is to be "
            "longer than fifty characters and not the same as the first title"
        )
        s3 = save_valid_submission(
            "This is a really long title whose only purpose in life is to be "
            "longer than fifty characters and not the same as the first or "
            "second title"
        )
        ok_(s.slug != s2.slug and s.slug != s3.slug and s2.slug != s3.slug)
Ejemplo n.º 29
0
class ProfileViewsTest(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.client = LocalizingClient()
        self.client.logout()

    def tearDown(self):
        settings.DEBUG = self.old_debug

    def _get_current_form_field_values(self, doc):
        # Scrape out the existing significant form field values.
        form = dict()
        for fn in ('email', 'fullname', 'title', 'organization', 'location',
                   'irc_nickname', 'bio', 'interests', 'country', 'format'):
            form[fn] = doc.find('#profile-edit *[name="%s"]' % fn).val()
        form['country'] = 'us'
        form['format'] = 'html'
        return form

    @attr('docs_activity')
    def test_profile_view(self):
        """A user profile can be viewed"""
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('users.profile', args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.user.username,
            doc.find('#profile-head.vcard .nickname').text())
        eq_(profile.fullname,
            doc.find('#profile-head.vcard .fn').text())
        eq_(profile.title,
            doc.find('#profile-head.vcard .title').text())
        eq_(profile.organization,
            doc.find('#profile-head.vcard .org').text())
        eq_(profile.location,
            doc.find('#profile-head.vcard .loc').text())
        eq_('IRC: ' + profile.irc_nickname,
            doc.find('#profile-head.vcard .irc').text())
        eq_(profile.bio,
            doc.find('#profile-head.vcard .bio').text())

    def test_my_profile_view(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/')
        eq_(302, resp.status_code)
        ok_(reverse('users.profile', args=(u.username,)) in
            resp['Location'])

    def test_bug_698971(self):
        """A non-numeric page number should not cause an error"""
        (user, profile) = create_profile()

        url = '%s?page=asdf' % reverse('users.profile', args=(user.username,))

        try:
            self.client.get(url, follow=True)
        except PageNotAnInteger:
            ok_(False, "Non-numeric page number should not cause an error")

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit(self,
                            unsubscribe,
                            subscribe,
                            lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('users.profile', args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(0, doc.find('#profile-head .edit .button').length)

        self.client.login(username=user.username,
                password=TESTUSER_PASSWORD)

        url = reverse('users.profile', args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        edit_button = doc.find('#profile-head .edit #edit-profile')
        eq_(1, edit_button.length)

        url = edit_button.attr('href')
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        eq_(profile.fullname,
            doc.find('#profile-edit input[name="fullname"]').val())
        eq_(profile.title,
            doc.find('#profile-edit input[name="title"]').val())
        eq_(profile.organization,
            doc.find('#profile-edit input[name="organization"]').val())
        eq_(profile.location,
            doc.find('#profile-edit input[name="location"]').val())
        eq_(profile.irc_nickname,
            doc.find('#profile-edit input[name="irc_nickname"]').val())

        new_attrs = dict(
            email='*****@*****.**',
            fullname="Another Name",
            title="Another title",
            organization="Another org",
            country="us",
            format="html"
        )

        r = self.client.post(url, new_attrs, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)
        eq_(new_attrs['fullname'],
            doc.find('#profile-head .main .fn').text())
        eq_(new_attrs['title'],
            doc.find('#profile-head .info .title').text())
        eq_(new_attrs['organization'],
            doc.find('#profile-head .info .org').text())

        profile = UserProfile.objects.get(user__username=user.username)
        eq_(new_attrs['fullname'], profile.fullname)
        eq_(new_attrs['title'], profile.title)
        eq_(new_attrs['organization'], profile.organization)

    def test_my_profile_edit(self):
        u = User.objects.get(username='******')
        self.client.login(username=u.username, password=TESTUSER_PASSWORD)
        resp = self.client.get('/profile/edit')
        eq_(302, resp.status_code)
        ok_(reverse('users.profile_edit', args=(u.username,)) in
            resp['Location'])

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_beta(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username,
                          password=TESTUSER_PASSWORD)

        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_(None, doc.find('input#id_beta').attr('checked'))

        form = self._get_current_form_field_values(doc)
        form['beta'] = True

        r = self.client.post(url, form, follow=True)

        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        eq_('checked', doc.find('input#id_beta').attr('checked'))

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_websites(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True

        user = User.objects.get(username='******')
        self.client.login(username=user.username,
                password=TESTUSER_PASSWORD)

        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_sites = {
            u'website': u'http://example.com/',
            u'twitter': u'http://twitter.com/lmorchard',
            u'github': u'http://github.com/lmorchard',
            u'stackoverflow': u'http://stackoverflow.com/users/lmorchard',
            u'linkedin': u'https://www.linkedin.com/in/testuser',
            u'mozillians': u'https://mozillians.org/u/testuser',
            u'facebook': u'https://www.facebook.com/test.user'
        }

        form = self._get_current_form_field_values(doc)

        # Fill out the form with websites.
        form.update(dict(('websites_%s' % k, v)
                    for k, v in test_sites.items()))

        # Submit the form, verify redirect to profile detail
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        # Verify the websites are saved in the profile.
        eq_(test_sites, p.websites)

        # Verify the saved websites appear in the editing form
        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)
        for k, v in test_sites.items():
            eq_(v, doc.find('#profile-edit *[name="websites_%s"]' % k).val())

        # Come up with some bad sites, either invalid URL or bad URL prefix
        bad_sites = {
            u'website': u'HAHAHA WHAT IS A WEBSITE',
            u'twitter': u'http://facebook.com/lmorchard',
            u'stackoverflow': u'http://overqueueblah.com/users/lmorchard',
        }
        form.update(dict(('websites_%s' % k, v)
                    for k, v in bad_sites.items()))

        # Submit the form, verify errors for all of the bad sites
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-edit').length)
        tmpl = '#profile-edit #elsewhere .%s .errorlist'
        for n in ('website', 'twitter', 'stackoverflow'):
            eq_(1, doc.find(tmpl % n).length)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_profile_edit_interests(self,
                                    unsubscribe,
                                    subscribe,
                                    lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True

        user = User.objects.get(username='******')
        self.client.login(username=user.username,
                password=TESTUSER_PASSWORD)

        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = ['javascript', 'css', 'canvas', 'html', 'homebrewing']

        form = self._get_current_form_field_values(doc)

        form['interests'] = ', '.join(test_tags)

        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)
        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [t.name.replace('profile:interest:', '')
                for t in p.tags.all_ns('profile:interest:')]
        result_tags.sort()
        test_tags.sort()
        eq_(test_tags, result_tags)

        test_expertise = ['css', 'canvas']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('#profile-head').length)

        p = UserProfile.objects.get(user=user)

        result_tags = [t.name.replace('profile:expertise:', '')
                for t in p.tags.all_ns('profile:expertise')]
        result_tags.sort()
        test_expertise.sort()
        eq_(test_expertise, result_tags)

        # Now, try some expertise tags not covered in interests
        test_expertise = ['css', 'canvas', 'mobile', 'movies']
        form['expertise'] = ', '.join(test_expertise)
        r = self.client.post(url, form, follow=True)
        doc = pq(r.content)

        eq_(1, doc.find('.error #id_expertise').length)

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_bug_709938_interests(self, unsubscribe, subscribe, lookup_user):
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username,
                password=TESTUSER_PASSWORD)

        url = reverse('users.profile_edit',
                      args=(user.username,))
        r = self.client.get(url, follow=True)
        doc = pq(r.content)

        test_tags = [u'science,Technology,paradox,knowledge,modeling,big data,'
                     u'vector,meme,heuristics,harmony,mathesis universalis,'
                     u'symmetry,mathematics,computer graphics,field,chemistry,'
                     u'religion,astronomy,physics,biology,literature,'
                     u'spirituality,Art,Philosophy,Psychology,Business,Music,'
                     u'Computer Science']

        form = self._get_current_form_field_values(doc)

        form['interests'] = test_tags

        r = self.client.post(url, form, follow=True)
        eq_(200, r.status_code)
        doc = pq(r.content)
        eq_(1, doc.find('ul.errorlist li').length)
        assert ('Ensure this value has at most 255 characters'
                in doc.find('ul.errorlist li').text())

    @mock.patch('basket.lookup_user')
    @mock.patch('basket.subscribe')
    @mock.patch('basket.unsubscribe')
    def test_bug_698126_l10n(self, unsubscribe, subscribe, lookup_user):
        """Test that the form field names are localized"""
        lookup_user.return_value = mock_lookup_user()
        subscribe.return_value = True
        unsubscribe.return_value = True
        user = User.objects.get(username='******')
        self.client.login(username=user.username,
            password=TESTUSER_PASSWORD)

        url = reverse('users.profile_edit',
            args=(user.username,))
        r = self.client.get(url, follow=True)
        for field in r.context['form'].fields:
            # if label is localized it's a lazy proxy object
            ok_(not isinstance(
                r.context['form'].fields[field].label, basestring),
                'Field %s is a string!' % field)

    def _break(self, url, r):
        logging.debug("URL  %s" % url)
        logging.debug("STAT %s" % r.status_code)
        logging.debug("HEAD %s" % r.items())
        logging.debug("CONT %s" % r.content)
        ok_(False)

    def test_bug_811751_banned_profile(self):
        """A banned user's profile should not be viewable"""
        profile = UserProfile.objects.get(user__username='******')
        user = profile.user
        url = reverse('users.profile', args=(user.username,))

        # Profile viewable if not banned
        response = self.client.get(url, follow=True)
        self.assertNotEqual(response.status_code, 403)

        # Ban User
        admin = User.objects.get(username='******')
        testuser = User.objects.get(username='******')
        ban = UserBan(user=testuser, by=admin,
                      reason='Banned by unit test.',
                      is_active=True)
        ban.save()

        # Profile not viewable if banned
        response = self.client.get(url, follow=True)
        self.assertEqual(response.status_code, 403)

        # Admin can view banned user's profile
        self.client.login(username='******', password='******')
        response = self.client.get(url, follow=True)
        self.assertNotEqual(response.status_code, 403)
Ejemplo n.º 30
0
 def setUp(self):
     self.testuser = User.objects.get(username="******")
     self.testuser.set_password(TESTUSER_PASSWORD)
     self.testuser.save()
     self.client = LocalizingClient()
Ejemplo n.º 31
0
class LoginTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.old_debug = settings.DEBUG
        settings.DEBUG = True
        self.client = LocalizingClient()
        self.client.logout()

    def tearDown(self):
        settings.DEBUG = self.old_debug

    @mock.patch_object(Site.objects, 'get_current')
    def test_bad_login_fails_both_backends(self, get_current):
        get_current.return_value.domain = 'dev.mo.org'
        self.assertRaises(User.DoesNotExist, User.objects.get,
                          username='******')

        response = self.client.post(reverse('users.login'),
                                    {'username': '******',
                                     'password': '******'}, follow=True)
        eq_(200, response.status_code)
        self.assertContains(response, 'Please enter a correct username and '
                                      'password.')

    @mock.patch_object(Site.objects, 'get_current')
    def test_django_login(self, get_current):
        get_current.return_value.domain = 'dev.mo.org'

        response = self.client.post(reverse('users.login'),
                                    {'username': '******',
                                     'password': '******'}, follow=True)
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('testuser', doc.find('ul.user-state a:first').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_django_login_wont_redirect_to_login(self, get_current):
        get_current.return_value.domain = 'dev.mo.org'
        login_uri = reverse('users.login')

        response = self.client.post(login_uri,
                                    {'username': '******',
                                     'password': '******',
                                     'next': login_uri},
                                    follow=True)
        eq_(200, response.status_code)
        for redirect_url, code in response.redirect_chain:
            ok_(login_uri not in redirect_url, "Found %s in redirect_chain"
                % login_uri)
        doc = pq(response.content)
        eq_('testuser', doc.find('ul.user-state a:first').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_logged_in_message(self, get_current):
        get_current.return_value.domain = 'dev.mo.org'
        login_uri = reverse('users.login')

        response = self.client.post(login_uri,
                                    {'username': '******',
                                     'password': '******'},
                                    follow=True)
        eq_(200, response.status_code)
        response = self.client.get(login_uri, follow=True)
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_("You are already logged in.", doc.find('article').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_django_login_redirects_to_next(self, get_current):
        get_current.return_value.domain = 'dev.mo.org'
        login_uri = reverse('users.login')

        response = self.client.post(login_uri,
                                    {'username': '******',
                                     'password': '******'},
                                    follow=True)
        eq_(200, response.status_code)
        response = self.client.get(login_uri, {'next': '/en-US/demos/submit'},
                                   follow=True)
        eq_('http://testserver/en-US/demos/submit',
                                                response.redirect_chain[0][0])

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_request_properties(self, get_current):
        '''_clean_next_url checks POST, GET, and REFERER'''
        get_current.return_value.domain = 'dev.mo.org'

        r = RequestFactory().get('/users/login', {'next': '/demos/submit'},
                                 HTTP_REFERER='referer-trumped-by-get')
        eq_('/demos/submit', _clean_next_url(r))
        r = RequestFactory().post('/users/login', {'next': '/demos/submit'})
        eq_('/demos/submit', _clean_next_url(r))
        r = RequestFactory().get('/users/login', HTTP_REFERER='/demos/submit')
        eq_('/demos/submit', _clean_next_url(r))

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_no_self_redirects(self, get_current):
        '''_clean_next_url checks POST, GET, and REFERER'''
        get_current.return_value.domain = 'dev.mo.org'

        for next in [settings.LOGIN_URL, settings.LOGOUT_URL]:
            r = RequestFactory().get('/users/login', {'next': next})
            eq_(None, _clean_next_url(r))

    @mock.patch_object(Site.objects, 'get_current')
    def test_clean_next_url_invalid_next_parameter(self, get_current):
        '''_clean_next_url cleans invalid urls'''
        get_current.return_value.domain = 'dev.mo.org'

        for next in self._invalid_nexts():
            r = RequestFactory().get('/users/login', {'next': next})
            eq_(None, _clean_next_url(r))

    @mock.patch_object(Site.objects, 'get_current')
    def test_login_invalid_next_parameter(self, get_current):
        '''Test with an invalid ?next=http://example.com parameter.'''
        get_current.return_value.domain = 'testserver.com'
        valid_next = reverse('home', locale=settings.LANGUAGE_CODE)

        for invalid_next in self._invalid_nexts():
            # Verify that _valid_ next parameter is set in form hidden field.
            response = self.client.get(urlparams(reverse('users.login'),
                                                 next=invalid_next))
            eq_(200, response.status_code)
            doc = pq(response.content)
            eq_(valid_next, doc('input[name="next"]')[0].attrib['value'])

            # Verify that it gets used on form POST.
            response = self.client.post(reverse('users.login'),
                                        {'username': '******',
                                         'password': '******',
                                         'next': invalid_next})
            eq_(302, response.status_code)
            eq_('http://testserver' + valid_next, response['location'])
            self.client.logout()

    def _invalid_nexts(self):
        return ['http://foobar.com/evil/', '//goo.gl/y-bad']
Ejemplo n.º 32
0
 def setUp(self):
     self.client = LocalizingClient()
     calendar_reload()
Ejemplo n.º 33
0
class ChangeEmailTestCase(TestCase):
    fixtures = ['test_users.json']

    def setUp(self):
        self.client = LocalizingClient()

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_change_email(self, get_current):
        """Send email to change user's email and then change it."""
        get_current.return_value.domain = 'su.mo.com'

        self.client.login(username='******', password='******')
        # Attempt to change email.
        response = self.client.post(reverse('users.change_email'),
                                    {'email': '*****@*****.**'},
                                    follow=True)
        eq_(200, response.status_code)

        # Be notified to click a confirmation link.
        eq_(1, len(mail.outbox))
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]
        assert ec.activation_key in mail.outbox[0].body
        eq_('*****@*****.**', ec.email)

        # Visit confirmation link to change email.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        u = User.objects.get(username='******')
        eq_('*****@*****.**', u.email)

    def test_user_change_email_same(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        user = User.objects.get(username='******')
        user.email = '*****@*****.**'
        user.save()
        response = self.client.post(reverse('users.change_email'),
                                    {'email': user.email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('This is your current email.', doc('ul.errorlist').text())

    def test_user_change_email_duplicate(self):
        """Changing to same email shows validation error."""
        self.client.login(username='******', password='******')
        email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': email})
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('A user with that email address already exists.',
            doc('ul.errorlist').text())

    @mock.patch_object(Site.objects, 'get_current')
    def test_user_confirm_email_duplicate(self, get_current):
        """If we detect a duplicate email when confirming an email change,
        don't change it and notify the user."""
        get_current.return_value.domain = 'su.mo.com'
        self.client.login(username='******', password='******')
        old_email = User.objects.get(username='******').email
        new_email = '*****@*****.**'
        response = self.client.post(reverse('users.change_email'),
                                    {'email': new_email})
        eq_(200, response.status_code)
        assert mail.outbox[0].subject.find('Please confirm your') == 0
        ec = EmailChange.objects.all()[0]

        # Before new email is confirmed, give the same email to a user
        other_user = User.objects.filter(username='******')[0]
        other_user.email = new_email
        other_user.save()

        # Visit confirmation link and verify email wasn't changed.
        response = self.client.get(reverse('users.confirm_email',
                                           args=[ec.activation_key]))
        eq_(200, response.status_code)
        doc = pq(response.content)
        eq_('Unable to change email for user testuser',
            doc('article h1').text())
        u = User.objects.get(username='******')
        eq_(old_email, u.email)