def test_persona_signin_captcha(self): persona_signup_email = '*****@*****.**' persona_signup_username = '******' with mock.patch('requests.post') as requests_mock: requests_mock.return_value.json.return_value = { 'status': 'okay', 'email': persona_signup_email, } self.client.post(reverse('persona_login'), follow=True) data = {'website': '', 'username': persona_signup_username, 'email': persona_signup_email, 'terms': True, 'g-recaptcha-response': 'FAILED'} signup_url = reverse('socialaccount_signup', locale=settings.WIKI_DEFAULT_LANGUAGE) with mock.patch('captcha.client.request') as request_mock: request_mock.return_value.read.return_value = '{"success": null}' response = self.client.post(signup_url, data=data, follow=True) eq_(response.status_code, 200) eq_(response.context['form'].errors, {'captcha': [u'Incorrect, please try again.']})
def test_persona_signup_create_socialaccount(self): """ Signing up with Persona creates a new SocialAccount instance. """ persona_signup_email = '*****@*****.**' persona_signup_username = '******' with mock.patch('requests.post') as requests_mock: requests_mock.return_value.json.return_value = { 'status': 'okay', 'email': persona_signup_email, } self.client.post(reverse('persona_login'), follow=True) data = {'website': '', 'username': persona_signup_username, 'email': persona_signup_email, 'terms': True, 'g-recaptcha-response': 'PASSED'} signup_url = reverse('socialaccount_signup', locale=settings.WIKI_DEFAULT_LANGUAGE) self.client.post(signup_url, data=data, follow=True) try: socialaccount = (SocialAccount.objects .filter(user__username=persona_signup_username))[0] except IndexError: socialaccount = None ok_(socialaccount is not None) eq_('persona', socialaccount.provider) eq_(persona_signup_email, socialaccount.uid) eq_({'status': 'okay', 'email': persona_signup_email}, socialaccount.extra_data) testuser = self.user_model.objects.get(username=persona_signup_username) eq_(testuser.id, socialaccount.user.id)
def test_my_user_edit(self): u = self.user_model.objects.get(username='******') self.client.login(username=u.username, password=TESTUSER_PASSWORD) resp = self.client.get(reverse('users.my_edit_page')) eq_(302, resp.status_code) ok_(reverse('users.user_edit', args=(u.username,)) in resp['Location'])
def test_spam_submission_submitted(self, mock_requests): admin = User.objects.get(username='******') flag, created = Flag.objects.get_or_create(name=SPAM_SUBMISSIONS_FLAG) flag.users.add(admin) revision = admin.created_revisions.all()[0] url = reverse('admin:wiki_revisionakismetsubmission_add') mock_requests.post(VERIFY_URL, content='valid') mock_requests.post(SPAM_URL, content=Akismet.submission_success) revision = admin.created_revisions.all()[0] data = { 'revision': revision.id, 'type': 'spam', } self.client.login(username='******', password='******') url = reverse('admin:wiki_revisionakismetsubmission_add') response = self.client.post(url, data) self.assertEqual(response.status_code, 302) # successfully created the submission record submission = RevisionAkismetSubmission.objects.first() self.assertTrue(submission is not None) self.assertEqual(submission.sender, admin) self.assertTrue(submission.sent) self.assertEqual(submission.revision, revision) self.assertEqual(submission.type, 'spam') self.assertEqual(mock_requests.call_count, 2) request_body = mock_requests.request_history[1].body self.assertIn('user_ip=0.0.0.0', request_body) self.assertIn('user_agent=', request_body) self.assertIn(revision.slug, request_body)
def _test_form_maintains_based_on_rev(client, doc, view, post_data, trans_lang=None, locale=None): """Confirm that the based_on value set in the revision created by an edit or translate form is the current_revision of the document as of when the form was first loaded, even if other revisions have been approved in the meantime.""" if trans_lang: translate_path = doc.slug uri = urllib.quote(reverse('wiki.translate', locale=trans_lang, args=[translate_path])) else: uri = reverse(view, locale=locale, args=[doc.slug]) response = client.get(uri) orig_rev = doc.current_revision eq_(orig_rev.id, int(pq(response.content)('input[name=based_on]').attr('value'))) # While Fred is editing the above, Martha approves a new rev: martha_rev = revision(document=doc) martha_rev.is_approved = True martha_rev.save() # Then Fred saves his edit: post_data_copy = {'based_on': orig_rev.id, 'slug': orig_rev.slug} post_data_copy.update(post_data) # Don't mutate arg. response = client.post(uri, data=post_data_copy) ok_(response.status_code in (200, 302)) fred_rev = Revision.objects.all().order_by('-id')[0] eq_(orig_rev, fred_rev.based_on)
def test_welcome_mail_for_unverified_email(self): Switch.objects.get_or_create(name='welcome_email', active=True) testuser = user(username='******', email='*****@*****.**', password='******', save=True) email_address = EmailAddress.objects.create(user=testuser, email='*****@*****.**', verified=False) request = self.rf.get('/') request.LANGUAGE_CODE = 'en-US' # emulate the phase in which the request for email confirmation is # sent as the user's email address is not verified confirmation = EmailConfirmationHMAC(email_address) confirmation.send() # only one email, the confirmation email is sent self.assertEqual(len(mail.outbox), 1) confirm_email = mail.outbox[0] expected_to = [email_address.email] self.assertEqual(expected_to, confirm_email.to) self.assertTrue('Confirm' in confirm_email.subject) # Click on a similar confirm link (HMAC has timestamp, changes) link = reverse('account_confirm_email', locale='en-US', args=[confirmation.key]) resp = self.client.get(link) assert resp.status_code == 200 resp = self.client.post(link, follow=True) assert resp.status_code == 200 # a second email, the welcome email, is sent self.assertEqual(len(mail.outbox), 2) welcome_email = mail.outbox[1] expected_to = [email_address.email] self.assertEqual(expected_to, welcome_email.to) self.assertTrue('utm_campaign=welcome' in welcome_email.body) # now add second unverified email address to the user # and check if the usual confirmation email is sent out email_address2 = EmailAddress.objects.create(user=testuser, email='*****@*****.**', verified=False) confirmation2 = EmailConfirmationHMAC(email_address2) confirmation2.send() self.assertEqual(len(mail.outbox), 3) confirm_email2 = mail.outbox[2] expected_to = [email_address2.email] self.assertEqual(expected_to, confirm_email2.to) self.assertTrue('Confirm' in confirm_email2.subject) # Confirm the second email address link2 = reverse('account_confirm_email', locale='en-US', args=[confirmation2.key]) resp = self.client.get(link2) assert resp.status_code == 200 resp = self.client.post(link2, follow=True) assert resp.status_code == 200 # no increase in number of emails (no 2nd welcome email) self.assertEqual(len(mail.outbox), 3) self.assertTrue('Confirm' in mail.outbox[2].subject)
def test_persona_form_present(self): """ When not authenticated, the Persona authentication components, with correct data attributes, are present in page contents, and the 'next' parameter is filled in. """ all_docs_url = reverse('wiki.all_documents', locale=settings.WIKI_DEFAULT_LANGUAGE) response = self.client.get(all_docs_url, follow=True) parsed = pq(response.content) request_info = '{"siteName": "%(siteName)s", "siteLogo": "%(siteLogo)s"}' % \ settings.SOCIALACCOUNT_PROVIDERS['persona']['REQUEST_PARAMETERS'] stub_attrs = ( ('data-csrf-token-url', reverse('persona_csrf_token')), ('data-request', request_info), ) auth_attrs = ( ('data-service', 'Persona'), ('data-next', all_docs_url), ) stub_persona_form = parsed.find('#_persona_login') ok_(len(stub_persona_form) > 0) for stub_attr in stub_attrs: ok_(stub_persona_form.attr(stub_attr[0])) eq_(stub_attr[1], stub_persona_form.attr(stub_attr[0])) auth_persona_form = parsed.find('.launch-persona-login') ok_(len(auth_persona_form) > 0) for auth_attr in auth_attrs: ok_(auth_persona_form.attr(auth_attr[0])) eq_(auth_attr[1], auth_persona_form.attr(auth_attr[0]))
def test_spam_submission_tags(self, mock_requests): admin = User.objects.get(username='******') flag, created = Flag.objects.get_or_create(name=SPAM_SUBMISSIONS_FLAG) flag.users.add(admin) revision = admin.created_revisions.all()[0] revision.tags = '"Banana" "Orange" "Apple"' revision.save() url = reverse('admin:wiki_revisionakismetsubmission_add') mock_requests.post(VERIFY_URL, content='valid') mock_requests.post(SPAM_URL, content=Akismet.submission_success) data = { 'revision': revision.id, 'type': 'spam', } self.client.login(username='******', password='******') url = reverse('admin:wiki_revisionakismetsubmission_add') response = self.client.post(url, data) self.assertEqual(response.status_code, 302) request_body = mock_requests.request_history[1].body submitted_data = dict(parse_qsl(request_body)) expected_content = ( 'Seventh revision of the article.\n' 'article-with-revisions\n' 'Seventh revision of the article.\n' 'Seventh revision of the article.\n' 'Apple\n' 'Banana\n' 'Orange' ) self.assertEqual(submitted_data['comment_content'], expected_content)
def test_known_authors_filter(self): # There are a total of 11 revisions url = urlparams(reverse('dashboards.revisions', locale='en-US'), authors=RevisionDashboardForm.ALL_AUTHORS) response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') eq_(response.status_code, 200) page = pq(response.content) revisions = page.find('.dashboard-row') eq_(11, revisions.length) # Only testuser01 is in the Known Authors group, and has 2 revisions url = urlparams(reverse('dashboards.revisions', locale='en-US'), authors=RevisionDashboardForm.KNOWN_AUTHORS) response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') eq_(response.status_code, 200) page = pq(response.content) revisions = page.find('.dashboard-row') eq_(2, revisions.length) # Of the 11 revisions, 9 are by users not in the Known Authors group url = urlparams(reverse('dashboards.revisions', locale='en-US'), authors=RevisionDashboardForm.UNKNOWN_AUTHORS) response = self.client.get(url, HTTP_X_REQUESTED_WITH='XMLHttpRequest') eq_(response.status_code, 200) page = pq(response.content) revisions = page.find('.dashboard-row') eq_(9, revisions.length)
def test_permissions(self, mock_analytics_upageviews): """A user with correct permissions is able to see the dashboard.""" self.client.login(username='******', password='******') # Attempt to see spam dashboard as a logged-in user without permissions response = self.client.get(reverse('dashboards.spam', locale='en-US')) eq_(403, response.status_code) # Give testuser wiki.add_revisionakismetsubmission permission perm_akismet = Permission.objects.get(codename='add_revisionakismetsubmission') self.testuser.user_permissions.add(perm_akismet) response = self.client.get(reverse('dashboards.spam', locale='en-US')) eq_(403, response.status_code) # Give testuser wiki.add_documentspamattempt permission perm_spam = Permission.objects.get(codename='add_documentspamattempt') self.testuser.user_permissions.add(perm_spam) response = self.client.get(reverse('dashboards.spam', locale='en-US')) eq_(403, response.status_code) # Give testuser wiki.add_userban permission perm_ban = Permission.objects.get(codename='add_userban') self.testuser.user_permissions.add(perm_ban) response = self.client.get(reverse('dashboards.spam', locale='en-US')) # With all correct permissions testuser is able to see the dashboard eq_(200, response.status_code) ok_('text/html' in response['Content-Type']) ok_('dashboards/spam.html' in [template.name for template in response.templates])
def test_misconfigured_google_analytics_does_not_block(self, mock_analytics_upageviews): """If the constance setting for the Google Analytics API credentials is not configured, or is misconfigured, calls to analytics_upageviews will raise an ImproperlyConfigured error. Show that we still get the rest of the stats, along with a message. """ mock_analytics_upageviews.side_effect = ImproperlyConfigured("Oops!") rev = self.create_revisions( num=1, creator=self.testuser, document=self.document )[0] rev.created = datetime.datetime.today() - datetime.timedelta(days=1) rev.save() rev.akismet_submissions.create(sender=self.admin, type='spam') self.client.login(username='******', password='******') # The first response will say that the report is being processed response = self.client.get(reverse('dashboards.spam', locale='en-US')) eq_(200, response.status_code) response2 = self.client.get(reverse('dashboards.spam', locale='en-US')) self.assertContains(response2, "Oops!", status_code=200) page = pq(response2.content) spam_trends_table = page.find('.spam-trends-table') eq_(len(spam_trends_table), 1) spam_events_table = page.find('.spam-events-table') eq_(len(spam_events_table), 1)
def test_user_edit(self, unsubscribe, subscribe, lookup_user): lookup_user.return_value = mock_lookup_user() subscribe.return_value = True unsubscribe.return_value = True testuser = self.user_model.objects.get(username='******') url = reverse('users.user_detail', args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.content) eq_(0, doc.find('#user-head .edit .button').length) self.client.login(username=testuser.username, password=TESTUSER_PASSWORD) url = reverse('users.user_detail', args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.content) edit_button = doc.find('#user-head .user-buttons #edit-user') eq_(1, edit_button.length) url = edit_button.attr('href') response = self.client.get(url, follow=True) doc = pq(response.content) eq_(testuser.fullname, doc.find('#user-edit input[name="user-fullname"]').val()) eq_(testuser.title, doc.find('#user-edit input[name="user-title"]').val()) eq_(testuser.organization, doc.find('#user-edit input[name="user-organization"]').val()) eq_(testuser.location, doc.find('#user-edit input[name="user-location"]').val()) eq_(testuser.irc_nickname, doc.find('#user-edit input[name="user-irc_nickname"]').val()) new_attrs = { 'user-username': testuser.username, 'user-email': '*****@*****.**', 'user-fullname': "Another Name", 'user-title': "Another title", 'user-organization': "Another org", 'user-country': "us", 'user-format': "html" } response = self.client.post(url, new_attrs, follow=True) doc = pq(response.content) eq_(1, doc.find('#user-head').length) eq_(new_attrs['user-fullname'], doc.find('#user-head .fn').text()) eq_(new_attrs['user-title'], doc.find('#user-head .user-info .title').text()) eq_(new_attrs['user-organization'], doc.find('#user-head .user-info .org').text()) testuser = self.user_model.objects.get(username=testuser.username) eq_(new_attrs['user-fullname'], testuser.fullname) eq_(new_attrs['user-title'], testuser.title) eq_(new_attrs['user-organization'], testuser.organization)
def test_create_valid(add_doc_client): """Test creating a new document with valid and invalid slugs.""" slug = 'Foobar' data = dict( title='A Foobar Document', slug=slug, tags='tag1, tag2', review_tags=['editorial', 'technical'], keywords='key1, key2', summary='lipsum', content='lorem ipsum dolor sit amet', comment='This is foobar.', toc_depth=1, ) url = reverse('wiki.create') resp = add_doc_client.post(url, data) assert resp.status_code == 302 assert resp['X-Robots-Tag'] == 'noindex' assert_no_cache_header(resp) assert resp['Location'].endswith(reverse('wiki.document', args=(slug,))) doc = Document.objects.get(slug=slug) for name in (set(data.keys()) - set(('tags', 'review_tags'))): assert getattr(doc.current_revision, name) == data[name] assert (sorted(doc.tags.all().values_list('name', flat=True)) == ['tag1', 'tag2']) review_tags = doc.current_revision.review_tags assert (sorted(review_tags.all().values_list('name', flat=True)) == ['editorial', 'technical'])
def context_dict(revision): """Return a dict that fills in the blanks in notification templates.""" document = revision.document from_revision = revision.get_previous() to_revision = revision diff = revisions_unified_diff(from_revision, to_revision) compare_url = "" if from_revision: compare_url = reverse( "wiki.compare_revisions", args=[document.slug], locale=document.locale ) + "?from=%s&to=%s" % (from_revision.id, to_revision.id) link_urls = { "profile_url": revision.creator.get_absolute_url(), "compare_url": compare_url, "view_url": reverse("wiki.document", locale=document.locale, args=[document.slug]), "edit_url": reverse("wiki.edit_document", locale=document.locale, args=[document.slug]), "history_url": reverse("wiki.document_revisions", locale=document.locale, args=[document.slug]), } for name, url in link_urls.iteritems(): url = add_utm(url, "Wiki Doc Edits") link_urls[name] = url context = {"document_title": document.title, "creator": revision.creator, "diff": diff} context.update(link_urls) return context
def test_my_profile_view(self): u = User.objects.get(username='******') self.client.login(username=u.username, password=TESTUSER_PASSWORD) resp = self.client.get(reverse('users.my_profile')) eq_(302, resp.status_code) ok_(reverse('users.profile', args=(u.username,)) in resp['Location'])
def context_dict(revision): """ Return a dict that fills in the blanks in notification templates. """ document = revision.document from_revision = revision.previous to_revision = revision diff = revisions_unified_diff(from_revision, to_revision) context = {"document_title": document.title, "creator": revision.creator, "diff": diff} if from_revision: compare_url = get_compare_url(document, from_revision.id, to_revision.id) else: compare_url = "" link_urls = { "user_url": revision.creator.get_absolute_url(), "compare_url": compare_url, "view_url": document.get_absolute_url(), "edit_url": reverse("wiki.edit_document", locale=document.locale, args=[document.slug]), "history_url": reverse("wiki.document_revisions", locale=document.locale, args=[document.slug]), } for name, url in link_urls.items(): context[name] = add_utm(url, "Wiki Doc Edits") return context
def test_user_edit_websites(self): testuser = self.user_model.objects.get(username='******') self.client.login(username=testuser.username, password=TESTUSER_PASSWORD) url = reverse('users.user_edit', args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.content) test_sites = { 'website': 'http://example.com/', 'twitter': 'http://twitter.com/lmorchard', 'github': 'http://github.com/lmorchard', 'stackoverflow': 'http://stackoverflow.com/users/lmorchard', 'linkedin': 'https://www.linkedin.com/in/testuser', 'mozillians': 'https://mozillians.org/u/testuser', 'facebook': 'https://www.facebook.com/test.user' } form = self._get_current_form_field_values(doc) # Fill out the form with websites. form.update(dict(('user-%s_url' % k, v) for k, v in test_sites.items())) # Submit the form, verify redirect to user detail response = self.client.post(url, form, follow=True) doc = pq(response.content) eq_(1, doc.find('#user-head').length) testuser = self.user_model.objects.get(pk=testuser.pk) # Verify the websites are saved in the user. for site, url in test_sites.items(): url_attr_name = '%s_url' % site eq_(getattr(testuser, url_attr_name), url) # Verify the saved websites appear in the editing form url = reverse('users.user_edit', args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.content) for k, v in test_sites.items(): eq_(v, doc.find('#user-edit *[name="user-%s_url"]' % k).val()) # Come up with some bad sites, either invalid URL or bad URL prefix bad_sites = { 'website': 'HAHAHA WHAT IS A WEBSITE', 'twitter': 'http://facebook.com/lmorchard', 'stackoverflow': 'http://overqueueblah.com/users/lmorchard', } form.update(dict(('user-%s_url' % k, v) for k, v in bad_sites.items())) # Submit the form, verify errors for all of the bad sites response = self.client.post(url, form, follow=True) doc = pq(response.content) eq_(1, doc.find('#user-edit').length) tmpl = '#user-edit #users .%s .errorlist' for n in ('website', 'twitter', 'stackoverflow'): eq_(1, doc.find(tmpl % n).length)
def test_xss_file_attachment_title(self): title = '"><img src=x onerror=prompt(navigator.userAgent);>' # use view to create new attachment file_for_upload = make_test_file() post_data = { 'title': title, 'description': 'xss', 'comment': 'xss', 'file': file_for_upload, } self.client.login(username='******', password='******') resp = self.client.post(reverse('attachments.new_attachment'), data=post_data) eq_(302, resp.status_code) # now stick it in/on a document attachment = Attachment.objects.get(title=title) rev = revision(content='<img src="%s" />' % attachment.get_file_url(), save=True) # view it and verify markup is escaped response = self.client.get(reverse('wiki.edit_document', args=(rev.slug,), locale=settings.WIKI_DEFAULT_LANGUAGE)) eq_(200, response.status_code) doc = pq(response.content) eq_('%s xss' % title, doc('#page-attachments-table .attachment-name-cell').text()) ok_('><img src=x onerror=prompt(navigator.userAgent);>' in doc('#page-attachments-table .attachment-name-cell').html())
def ban_links(context, ban_user, banner_user): """Returns a link to ban a user""" links = '' if ban_user.id != banner_user.id and banner_user.has_perm('users.add_userban'): active_ban = ban_user.active_ban url_ban_cleanup = reverse('users.ban_user_and_cleanup', kwargs={'username': ban_user.username}) if active_ban: url = reverse('admin:users_userban_change', args=(active_ban.id,)) title = ugettext('Banned on %(ban_date)s by %(ban_admin)s.') % { 'ban_date': datetimeformat(context, active_ban.date, format='date', output='json'), 'ban_admin': active_ban.by, } link = ('<a id="ban_link" href="%s" class="button ban-link" title="%s">%s' '<i aria-hidden="true" class="icon-ban"></i></a>' % (url, title, ugettext('Banned'))) link_cleanup = ('<a id="cleanup_link" href="%s" class="button negative ban-link">%s' '<i aria-hidden="true" class="icon-ban"></i></a>' % (url_ban_cleanup, ugettext('Clean Up Revisions'))) else: url = reverse('users.ban_user', kwargs={'username': ban_user.username}) link = ('<a id="ban_link" href="%s" class="button negative ban-link">%s' '<i aria-hidden="true" class="icon-ban"></i></a>' % (url, ugettext('Ban User'))) link_cleanup = ('<a id="cleanup_link" href="%s" class="button negative ban-link">%s' '<i aria-hidden="true" class="icon-ban"></i></a>' % (url_ban_cleanup, ugettext('Ban User & Clean Up'))) links = link_cleanup + ' ' + link return Markup(links)
def test_create_child_valid(root_doc, add_doc_client, slug): """Test creating a new child document with valid and invalid slugs.""" data = dict( title='A Child of the Root Document', slug=slug, tags='tag1, tag2', review_tags=['editorial', 'technical'], keywords='key1, key2', summary='lipsum', content='lorem ipsum dolor sit amet', comment='This is foobar.', toc_depth=1, ) url = reverse('wiki.create') url += '?parent={}'.format(root_doc.id) full_slug = '{}/{}'.format(root_doc.slug, slug) resp = add_doc_client.post(url, data) assert resp.status_code == 302 assert resp['X-Robots-Tag'] == 'noindex' assert_no_cache_header(resp) assert resp['Location'].endswith( reverse('wiki.document', args=(full_slug,))) assert root_doc.children.count() == 1 doc = Document.objects.get(slug=full_slug, locale='en-US') skip_keys = set(('tags', 'review_tags', 'parent_topic')) for name in (set(data.keys()) - skip_keys): expected = full_slug if name == 'slug' else data[name] assert getattr(doc.current_revision, name) == expected assert (sorted(doc.tags.all().values_list('name', flat=True)) == ['tag1', 'tag2']) review_tags = doc.current_revision.review_tags assert (sorted(review_tags.all().values_list('name', flat=True)) == ['editorial', 'technical'])
def login(self, username='******', verified_email='*****@*****.**', process='login', with_refresh_token=True, public_email='*****@*****.**'): resp = self.client.get(reverse('github_login', locale=settings.WIKI_DEFAULT_LANGUAGE), {'process': process}) path = urlparse(resp['location']) query = parse_qs(path.query) complete_url = reverse('github_callback', unprefixed=True) self.assertGreater(query['redirect_uri'][0] .find(complete_url), 0) response_json = self.get_login_response_json( with_refresh_token=with_refresh_token) with mocked_response( MockedResponse(200, response_json, {'content-type': 'application/json'}), MockedResponse(200, self.mocked_user_response % {'username': username, 'public_email': json.dumps(public_email)}), MockedResponse(200, self.mocked_email_response % {'verified_email': verified_email})): resp = self.client.get(complete_url, {'code': 'test', 'state': query['state'][0]}, follow=True) return resp
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 testuser = self.user_model.objects.get(username="******") self.client.login(username=testuser.username, password=TESTUSER_PASSWORD) url = reverse("users.profile_edit", args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.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(("profile-websites_%s" % k, v) for k, v in test_sites.items())) # Submit the form, verify redirect to profile detail response = self.client.post(url, form, follow=True) doc = pq(response.content) eq_(1, doc.find("#profile-head").length) profile = UserProfile.objects.get(user=testuser) # Verify the websites are saved in the profile. eq_(test_sites, profile.websites) # Verify the saved websites appear in the editing form url = reverse("users.profile_edit", args=(testuser.username,)) response = self.client.get(url, follow=True) doc = pq(response.content) for k, v in test_sites.items(): eq_(v, doc.find('#profile-edit *[name="profile-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(("profile-websites_%s" % k, v) for k, v in bad_sites.items())) # Submit the form, verify errors for all of the bad sites response = self.client.post(url, form, follow=True) doc = pq(response.content) eq_(1, doc.find("#profile-edit").length) tmpl = "#profile-edit #profiles .%s .errorlist" for n in ("website", "twitter", "stackoverflow"): eq_(1, doc.find(tmpl % n).length)
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='******') url = reverse('users.profile', args=(profile.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=profile.user.username, password=TESTUSER_PASSWORD) url = reverse('users.profile', args=(profile.user.username,)) r = self.client.get(url, follow=True) doc = pq(r.content) edit_button = doc.find('#profile-head .profile-buttons #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="profile-fullname"]').val()) eq_(profile.title, doc.find('#profile-edit input[name="profile-title"]').val()) eq_(profile.organization, doc.find('#profile-edit input[name="profile-organization"]').val()) eq_(profile.location, doc.find('#profile-edit input[name="profile-location"]').val()) eq_(profile.irc_nickname, doc.find('#profile-edit input[name="profile-irc_nickname"]').val()) new_attrs = { 'profile-email': '*****@*****.**', 'profile-fullname': "Another Name", 'profile-title': "Another title", 'profile-organization': "Another org", 'profile-country': "us", 'profile-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['profile-fullname'], doc.find('#profile-head .fn').text()) eq_(new_attrs['profile-title'], doc.find('#profile-head .profile-info .title').text()) eq_(new_attrs['profile-organization'], doc.find('#profile-head .profile-info .org').text()) profile = UserProfile.objects.get(user__username=profile.user.username) eq_(new_attrs['profile-fullname'], profile.fullname) eq_(new_attrs['profile-title'], profile.title) eq_(new_attrs['profile-organization'], profile.organization)
def setUp(self): super(BanUserAndCleanupSummaryTestCase, self).setUp() self.ban_testuser_url = reverse('users.ban_user_and_cleanup_summary', kwargs={'user_id': self.testuser.id}) self.ban_testuser2_url = reverse('users.ban_user_and_cleanup_summary', kwargs={'user_id': self.testuser2.id}) self.client.login(username='******', password='******')
def test_watch_login_required(client, root_doc, endpoint): """User must be logged-in to subscribe to a document.""" url = reverse(endpoint, args=[root_doc.slug]) response = client.post(url) assert response.status_code == 302 assert_no_cache_header(response) assert response['Location'].endswith( reverse('account_login') + '?next=' + quote(url))
def item_description(self, item): # TODO: put this in a jinja template if django syndication will let us previous = item.previous if previous is None: action = u"Created" else: action = u"Edited" by = u"<h3>%s by:</h3><p>%s</p>" % (action, item.creator.username) if item.comment: comment = u"<h3>Comment:</h3><p>%s</p>" % item.comment else: comment = u"" review_diff = u"" tag_diff = u"" content_diff = u"" if previous: prev_review_tags = previous.review_tags.values_list("name", flat=True) curr_review_tags = item.review_tags.values_list("name", flat=True) if set(prev_review_tags) != set(curr_review_tags): table = tag_diff_table(u",".join(prev_review_tags), u",".join(curr_review_tags), previous.id, item.id) review_diff = u"<h3>Review changes:</h3>%s" % table review_diff = colorize_diff(review_diff) if previous.tags != item.tags: table = tag_diff_table(previous.tags, item.tags, previous.id, item.id) tag_diff = u"<h3>Tag changes:</h3>%s" % table tag_diff = colorize_diff(tag_diff) previous_content = "" previous_id = u"N/A" content_diff = u"<h3>Content changes:</h3>" if previous: previous_content = previous.get_tidied_content() current_content = item.get_tidied_content() previous_id = previous.id if previous_content != current_content: content_diff = content_diff + diff_table(previous_content, current_content, previous_id, item.id) content_diff = colorize_diff(content_diff) else: content_diff = content_diff + escape(item.content) link_cell = u'<td><a href="%s">%s</a></td>' view_cell = link_cell % (item.document.get_absolute_url(), _("View Page")) edit_cell = link_cell % (reverse("wiki.edit_document", args=[item.document.slug]), _("Edit Page")) if previous: compare_cell = link_cell % (get_compare_url(item.document, previous.id, item.id), _("Show comparison")) else: compare_cell = "" history_cell = link_cell % (reverse("wiki.document_revisions", args=[item.document.slug]), _("History")) links_table = u'<table border="0" width="80%">' links_table = links_table + u"<tr>%s%s%s%s</tr>" % (view_cell, edit_cell, compare_cell, history_cell) links_table = links_table + u"</table>" return u"".join([by, comment, tag_diff, review_diff, content_diff, links_table])
def get_object(self, request, format, tag=None, category=None): super(DocumentsRecentFeed, self).get_object(request, format) self.category = category self.tag = tag if tag: self.title = _("MDN recent changes to documents tagged %s" % tag) self.link = self.request.build_absolute_uri(reverse("wiki.tag", args=(tag,))) else: self.link = self.request.build_absolute_uri(reverse("kuma.wiki.views.list_documents"))
def get_object(self, request, format, tag=None): super(DocumentsRecentFeed, self).get_object(request, format) self.tag = tag if tag: self.title = _('MDN recent changes to documents tagged {0!s}'.format(tag)) self.link = self.request.build_absolute_uri( reverse('wiki.tag', args=(tag,))) else: self.link = self.request.build_absolute_uri( reverse('wiki.all_documents'))
def test_index_admin_sees_spam_dashboard(admin_client): """A moderator can see the spam dashboard in the list.""" response = admin_client.get(reverse('dashboards.index')) assert response.status_code == 200 content = response.content.decode(response.charset) assert reverse('dashboards.macros') in content assert reverse('dashboards.spam') in content l10n_url = reverse('wiki.list_with_localization_tag', kwargs={'tag': 'inprogress'}) assert l10n_url not in content
def get_object(self, request, format, tag=None): super(DocumentsReviewFeed, self).get_object(request, format) self.subtitle = None if tag: self.title = _("MDN documents for %s review" % tag) self.link = self.request.build_absolute_uri(reverse("wiki.list_review_tag", args=(tag,))) else: self.title = _("MDN documents for review") self.link = self.request.build_absolute_uri(reverse("wiki.list_review")) return tag
def history_link(self): url = '%s?%s' % (reverse('admin:authkeys_keyaction_changelist'), 'key__exact=%s' % (self.id)) count = self.history.count() what = (count == 1) and 'action' or 'actions' return '<a href="%s">%s %s</a>' % (url, count, what)
def test_ping_landing_page_survey_authenticated(user_client, wiki_user): url = reverse("api.v1.plus.landing_page_survey") response = user_client.get(url, {"variant": 1}) assert response.status_code == 200 (result, ) = LandingPageSurvey.objects.all() assert result.user == wiki_user
def edit(request, document_slug, document_locale, revision_id=None): """ Create a new revision of a wiki document, or edit document metadata. """ doc = get_object_or_404(Document, locale=document_locale, slug=document_slug) # If this document has a parent, then the edit is handled by the # translate view. Pass it on. if doc.parent and doc.parent.id != doc.id: return translate(request, doc.parent.slug, doc.locale, revision_id, bypass_process_document_path=True) if revision_id: rev = get_object_or_404(Revision, pk=revision_id, document=doc) else: rev = doc.current_revision or doc.revisions.order_by( '-created', '-id')[0] # Keep hold of the full post slug slug_dict = split_slug(document_slug) # Update the slug, removing the parent path, and # *only* using the last piece. # This is only for the edit form. rev.slug = slug_dict['specific'] section_id = request.GET.get('section', None) if section_id and not request.is_ajax(): return HttpResponse(_("Sections may only be edited inline.")) disclose_description = bool(request.GET.get('opendescription')) doc_form = rev_form = None if doc.allows_revision_by(request.user): rev_form = RevisionForm(request=request, instance=rev, initial={ 'based_on': rev.id, 'current_rev': rev.id, 'comment': '' }, section_id=section_id) if doc.allows_editing_by(request.user): doc_form = DocumentForm(initial=document_form_initial(doc)) # Need to make check *here* to see if this could have a translation parent show_translation_parent_block = ( (document_locale != settings.WIKI_DEFAULT_LANGUAGE) and (not doc.parent_id)) if request.method == 'GET': if not (rev_form or doc_form): # You can't do anything on this page, so get lost. raise PermissionDenied else: # POST is_iframe_target = request.GET.get('iframe', False) is_raw = request.GET.get('raw', False) need_edit_links = request.GET.get('edit_links', False) parent_id = request.POST.get('parent_id', '') # Attempt to set a parent if show_translation_parent_block and parent_id: try: parent_doc = get_object_or_404(Document, id=parent_id) doc.parent = parent_doc except Document.DoesNotExist: pass # Comparing against localized names for the Save button bothers me, so # I embedded a hidden input: which_form = request.POST.get('form') if which_form == 'doc': if doc.allows_editing_by(request.user): post_data = request.POST.copy() post_data.update({'locale': document_locale}) doc_form = DocumentForm(post_data, instance=doc) if doc_form.is_valid(): # if must be here for section edits if 'slug' in post_data: post_data['slug'] = u'/'.join( [slug_dict['parent'], post_data['slug']]) # Get the possibly new slug for the imminent redirection: doc = doc_form.save(parent=None) if is_iframe_target: # TODO: Does this really need to be a template? Just # shoehorning data into a single HTML element. response = HttpResponse( textwrap.dedent(""" <span id="iframe-response" data-status="OK" data-current-revision="%s">OK</span> """ % doc.current_revision.id)) response['X-Frame-Options'] = 'SAMEORIGIN' return response return redirect( urlparams(doc.get_edit_url(), opendescription=1)) disclose_description = True else: raise PermissionDenied elif which_form == 'rev': if not doc.allows_revision_by(request.user): raise PermissionDenied else: post_data = request.POST.copy() rev_form = RevisionForm(request=request, data=post_data, is_iframe_target=is_iframe_target, section_id=section_id) rev_form.instance.document = doc # for rev_form.clean() # Come up with the original revision to which these changes # would be applied. orig_rev_id = request.POST.get('current_rev', False) if orig_rev_id is False: orig_rev = None else: orig_rev = Revision.objects.get(pk=orig_rev_id) # Get the document's actual current revision. curr_rev = doc.current_revision if not rev_form.is_valid(): # Was there a mid-air collision? if 'current_rev' in rev_form._errors: # Jump out to a function to escape indentation hell return _edit_document_collision( request, orig_rev, curr_rev, is_iframe_target, is_raw, rev_form, doc_form, section_id, rev, doc) if rev_form.is_valid(): rev_form.save(doc) if is_iframe_target: # TODO: Does this really need to be a template? Just # shoehorning data into a single HTML element. response = HttpResponse(""" <span id="iframe-response" data-status="OK" data-current-revision="%s">OK</span> """ % doc.current_revision.id) response['X-Frame-Options'] = 'SAMEORIGIN' return response if (is_raw and orig_rev is not None and curr_rev.id != orig_rev.id): # If this is the raw view, and there was an original # revision, but the original revision differed from the # current revision at start of editing, we should tell # the client to refresh the page. response = HttpResponse('RESET') response['X-Frame-Options'] = 'SAMEORIGIN' response.status_code = 205 return response if rev_form.instance.is_approved: view = 'wiki.document' else: view = 'wiki.document_revisions' # Construct the redirect URL, adding any needed parameters url = reverse(view, args=[doc.slug], locale=doc.locale) params = {} if is_raw: params['raw'] = 'true' if need_edit_links: # Only need to carry over ?edit_links with ?raw, # because they're on by default in the normal UI params['edit_links'] = 'true' if section_id: # If a section was edited, and we're using the raw # content API, constrain to that section. params['section'] = section_id if params: url = '%s?%s' % (url, urlencode(params)) if not is_raw and section_id: # If a section was edited, jump to the section anchor # if we're not getting raw content. url = '%s#%s' % (url, section_id) return redirect(url) parent_path = parent_slug = '' if slug_dict['parent']: parent_slug = slug_dict['parent'] if doc.parent_topic_id: parent_doc = Document.objects.get(pk=doc.parent_topic_id) parent_path = parent_doc.get_absolute_url() parent_slug = parent_doc.slug context = { 'revision_form': rev_form, 'document_form': doc_form, 'section_id': section_id, 'disclose_description': disclose_description, 'parent_slug': parent_slug, 'parent_path': parent_path, 'revision': rev, 'document': doc, 'attachment_form': AttachmentRevisionForm(), } return render(request, 'wiki/edit.html', context)
def test_list_files(self): list_files_url = reverse('attachments.list_files', locale=settings.WIKI_DEFAULT_LANGUAGE) resp = self.client.get(list_files_url) eq_(200, resp.status_code) ok_('All Files' in resp.content)
def test_home(client, db): response = client.get(reverse('home'), follow=True) assert response.status_code == 200 assert_shared_cache_header(response)
def test_revisions_bad_slug_is_not_found(db, client): """$history of unknown page returns 404.""" url = reverse('wiki.document_revisions', args=('not_found',), locale='en-US') resp = client.get(url) assert resp.status_code == 404
def test_disallowed_methods(db, client, http_method, endpoint): """HTTP methods other than GET & HEAD are not allowed.""" url = reverse('wiki.{}'.format(endpoint)) response = getattr(client, http_method)(url) assert response.status_code == 405 assert_shared_cache_header(response)
def full_attachment_url(attachment_id, filename): path = reverse('attachments.raw_file', kwargs={ 'attachment_id': attachment_id, 'filename': filename, }) return '%s%s%s' % (settings.PROTOCOL, settings.ATTACHMENT_HOST, path)
def test_whoami_disallowed_methods(client, http_method): """HTTP methods other than GET are not allowed.""" url = reverse("api.v1.whoami") response = getattr(client, http_method)(url) assert response.status_code == 405 assert_no_cache_header(response)
def test_bc_signal_disabled(client, settings): settings.ENABLE_BCD_SIGNAL = False url = reverse("api.v1.bc_signal") response = client.post(url) assert response.status_code == 400
def test_create_subscription_failure_without_login(client): response = client.post(reverse("api.v1.create_subscription")) assert response.status_code == 403
def test_create_subscription_failure_with_disabled_waffle(user_client): response = user_client.post(reverse("api.v1.create_subscription")) assert response.status_code == 403
def content_object_link(self): obj = self.content_object url_key = 'admin:%s_%s_change' % (obj._meta.app_label, obj._meta.model_name) url = reverse(url_key, args=[obj.id]) return '<a href="%s">%s (#%s)</a>' % (url, self.content_type, obj.pk)
def test_doc_api_404(client, root_doc): """We get a 404 if we ask for a document that does not exist.""" url = reverse("api.v1.doc", args=["en-US", "NoSuchPage"]) response = client.get(url) assert response.status_code == 404 assert_no_cache_header(response)
def test_ckeditor_config(db, client): response = client.get(reverse('wiki.ckeditor_config')) assert response.status_code == 200 assert_shared_cache_header(response) assert response['Content-Type'] == 'application/x-javascript' assert 'wiki/ckeditor_config.js' in [t.name for t in response.templates]
def test_submit_loggedin(self): r = self.client.get(reverse('demos_submit')) assert pq(r.content)('form#demo-submit')
def get_user_url(user): from kuma.core.urlresolvers import reverse return reverse('users.profile', args=[user.username])
def test_submit_loggedout(self): r = self.client.get(reverse('demos_submit')) choices = pq(r.content)('p.choices a[href*="signin"]') eq_(choices.length, 1)
def test_promote_buttons(client, db): response = client.get(reverse('promote_buttons'), follow=True) assert response.status_code == 200 assert_shared_cache_header(response)
def test_search_view(self): try: self.client.get(reverse('demos_search')) except: self.fail("Search should not ISE.")
def test_contribute_json(client, db): response = client.get(reverse('contribute_json')) assert response.status_code == 200 assert_shared_cache_header(response) assert response['Content-Type'].startswith('application/json')
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"]')
def attachment_url(self, obj): attachment = obj.attachment url = reverse('admin:attachments_attachment_change', args=(attachment.pk, )) return format_html(u'<a href="{}">{}</a>', url, attachment.pk)
def wiki_url(path): """ Create a URL pointing to Kuma. Look for a wiki page in the current locale, or default to given path """ return reverse('wiki.document', args=[path])
def test_post_required(self): url = reverse('dashboards.submit_akismet_spam', locale='en-US') response = self.client.get(url) eq_(response.status_code, 405, "GET should not be allowed.")
def get_compare_url(doc, from_id, to_id): params = urllib.urlencode({'from': from_id, 'to': to_id}) return ( reverse('wiki.compare_revisions', args=[doc.slug], locale=doc.locale) + '?' + params)
def test_kumascript_revision_hash_405s(client, db, method): response = getattr(client, method)(reverse('version.kumascript')) assert response.status_code == 405
def test_revert_get(root_doc, moderator_client): url = reverse('wiki.revert_document', args=[root_doc.slug, root_doc.current_revision.id]) response = moderator_client.get(url, HTTP_HOST=settings.WIKI_HOST) assert response.status_code == 200 assert_no_cache_header(response)
def key_link(self): key = self.key url = reverse('admin:authkeys_key_change', args=[key.id]) return '<a href="%s">%s (#%s)</a>' % (url, key.user, key.id)
def test_doc_api_disallowed_methods(client, http_method): """HTTP methods other than GET are not allowed.""" url = reverse("api.v1.doc", args=["en-US", "Web/CSS"]) response = getattr(client, http_method)(url) assert response.status_code == 405 assert_no_cache_header(response)