def test_delete_key(self): """User should be able to delete own keys, but no one else's""" self.client.login(username=self.username, password=self.password) url = reverse('authkeys.delete', args=(self.key3.pk,), locale='en-US') resp = self.client.get(url, follow=True) eq_(403, resp.status_code) resp = self.client.post(url, follow=False) ok_(403, resp.status_code) url = reverse('authkeys.delete', args=(self.key1.pk,), locale='en-US') resp = self.client.get(url, follow=True) eq_(200, resp.status_code) page = pq(resp.content) eq_(self.key1.description, page.find('.key .description').text()) resp = self.client.post(url, follow=False) ok_(302, resp.status_code) eq_(0, Key.objects.filter(pk=self.key1.pk).count())
def _get_wiki_link(title, locale): """Checks the page exists, and returns its URL or the URL to create it. Return value is a dict: {'found': boolean, 'url': string}. found is False if the document does not exist. """ # Prevent circular import. sumo is conceptually a utils apps and # shouldn't have import-time (or really, any, but that's not going # to happen) dependencies on client apps. from wiki.models import Document d = get_object_fallback(Document, locale=locale, title=title, is_template=False) if d: # If the article redirects use its destination article while d.redirect_document(): d = d.redirect_document() # The locale in the link urls should always match the current # document's locale even if the document/slug being linked to # is in the default locale. url = reverse('wiki.document', locale=locale, args=[d.slug]) return {'found': True, 'url': url, 'text': d.title} # To avoid circular imports, wiki.models imports wiki_to_html from sumo.helpers import urlparams return {'found': False, 'text': title, 'url': urlparams(reverse('wiki.new_document', locale=locale), title=title)}
def _clean_next_url(request): if 'next' in request.POST: url = request.POST.get('next') elif 'next' in request.GET: url = request.GET.get('next') elif 'HTTP_REFERER' in request.META: url = request.META.get('HTTP_REFERER').decode('latin1', 'ignore') else: return None site = Site.objects.get_current() if not is_safe_url(url, site.domain): return None parsed_url = urlparse.urlparse(url) # Don't redirect right back to login, logout, register, or # change email pages locale, register_url = split_path(reverse( 'users.browserid_register')) locale, change_email_url = split_path(reverse( 'users.change_email')) LOOPING_NEXT_URLS = [settings.LOGIN_URL, settings.LOGOUT_URL, register_url, change_email_url] for looping_url in LOOPING_NEXT_URLS: if looping_url in parsed_url.path: return None # TODO?HACK: can't use urllib.quote_plus because mod_rewrite quotes the # next url value already. url = url.replace(' ', '+') return url
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="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 .main .fn').text()) eq_(new_attrs['profile-title'], doc.find('#profile-head .info .title').text()) eq_(new_attrs['profile-organization'], doc.find('#profile-head .info .org').text()) profile = UserProfile.objects.get(user__username=user.username) eq_(new_attrs['profile-fullname'], profile.fullname) eq_(new_attrs['profile-title'], profile.title) eq_(new_attrs['profile-organization'], profile.organization)
def add_tag(request, question_id): """Add a (case-insensitive) tag to question. If the question already has the tag, do nothing. """ # If somebody hits Return in the address bar after provoking an error from # the add form, nicely send them back to the question: if request.method == 'GET': return HttpResponseRedirect( reverse('questions.answers', args=[question_id])) try: question, canonical_name = _add_tag(request, question_id) except Tag.DoesNotExist: template_data = _answers_data(request, question_id) template_data['tag_adding_error'] = UNAPPROVED_TAG template_data['tag_adding_value'] = request.POST.get('tag-name', '') return jingo.render(request, 'questions/answers.html', template_data) if canonical_name: # success question.clear_cached_tags() return HttpResponseRedirect( reverse('questions.answers', args=[question_id])) # No tag provided template_data = _answers_data(request, question_id) template_data['tag_adding_error'] = NO_TAG return jingo.render(request, 'questions/answers.html', template_data)
def test_redirect_to_contributor_dash(self): """Should redirect to Contributor Dash if the locale is the default""" response = self.client.get(reverse('dashboards.localization', locale='en-US'), follow=True) self.assertRedirects(response, reverse('dashboards.contributors', locale='en-US'))
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 User.objects.filter(username='******').update(email=new_email) # 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 rrosario', doc('#main h1').text()) u = User.objects.get(username='******') eq_(old_email, u.email)
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)
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.full_path], locale=document.locale ) + "?from=%s&to=%s" % (from_revision.id, to_revision.id) link_urls = { "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, "host": Site.objects.get_current().domain, "diff": diff, } context.update(link_urls) return context
def test_new_user(self, get_current): get_current.return_value.domain = 'su.mo.com' now = time() username = '******' % now response = self.client.post(reverse('users.register'), {'username': username, 'email': '*****@*****.**', 'password': '******', 'password2': 'foo'}, follow=True) eq_(200, response.status_code) u = User.objects.get(username=username) assert u.password.startswith('sha256') assert not u.is_active eq_(1, len(mail.outbox)) assert mail.outbox[0].subject.find('Please confirm your') == 0 key = RegistrationProfile.objects.all()[0].activation_key assert mail.outbox[0].body.find('activate/%s' % key) > 0 # Now try to log in u.is_active = True u.save() response = self.client.post(reverse('users.login'), {'username': username, 'password': '******'}, follow=True) eq_(200, response.status_code) eq_('http://testserver/en-US/', response.redirect_chain[0][0])
def test_user_change_email_updates_mindtouch(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) if not settings.DEKIWIKI_MOCK: deki_id = u.get_profile().deki_user_id doc = get_deki_user_doc(u) eq_(str(deki_id), doc('user').attr('id')) eq_('*****@*****.**', doc('user').find('email').text())
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.full_path], locale=document.locale) + '?from=%s&to=%s' % (from_revision.id, to_revision.id)) return { 'document_title': document.title, 'creator': revision.creator, 'host': Site.objects.get_current().domain, '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]), 'diff': diff }
def item_description(self, item): previous = item.get_previous() if previous is None: return '<p>Created by: %s</p>' % item.creator.username # TODO: put this in a jinja template if django syndication will let us by = '<p>Edited by: %s</p>' % item.creator.username comment = '<p>Comment: %s</p>' % item.comment diff = ("Diff:<blockquote>%s</blockquote>" % ( diff_inline(previous.content, item.content))) diff = (diff.replace('<ins', '<ins style="background-color: #AAFFAA;"') .replace('<del', '<del style="background-color: #FFAAAA;"')) link_cell = '<td><a href="%s">%s</a></td>' view_cell = link_cell % (reverse('wiki.document', args=[item.document.full_path]), _('View Page')) edit_cell = link_cell % (reverse('wiki.edit_document', args=[item.document.full_path]), _('Edit Page')) compare_cell = link_cell % (reverse('wiki.compare_revisions', args=[item.document.full_path]) + '?' + urllib.urlencode({'from': previous.id, 'to': item.id}), _('Show comparison')) history_cell = link_cell % (reverse('wiki.document_revisions', args=[item.document.full_path]), _('History')) links_table = '<table border="0" width="80%">' links_table = links_table + '<tr>%s%s%s%s</tr>' % (view_cell, edit_cell, compare_cell, history_cell) links_table = links_table + '</table>' description = "%s%s%s%s" % (by, comment, diff, links_table) return description
def test_forums_filter_updated(self): """Filter for updated date.""" post_updated_ds = datetime(2010, 5, 3, 12, 00) thread1 = thread(title=u't1 audio', save=True) post(thread=thread1, created=post_updated_ds, save=True) thread2 = thread(title=u't2 audio', save=True) post(thread=thread2, created=(post_updated_ds + timedelta(days=2)), save=True) self.refresh() qs = {'a': 1, 'w': 4, 'format': 'json', 'sortby': 1, 'updated_date': '05/04/2010'} qs['updated'] = constants.INTERVAL_BEFORE response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([thread1.get_absolute_url()], [r['url'] for r in results]) qs['updated'] = constants.INTERVAL_AFTER response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([thread2.get_absolute_url()], [r['url'] for r in results])
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 test_advanced_search_questions_num_votes(self): """Tests advanced search for questions num_votes filter""" q = question(title=u'tags tags tags', save=True) # Add two question votes questionvote(question=q, save=True) questionvote(question=q, save=True) self.refresh() # Advanced search for questions with num_votes > 5. The above # question should be not in this set. response = self.client.get(reverse('search'), { 'q': '', 'tags': 'desktop', 'w': '2', 'a': '1', 'num_voted': 2, 'num_votes': 5, 'format': 'json' }) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 0) # Advanced search for questions with num_votes < 1. The above # question should be not in this set. response = self.client.get(reverse('search'), { 'q': '', 'tags': 'desktop', 'w': '2', 'a': '1', 'num_voted': 1, 'num_votes': 1, 'format': 'json' }) eq_(200, response.status_code) content = json.loads(response.content) eq_(content['total'], 0)
def test_created(self): """Basic functionality of created filter.""" created_ds = datetime(2010, 6, 19, 12, 00) # on 6/19/2010 q1 = question(title=u'q1 audio', created=created_ds, save=True) q1.tags.add(u'desktop') ans = answer(question=q1, save=True) answervote(answer=ans, helpful=True, save=True) # on 6/21/2010 q2 = question(title=u'q2 audio', created=(created_ds + timedelta(days=2)), save=True) q2.tags.add(u'desktop') ans = answer(question=q2, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {'a': 1, 'w': 2, 'format': 'json', 'sortby': 2, 'created_date': '06/20/2010'} qs['created'] = constants.INTERVAL_BEFORE response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([q1.get_absolute_url()], [r['url'] for r in results]) qs['created'] = constants.INTERVAL_AFTER response = self.client.get(reverse('search'), qs) results = json.loads(response.content)['results'] eq_([q2.get_absolute_url()], [r['url'] for r in results])
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) r = self.client.get(all_docs_url, follow=True) parsed = pq(r.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_advanced_search_sortby_documents_helpful(self): """Tests advanced search with a sortby_documents by helpful""" r1 = revision(is_approved=True, save=True) r2 = revision(is_approved=True, save=True) helpful_vote(revision=r2, helpful=True, save=True) # Note: We have to wipe and rebuild the index because new # helpful_votes don't update the index data. self.setup_indexes() self.reindex_and_refresh() # r2.document should come first with 1 vote. response = self.client.get(reverse('search'), { 'w': '1', 'a': '1', 'sortby_documents': 'helpful', 'format': 'json'}) eq_(200, response.status_code) content = json.loads(response.content) eq_(r2.document.title, content['results'][0]['title']) # Vote twice on r1, now it should come first. helpful_vote(revision=r1, helpful=True, save=True) helpful_vote(revision=r1, helpful=True, save=True) self.setup_indexes() self.reindex_and_refresh() response = self.client.get(reverse('search'), { 'w': '1', 'a': '1', 'sortby_documents': 'helpful', 'format': 'json'}) eq_(200, response.status_code) content = json.loads(response.content) eq_(r1.document.title, content['results'][0]['title'])
def test_new_user(self, get_current): get_current.return_value.domain = 'su.mo.com' response = self.client.post(reverse('users.register', locale='en-US'), {'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foobar22'}, follow=True) eq_(200, response.status_code) u = User.objects.get(username='******') assert u.password.startswith('sha256') assert not u.is_active eq_(1, len(mail.outbox)) assert mail.outbox[0].subject.find('Please confirm your') == 0 key = RegistrationProfile.objects.all()[0].activation_key assert mail.outbox[0].body.find('activate/%s/%s' % (u.id, key)) > 0 # By default, users aren't added to any groups eq_(0, len(u.groups.all())) # Now try to log in u.is_active = True u.save() response = self.client.post(reverse('users.login', locale='en-US'), {'username': '******', 'password': '******'}, follow=True) eq_(200, response.status_code) eq_('http://testserver/en-US/home', response.redirect_chain[0][0])
def login(request, template): """Try to log the user in.""" if request.method == 'GET' and not request.MOBILE: url = reverse('users.auth') + '?' + request.GET.urlencode() return HttpResponsePermanentRedirect(url) next_url = get_next_url(request) or reverse('home') form = handle_login(request) if request.user.is_authenticated(): # Add a parameter so we know the user just logged in. # fpa = "first page authed" or something. next_url = urlparams(next_url, fpa=1) res = HttpResponseRedirect(next_url) max_age = (None if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE else settings.SESSION_COOKIE_AGE) res.set_cookie(settings.SESSION_EXISTS_COOKIE, '1', secure=False, max_age=max_age) return res if request.MOBILE: return jingo.render(request, template, { 'form': form, }) return user_auth(request, login_form=form)
def _format_row_with_out_of_dateness(readout_locale, eng_slug, eng_title, slug, title, visits, significance, needs_review): """Format a row for a readout that has the traffic-light-style categorization of how seriously out of date a translation is.""" if slug: # A translation exists but may not be approved. locale = readout_locale status, view_name, status_class = SIGNIFICANCE_STATUSES.get( significance, REVIEW_STATUSES[needs_review]) status_url = (reverse(view_name, args=[slug], locale=locale) if view_name else '') else: slug = eng_slug title = eng_title locale = settings.WIKI_DEFAULT_LANGUAGE status = _(u'Translation Needed') # When calling the translate view, specify locale to translate to: status_url = reverse('wiki.translate', args=[slug], locale=readout_locale) status_class = 'untranslated' return dict(title=title, url=reverse('wiki.document', args=[slug], locale=locale), visits=visits, status=status, status_class=status_class, status_url=status_url)
def test_advanced_search_questions_num_votes(self): """Tests advanced search for questions num_votes filter""" q = question(title=u"tags tags tags", save=True) # Add two question votes questionvote(question=q, save=True) questionvote(question=q, save=True) self.refresh() # Advanced search for questions with num_votes > 5. The above # question should be not in this set. response = self.client.get( reverse("search"), {"q": "", "tags": "desktop", "w": "2", "a": "1", "num_voted": 2, "num_votes": 5, "format": "json"}, ) eq_(200, response.status_code) content = json.loads(response.content) eq_(content["total"], 0) # Advanced search for questions with num_votes < 1. The above # question should be not in this set. response = self.client.get( reverse("search"), {"q": "", "tags": "desktop", "w": "2", "a": "1", "num_voted": 1, "num_votes": 1, "format": "json"}, ) eq_(200, response.status_code) content = json.loads(response.content) eq_(content["total"], 0)
def test_document_listing(self, flag_is_active): """Verify /products/<product slug>/<topic slug> renders articles.""" flag_is_active.return_value = True # Create a topic and product. t1 = topic(save=True) t2 = topic(save=True) p = product(save=True) # Create 3 documents with the topic and product and one without. for i in range(3): doc = revision(is_approved=True, save=True).document doc.topics.add(t1) doc.products.add(p) if i == 1: # Only one document with t2 doc.topics.add(t2) doc = revision(is_approved=True, save=True).document self.refresh() # GET the page and verify the content. url = reverse('products.documents', args=[p.slug, t1.slug]) r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_(3, len(doc('#document-list > ul > li'))) # GET the page with refine topic and verify the content. url = reverse('products.documents', args=[p.slug, t1.slug]) url = urlparams(url, refine=t2.slug) r = self.client.get(url, follow=True) eq_(200, r.status_code) doc = pq(r.content) eq_(1, len(doc('#document-list > ul > li')))
def test_invalid_slugs(self, get_current): """Slugs cannot contain /.""" get_current.return_value.domain = 'testserver' client = LocalizingClient() client.login(username='******', password='******') data = new_document_data() error = 'The slug provided is not valid.' data['slug'] = 'inva/lid' response = client.post(reverse('wiki.new_document'), data) self.assertContains(response, error) data['slug'] = 'no-question-marks?' response = client.post(reverse('wiki.new_document'), data) self.assertContains(response, error) data['slug'] = 'no+plus' response = client.post(reverse('wiki.new_document'), data) self.assertContains(response, error) data['slug'] = 'valid' response = client.post(reverse('wiki.new_document'), data) self.assertRedirects(response, reverse('wiki.document_revisions', args=[data['slug']], locale='en-US'))
def test_needs_change(self): """Test setting and unsetting the needs change flag""" # Create a new document and edit it, setting needs_change. comment = 'Please update for Firefix.next' doc = revision(save=True).document data = new_document_data() data.update({'needs_change': True, 'needs_change_comment': comment, 'form': 'doc'}) # Verify that needs_change can't be set if the user doesn't have # the permission. self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data) doc = Document.uncached.get(pk=doc.pk) assert not doc.needs_change assert not doc.needs_change_comment # Give the user permission, now it should work. add_permission(self.u, Document, 'edit_needs_change') self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data) doc = Document.uncached.get(pk=doc.pk) assert doc.needs_change eq_(comment, doc.needs_change_comment) # Clear out needs_change. data.update({'needs_change': False, 'needs_change_comment': comment}) self.client.post(reverse('wiki.edit_document', args=[doc.slug]), data) doc = Document.uncached.get(pk=doc.pk) assert not doc.needs_change eq_('', doc.needs_change_comment)
def devmo_url(context, path): """ Create a URL pointing to devmo. Look for a wiki page in the current locale, or default to given path """ if hasattr(context["request"], "locale"): locale = context["request"].locale else: locale = settings.WIKI_DEFAULT_LANGUAGE try: url = cache.get("devmo_url:%s_%s" % (locale, path)) except: return path if not url: url = reverse("wiki.document", locale=settings.WIKI_DEFAULT_LANGUAGE, args=[path]) if locale != settings.WIKI_DEFAULT_LANGUAGE: try: parent = Document.objects.get(locale=settings.WIKI_DEFAULT_LANGUAGE, slug=path) """ # TODO: redirect_document is coupled to doc view follow redirects vs. update devmo_url calls target = parent.redirect_document() if target: parent = target """ child = Document.objects.get(locale=locale, parent=parent) url = reverse("wiki.document", locale=locale, args=[child.slug]) except Document.DoesNotExist: pass cache.set("devmo_url:%s_%s" % (locale, path), url) return url
def test_created(self): """Basic functionality of created filter.""" created_ds = datetime(2010, 6, 19, 12, 00) # on 6/19/2010 q1 = question(title=u"q1 audio", created=created_ds, save=True) q1.tags.add(u"desktop") ans = answer(question=q1, save=True) answervote(answer=ans, helpful=True, save=True) # on 6/21/2010 q2 = question(title=u"q2 audio", created=(created_ds + timedelta(days=2)), save=True) q2.tags.add(u"desktop") ans = answer(question=q2, save=True) answervote(answer=ans, helpful=True, save=True) self.refresh() qs = {"a": 1, "w": 2, "format": "json", "sortby": 2, "created_date": "06/20/2010"} qs["created"] = constants.INTERVAL_BEFORE response = self.client.get(reverse("search"), qs) results = json.loads(response.content)["results"] eq_([q1.get_absolute_url()], [r["url"] for r in results]) qs["created"] = constants.INTERVAL_AFTER response = self.client.get(reverse("search"), qs) results = json.loads(response.content)["results"] eq_([q2.get_absolute_url()], [r["url"] for r in results])
def test_my_profile_edit(self): u = User.objects.get(username='******') self.client.login(username=u.username, password=TESTUSER_PASSWORD) resp = self.client.get(reverse('users.my_profile_edit')) eq_(302, resp.status_code) ok_(reverse('users.profile_edit', args=(u.username,)) in resp['Location'])
def test_new_contributor(self, get_current): """Verify that interested contributors are added to group.""" get_current.return_value.domain = 'su.mo.com' group_name = 'Registered as contributor' group(name=group_name, save=True) data = { 'username': '******', 'email': '*****@*****.**', 'password': '******', 'password2': 'foobar22', 'interested': 'yes'} response = self.client.post(reverse('users.register', locale='en-US'), data, follow=True) eq_(200, response.status_code) u = User.objects.get(username='******') eq_(group_name, u.groups.all()[0].name) # Activate user and verify email is sent. key = RegistrationProfile.objects.all()[0].activation_key url = reverse('users.activate', args=[u.id, key]) response = self.client.get(url, follow=True) eq_(200, response.status_code) eq_(2, len(mail.outbox)) assert mail.outbox[1].subject.find('Welcome to') == 0 assert u.username in mail.outbox[1].body
def test_redirect_permanent(self): resp = redirect_to(self.rf.get('/'), url='home') assert isinstance(resp, HttpResponsePermanentRedirect) eq_(reverse('home'), resp['location'])
def test_top_text(self): response = self.client.get(reverse('home.mobile'), follow=True) self.assertContains(response, 'Firefox for Mobile')
class UnreadyForLocalizationReadout(Readout): """Articles which have approved but unready revisions newer than their latest ready-for-l10n ones""" title = _lazy(u'Changes Not Ready For Localization') description = _lazy(u'Articles which have approved revisions newer than ' 'the latest ready-for-localization one') # No short_title; the Contributors dash lacks an Overview readout details_link_text = _lazy(u'All articles with changes not ready for ' 'localization...') slug = 'unready' column4_label = _lazy(u'Approved') def _query_and_params(self, max): # Filter by product if specified. if self.product: extra_joins = PRODUCT_FILTER params = (LAST_30_DAYS, self.product.id, settings.WIKI_DEFAULT_LANGUAGE, TYPO_SIGNIFICANCE) else: extra_joins = '' params = (LAST_30_DAYS, settings.WIKI_DEFAULT_LANGUAGE, TYPO_SIGNIFICANCE) query = ( 'SELECT engdoc.slug, engdoc.title, ' 'MAX(wiki_revision.reviewed) maxreviewed, ' 'visits.visits ' 'FROM wiki_document engdoc ' 'INNER JOIN wiki_revision ON ' 'engdoc.id=wiki_revision.document_id ' 'LEFT JOIN dashboards_wikidocumentvisits visits ON ' 'engdoc.id=visits.document_id AND ' 'visits.period=%s ' + extra_joins + 'WHERE engdoc.locale=%s ' # shouldn't be necessary 'AND NOT engdoc.is_archived ' 'AND engdoc.is_localizable ' 'AND (engdoc.current_revision_id>' 'engdoc.latest_localizable_revision_id OR ' 'engdoc.latest_localizable_revision_id IS NULL) ' # When picking the max(reviewed) date, consider only revisions that # are ripe to be marked Ready: 'AND wiki_revision.is_approved ' 'AND NOT wiki_revision.is_ready_for_localization ' 'AND (wiki_revision.significance>%s OR ' 'wiki_revision.significance IS NULL) ' # initial revision # An optimization: minimize rows before max(): 'AND (wiki_revision.id>' 'engdoc.latest_localizable_revision_id OR ' 'engdoc.latest_localizable_revision_id IS NULL) ' 'GROUP BY engdoc.id ' + self._order_clause() + self._limit_clause(max)) return query, params def _order_clause(self): # Put the most recently approved articles first, as those are the most # recent to have transitioned onto this dashboard or to change which # revision causes them to be on this dashboard. return ('ORDER BY maxreviewed DESC' if self.mode == MOST_RECENT else 'ORDER BY visits.visits DESC, engdoc.title ASC') def _format_row(self, (slug, title, reviewed, visits)): return dict(title=title, url=reverse('wiki.document_revisions', args=[slug], locale=settings.WIKI_DEFAULT_LANGUAGE), visits=visits, updated=reviewed)
class UnreviewedReadout(Readout): # L10n: Not just changes to translations but also unreviewed changes to # docs in this locale that are not translations title = _lazy(u'Unreviewed Changes') short_title = _lazy(u'Unreviewed', 'document') details_link_text = _lazy(u'All articles requiring review...') slug = 'unreviewed' column4_label = _lazy(u'Changed') def _query_and_params(self, max): english_id = ('id' if self.locale == settings.WIKI_DEFAULT_LANGUAGE else 'parent_id') # Filter by product if specified. if self.product: extra_joins = ('INNER JOIN wiki_document_products docprod ON ' 'docprod.document_id=wiki_document.' + english_id + ' ' 'AND docprod.product_id=%s ') params = (LAST_30_DAYS, self.product.id, self.locale) else: extra_joins = '' params = (LAST_30_DAYS, self.locale) query = ( 'SELECT wiki_document.slug, wiki_document.title, ' 'MAX(wiki_revision.created) maxcreated, ' 'GROUP_CONCAT(DISTINCT auth_user.username ' "ORDER BY wiki_revision.id SEPARATOR ', '), " 'dashboards_wikidocumentvisits.visits ' 'FROM wiki_document ' 'INNER JOIN wiki_revision ON ' 'wiki_document.id=wiki_revision.document_id ' 'INNER JOIN auth_user ON wiki_revision.creator_id=auth_user.id ' 'LEFT JOIN dashboards_wikidocumentvisits ON ' 'wiki_document.' + english_id + '=dashboards_wikidocumentvisits.document_id AND ' 'dashboards_wikidocumentvisits.period=%s ' + extra_joins + 'WHERE wiki_revision.reviewed IS NULL ' 'AND (wiki_document.current_revision_id IS NULL OR ' 'wiki_revision.id>wiki_document.current_revision_id) ' 'AND wiki_document.locale=%s AND NOT wiki_document.is_archived ' 'GROUP BY wiki_document.id ' + self._order_clause() + self._limit_clause(max)) return query, params def _order_clause(self): return ('ORDER BY maxcreated DESC' if self.mode == MOST_RECENT else 'ORDER BY dashboards_wikidocumentvisits.visits DESC, ' 'wiki_document.title ASC') def _format_row(self, (slug, title, changed, users, visits)): return dict(title=title, url=reverse('wiki.document_revisions', args=[slug], locale=self.locale), visits=visits, updated=changed, users=users)
class OutOfDateReadout(Readout): title = _lazy(u'Immediate Updates Needed') description = _lazy( u'This indicates a major edit which changes the content of the article' ' enough to hurt the value of the localization. Until it is updated, ' 'the localized page will warn users that it may be outdated. You ' 'should update these articles as soon as possible.') short_title = _lazy(u'Immediate Updates Needed') details_link_text = _lazy(u'All translations needing immediate updates...') slug = 'out-of-date' column4_label = _lazy(u'Out of date since') # To show up in this readout, an article's revision since the last # approved translation must have a maximum significance equal to this # value: _max_significance = MAJOR_SIGNIFICANCE def _query_and_params(self, max): # Filter by product if specified. if self.product: extra_joins = PRODUCT_FILTER params = (MEDIUM_SIGNIFICANCE, self._max_significance, LAST_30_DAYS, self.product.id, self.locale) else: extra_joins = '' params = (MEDIUM_SIGNIFICANCE, self._max_significance, LAST_30_DAYS, self.locale) # At the moment, the "Out of Date Since" column shows the time since # the translation was out of date at a MEDIUM level of severity or # higher. We could arguably knock this up to MAJOR, but technically it # is out of date when the original gets anything more than typo # corrections. # TODO: This is wrong because it uses the reviewed date to calculate # "Out of date since", instead of using the ready for l10n date. # To fix it is pretty hairy though. What a query!!! query = ( 'SELECT transdoc.slug, transdoc.title, engrev.reviewed, ' 'dashboards_wikidocumentvisits.visits ' 'FROM wiki_document transdoc ' 'INNER JOIN wiki_document engdoc ON transdoc.parent_id=engdoc.id ' 'INNER JOIN wiki_revision engrev ON engrev.id=' # The oldest English rev to have an approved, ready-for- # localization level-30 change since the translated doc had an # approved rev based on it. NULL if there is none: '(SELECT min(id) FROM wiki_revision ' # Narrow engrev rows to those representing revision of parent # doc: 'WHERE wiki_revision.document_id=transdoc.parent_id ' # For the purposes of computing the "Out of Date Since" column, # the revision that threw the translation out of date had # better be more recent than the one the current translation is # based on: 'AND wiki_revision.id>' '(SELECT based_on_id FROM wiki_revision basedonrev ' 'WHERE basedonrev.id=transdoc.current_revision_id) ' 'AND wiki_revision.significance>=%s ' 'AND %s=' # Completely filter out outer selections where 30 is not the # max signif of approved English revisions since trans was last # approved. Other maxes will be shown by other readouts. # Optimize: try "30 IN" if MySQL's statistics gatherer is # stupid/nonexistent; the inner query should be able to bail # out early. [Ed: No effect on EXPLAIN on admittedly light test # corpus.] '(SELECT MAX(engsince.significance) ' 'FROM wiki_revision engsince ' 'WHERE engsince.document_id=transdoc.parent_id ' # Assumes that any approved revision became the current # revision at some point: we don't let the user go back and # approve revisions older than the latest approved one. 'AND engsince.is_approved ' # Consider revisions between the one the last translation # was based on and the latest ready-for-l10n one. 'AND engsince.id>' # The English revision the current translation's based on: '(SELECT based_on_id FROM wiki_revision basedonrev ' 'WHERE basedonrev.id=transdoc.current_revision_id) ' 'AND engsince.id<=engdoc.latest_localizable_revision_id' ')' ') ' # Join up the visits table for stats: 'LEFT JOIN dashboards_wikidocumentvisits ON ' 'engrev.document_id=dashboards_wikidocumentvisits.document_id ' 'AND dashboards_wikidocumentvisits.period=%s ' + extra_joins + # We needn't check is_localizable, since the models ensure every # document with translations has is_localizable set. 'WHERE transdoc.locale=%s AND NOT transdoc.is_archived AND ' 'transdoc.category in (10, 20, 60) ' + self._order_clause() + self._limit_clause(max)) return query, params def _order_clause(self): return ('ORDER BY engrev.reviewed DESC' if self.mode == MOST_RECENT else 'ORDER BY dashboards_wikidocumentvisits.visits DESC, ' 'transdoc.title ASC') def _format_row(self, (slug, title, reviewed, visits)): return dict(title=title, url=reverse('wiki.edit_document', args=[slug]), visits=visits, updated=reviewed)
def setUp(self): self.user = user() self.user.save() self.profile = profile(user=self.user) self.url = reverse('users.profile', args=[self.user.pk], locale='en-US')
def test_redirect(self): """Test our redirect from old url to new one.""" response = self.client.get(reverse('users.old_change_email', locale='en-US'), follow=False) eq_(301, response.status_code) eq_('http://testserver/en-US/users/change_email', response['location'])
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 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_search_view(self): try: self.client.get(reverse('demos_search')) except: self.fail("Search should not ISE.")
def test_anonymous_user(self): """Checks the locale dashboard doesn't load for an anonymous user.""" response = self.client.get( reverse('dashboards.group', args=[self.g.pk], locale='en-US')) eq_(302, response.status_code) assert '/users/login' in response['location']
def test_submit_loggedin(self): r = self.client.get(reverse('demos_submit')) assert pq(r.content)('form#demo-submit')
def test_active(self): """Active announcement shows.""" announcement(creator=self.creator).save() response = self.client.get(reverse('dashboards.review'), follow=True) self.assertContains(response, 'stardate 43124.5')
def get_user_url(user): from sumo.urlresolvers import reverse return reverse('users.profile', args=[user.username])
def test_gallery_invalid_type(self): url = reverse('gallery.gallery', args=['foo']) response = self.client.get(url, follow=True) eq_(404, response.status_code)
def test_no_announcements(self): """Template renders with no announcements.""" response = self.client.get(reverse('dashboards.review'), follow=True) doc = pq(response.content) assert not len(doc('ol.announcements'))
def test_search_description(self): url = reverse('gallery.search', args=['image']) response = self.client.get(url, {'q': 'migrated'}, follow=True) doc = pq(response.content) eq_(5, len(doc('#media-list li')))
def test_redirect(self): """/gallery redirects to /gallery/images""" response = self.client.get(reverse('gallery.home', locale='en-US'), follow=False) eq_(301, response.status_code) eq_('http://testserver/en-US/gallery/images', response['location'])
def test_image_search(self): url = reverse('gallery.search', args=['image']) response = self.client.get(url, {'q': 'quicktime'}, follow=True) doc = pq(response.content) eq_(1, len(doc('#media-list li')))
def test_search_nonexistent(self): url = reverse('gallery.search', args=['foo']) response = self.client.get(url, {'q': 'foo'}, follow=True) eq_(404, response.status_code)
def translate(request, document_slug, revision_id=None): """Create a new translation of a wiki document. * document_slug is for the default locale * translation is to the request locale """ # TODO: Refactor this view into two views? (new, edit) # That might help reduce the headache-inducing branchiness. parent_doc = get_object_or_404(Document, locale=settings.WIKI_DEFAULT_LANGUAGE, slug=document_slug) user = request.user if settings.WIKI_DEFAULT_LANGUAGE == request.locale: # Don't translate to the default language. return HttpResponseRedirect( reverse('wiki.edit_document', locale=settings.WIKI_DEFAULT_LANGUAGE, args=[parent_doc.slug])) if not parent_doc.is_localizable: message = _lazy(u'You cannot translate this document.') return jingo.render(request, 'handlers/400.html', {'message': message}, status=400) based_on_rev = parent_doc.localizable_or_latest_revision( include_rejected=True) disclose_description = bool(request.GET.get('opendescription')) try: doc = parent_doc.translations.get(locale=request.locale) except Document.DoesNotExist: doc = None disclose_description = True user_has_doc_perm = ((not doc) or (doc and doc.allows_editing_by(user))) user_has_rev_perm = ((not doc) or (doc and doc.allows_revision_by(user))) if not user_has_doc_perm and not user_has_rev_perm: # User has no perms, bye. raise PermissionDenied doc_form = rev_form = None base_rev = None if user_has_doc_perm: doc_initial = _document_form_initial(doc) if doc else None doc_form = DocumentForm( initial=doc_initial, can_create_tags=user.has_perm('taggit.add_tag')) if user_has_rev_perm: initial = {'based_on': based_on_rev.id, 'comment': ''} if revision_id: base_rev = Revision.objects.get(pk=revision_id) initial.update(content=base_rev.content, summary=base_rev.summary, keywords=base_rev.keywords) elif not doc: initial.update(content=based_on_rev.content, summary=based_on_rev.summary, keywords=based_on_rev.keywords) # Get a revision of the translation to plonk into the page as a # starting point. Since translations are never "ready for # localization", this will first try to find an approved revision, then # an unrejected one, then give up. instance = doc and doc.localizable_or_latest_revision() rev_form = RevisionForm(instance=instance, initial=initial) base_rev = base_rev or instance if request.method == 'POST': which_form = request.POST.get('form', 'both') doc_form_invalid = False if user_has_doc_perm and which_form in ['doc', 'both']: disclose_description = True post_data = request.POST.copy() post_data.update({'locale': request.locale}) doc_form = DocumentForm( post_data, instance=doc, can_create_tags=user.has_perm('taggit.add_tag')) doc_form.instance.locale = request.locale doc_form.instance.parent = parent_doc if which_form == 'both': rev_form = RevisionForm(request.POST) # If we are submitting the whole form, we need to check that # the Revision is valid before saving the Document. if doc_form.is_valid() and (which_form == 'doc' or rev_form.is_valid()): doc = doc_form.save(parent_doc) # Possibly schedule a rebuild. _maybe_schedule_rebuild(doc_form) if which_form == 'doc': url = urlparams(reverse('wiki.edit_document', args=[doc.slug]), opendescription=1) return HttpResponseRedirect(url) doc_slug = doc_form.cleaned_data['slug'] else: doc_form_invalid = True else: doc_slug = doc.slug if doc and user_has_rev_perm and which_form in ['rev', 'both']: rev_form = RevisionForm(request.POST) rev_form.instance.document = doc # for rev_form.clean() if rev_form.is_valid() and not doc_form_invalid: _save_rev_and_notify(rev_form, request.user, doc) url = reverse('wiki.document_revisions', args=[doc_slug]) return HttpResponseRedirect(url) show_revision_warning = _show_revision_warning(doc, base_rev) return jingo.render( request, 'wiki/translate.html', { 'parent': parent_doc, 'document': doc, 'document_form': doc_form, 'revision_form': rev_form, 'locale': request.locale, 'based_on': based_on_rev, 'disclose_description': disclose_description, 'show_revision_warning': show_revision_warning })
def test_video_search(self): url = reverse('gallery.search', args=['video']) response = self.client.get(url, {'q': '1802'}, follow=True) doc = pq(response.content) eq_(1, len(doc('#media-list li')))
def edit_document(request, document_slug, revision_id=None): """Create a new revision of a wiki document, or edit document metadata.""" doc = get_object_or_404(Document, locale=request.locale, slug=document_slug) user = request.user # If this document has a parent, then the edit is handled by the # translate view. Pass it on. if doc.parent: return translate(request, doc.parent.slug, revision_id) 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] disclose_description = bool(request.GET.get('opendescription')) doc_form = rev_form = None if doc.allows_revision_by(user): rev_form = RevisionForm(instance=rev, initial={ 'based_on': rev.id, 'comment': '' }) if doc.allows_editing_by(user): doc_form = DocumentForm( initial=_document_form_initial(doc), can_create_tags=user.has_perm('taggit.add_tag'), can_archive=user.has_perm('wiki.archive_document')) 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 # 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(user): post_data = request.POST.copy() post_data.update({'locale': request.locale}) doc_form = DocumentForm( post_data, instance=doc, can_create_tags=user.has_perm('taggit.add_tag'), can_archive=user.has_perm('wiki.archive_document')) if doc_form.is_valid(): # Get the possibly new slug for the imminent redirection: doc = doc_form.save(None) # Do we need to rebuild the KB? _maybe_schedule_rebuild(doc_form) return HttpResponseRedirect( urlparams(reverse('wiki.edit_document', args=[doc.slug]), opendescription=1)) disclose_description = True else: raise PermissionDenied elif which_form == 'rev': if doc.allows_revision_by(user): rev_form = RevisionForm(request.POST) rev_form.instance.document = doc # for rev_form.clean() if rev_form.is_valid(): _save_rev_and_notify(rev_form, user, doc) if 'notify-future-changes' in request.POST: EditDocumentEvent.notify(request.user, doc) return HttpResponseRedirect( reverse('wiki.document_revisions', args=[document_slug])) else: raise PermissionDenied show_revision_warning = _show_revision_warning(doc, rev) return jingo.render( request, 'wiki/edit_document.html', { 'revision_form': rev_form, 'document_form': doc_form, 'disclose_description': disclose_description, 'document': doc, 'show_revision_warning': show_revision_warning })
def setUp(self): url_ = reverse('forums.threads', args=[u'testslug']) self.context = {'request': test_utils.RequestFactory().get(url_)} self.context['request'].locale = u'en-US'
def test_fallback_with_query_params(self): """The query parameters should be passed along to the redirect.""" en_doc, de_doc = self._create_en_and_de_docs() url = reverse('wiki.document', args=[en_doc.slug], locale='de') response = self.client.get(url + '?x=y&x=z', follow=True) self.assertRedirects(response, de_doc.get_absolute_url() + '?x=y&x=z')
def review_revision(request, document_slug, revision_id): """Review a revision of a wiki document.""" rev = get_object_or_404(Revision, pk=revision_id, document__slug=document_slug) doc = rev.document form = ReviewForm( initial={ 'needs_change': doc.needs_change, 'needs_change_comment': doc.needs_change_comment }) # Don't ask significance if this doc is a translation or if it has no # former approved versions: should_ask_significance = not doc.parent and doc.current_revision based_on_revs = doc.revisions.all() last_approved_date = getattr(doc.current_revision, 'created', datetime.fromordinal(1)) based_on_revs = based_on_revs.filter(created__gt=last_approved_date) recent_contributors = based_on_revs.values_list('creator__username', flat=True) if request.method == 'POST': form = ReviewForm(request.POST) if form.is_valid() and not rev.reviewed: # Don't allow revisions to be reviewed twice rev.is_approved = 'approve' in request.POST rev.reviewer = request.user rev.reviewed = datetime.now() if should_ask_significance and form.cleaned_data['significance']: rev.significance = form.cleaned_data['significance'] # If document is localizable and revision was approved and # user has permission, set the is_ready_for_localization value. if (doc.is_localizable and rev.is_approved and request.user.has_perm('wiki.mark_ready_for_l10n')): rev.is_ready_for_localization = form.cleaned_data[ 'is_ready_for_localization'] rev.save() # Update the needs change bit (if approved, default language and # user has permission). if (doc.locale == settings.WIKI_DEFAULT_LANGUAGE and doc.allows_editing_by(request.user) and rev.is_approved): doc.needs_change = form.cleaned_data['needs_change'] doc.needs_change_comment = \ form.cleaned_data['needs_change_comment'] doc.save() # Send notifications of approvedness and readiness: if rev.is_ready_for_localization or rev.is_approved: events = [ApproveRevisionInLocaleEvent(rev)] if rev.is_ready_for_localization: events.append(ReadyRevisionEvent(rev)) ApprovedOrReadyUnion(*events).fire( exclude=[rev.creator, request.user]) # Send an email (not really a "notification" in the sense that # there's a Watch table entry) to revision creator. msg = form.cleaned_data['comment'] send_reviewed_notification.delay(rev, doc, msg) send_contributor_notification(based_on_revs, rev, doc, msg) # Schedule KB rebuild? statsd.incr('wiki.review') schedule_rebuild_kb() return HttpResponseRedirect( reverse('wiki.document_revisions', args=[document_slug])) if doc.parent: # A translation # For diffing the based_on revision against, to help the user see if he # translated all the recent changes: parent_revision = doc.parent.localizable_or_latest_revision() template = 'wiki/review_translation.html' else: parent_revision = None template = 'wiki/review_revision.html' data = { 'revision': rev, 'document': doc, 'form': form, 'parent_revision': parent_revision, 'recent_contributors': list(recent_contributors), 'should_ask_significance': should_ask_significance } data.update(SHOWFOR_DATA) return jingo.render(request, template, data)
def test_helpful_vote_no_id(self): """Throw helpful_vote a POST without an ID and see if it 400s.""" response = self.client.post(reverse('wiki.document_vote', args=['hi']), {}) eq_(400, response.status_code)
def _get_next_url_fallback_localization(request): return get_next_url(request) or reverse('dashboards.localization')
def test_helpful_vote_bad_id(self): """Throw helpful_vote a bad ID, and see if it crashes.""" response = self.client.post(reverse('wiki.document_vote', args=['hi']), {'revision_id': 'x'}) eq_(404, response.status_code)
def test_home_redirect(self): """Going to /kb/ should redirect to /home/.""" resp = self.client.get(reverse('wiki.home', locale='en-US')) self.assertRedirects(resp, reverse('home', locale='en-US'), status_code=301)