def test_watch_solution_and_replies(self): """User subscribes to solution and replies: page doesn't break""" self.client.login(username="******", password="******") user = User.objects.get(username="******") QuestionReplyEvent.notify(user, self.question) QuestionSolvedEvent.notify(user, self.question) response = get(self.client, "questions.answers", args=[self.question.id]) eq_(200, response.status_code)
def test_watch_solution_and_replies(self): """User subscribes to solution and replies: page doesn't break""" self.client.login(username='******', password='******') user = User.objects.get(username='******') QuestionReplyEvent.notify(user, self.question) QuestionSolvedEvent.notify(user, self.question) response = get(self.client, 'questions.answers', args=[self.question.id]) eq_(200, response.status_code)
def save(self, no_update=False, *args, **kwargs): """Override save method to take care of updated.""" new = not self.id if not new and not no_update: self.updated = datetime.now() super(Question, self).save(*args, **kwargs) if new: # Avoid circular import, events.py imports Question from questions.events import QuestionReplyEvent # Authors should automatically watch their own questions. QuestionReplyEvent.notify(self.creator, self)
def save(self, no_update=False, *args, **kwargs): """Override save method to take care of updated.""" new = not self.id if not new: self.clear_cached_html() if not no_update: self.updated = datetime.now() super(Question, self).save(*args, **kwargs) if new: # Avoid circular import, events.py imports Question from questions.events import QuestionReplyEvent # Authors should automatically watch their own questions. QuestionReplyEvent.notify(self.creator, self)
def test_answer_notification(self, get_current): """Assert that hitting the watch toggle toggles and that proper mails are sent to anonymous users, registered users, and the question asker.""" # TODO: This test is way too monolithic, and the fixtures encode # assumptions that aren't obvious here. Split this test into about 5, # each of which tests just 1 thing. Consider using instantiation # helpers. get_current.return_value.domain = 'testserver' # An arbitrary registered user (pcraciunoiu) watches: question = self._toggle_watch_question('reply', turn_on=True) # An anonymous user watches: QuestionReplyEvent.notify('*****@*****.**', question) # The question asker (jsocol) watches: QuestionReplyEvent.notify(question.creator, question) # Post a reply self.client.login(username='******', password='******') post(self.client, 'questions.reply', {'content': 'an answer'}, args=[question.id]) answer = Answer.uncached.filter().order_by('-id')[0] # Order of emails is not important. attrs_eq(mail.outbox[0], to=['user47963@nowhere'], subject='%s commented on a Firefox question ' "you're watching" % answer.creator.username) starts_with(mail.outbox[0].body, ANSWER_EMAIL.format(answer=answer.id)) attrs_eq(mail.outbox[1], to=[question.creator.email], subject='%s posted an answer to your question "%s"' % (answer.creator.username, question.title)) starts_with(mail.outbox[1].body, ANSWER_EMAIL_TO_ASKER.format(answer=answer.id)) attrs_eq(mail.outbox[2], to=['*****@*****.**'], subject="%s commented on a Firefox question you're watching" % answer.creator.username) starts_with(mail.outbox[2].body, ANSWER_EMAIL_TO_ANONYMOUS.format(answer=answer.id)) self._toggle_watch_question('reply', turn_on=False)
def watch_question(request, question_id): """Start watching a question for replies or solution.""" question = get_object_or_404(Question, pk=question_id) form = WatchQuestionForm(request.user, request.POST) # Process the form msg = None if form.is_valid(): user_or_email = (request.user if request.user.is_authenticated() else form.cleaned_data['email']) try: if form.cleaned_data['event_type'] == 'reply': QuestionReplyEvent.notify(user_or_email, question) else: QuestionSolvedEvent.notify(user_or_email, question) except ActivationRequestFailed: msg = _('Could not send a message to that email address.') # Respond to ajax request if request.is_ajax(): if form.is_valid(): msg = msg or (_('You will be notified of updates by email.') if request.user.is_authenticated() else _( 'You should receive an email shortly ' 'to confirm your subscription.')) return HttpResponse(json.dumps({'message': msg})) if request.POST.get('from_vote'): tmpl = 'questions/includes/question_vote_thanks.html' else: tmpl = 'questions/includes/email_subscribe.html' html = jingo.render_to_string(request, tmpl, { 'question': question, 'watch_form': form }) return HttpResponse(json.dumps({'html': html})) # Respond to normal request if form.is_valid() and not msg: return HttpResponseRedirect(question.get_absolute_url()) return answers(request, question.id, watch_form=form, message=msg)
def save(self, no_update=False, *args, **kwargs): """Override save method to take care of updated.""" new = not self.id if not new and not no_update: self.updated = datetime.now() # Generate a confirmation_id if necessary if new and not self.confirmation_id: chars = [random.choice(string.ascii_letters) for x in xrange(10)] self.confirmation_id = "".join(chars) super(Question, self).save(*args, **kwargs) if new: # Avoid circular import, events.py imports Question from questions.events import QuestionReplyEvent # Authors should automatically watch their own questions. QuestionReplyEvent.notify(self.creator, self)
def reply(request, question_id): """Post a new answer to a question.""" question = get_object_or_404(Question, pk=question_id) answer_preview = None if question.is_locked: raise PermissionDenied form = AnswerForm(request.POST) # NOJS: delete images if 'delete_images' in request.POST: for image_id in request.POST.getlist('delete_image'): ImageAttachment.objects.get(pk=image_id).delete() return answers(request, question_id=question_id, form=form) # NOJS: upload image if 'upload_image' in request.POST: upload_imageattachment(request, question) return answers(request, question_id=question_id, form=form) if form.is_valid(): answer = Answer(question=question, creator=request.user, content=form.cleaned_data['content']) if 'preview' in request.POST: answer_preview = answer else: answer.save() ct = ContentType.objects.get_for_model(answer) # Move over to the answer all of the images I added to the # reply form up_images = question.images.filter(creator=request.user) up_images.update(content_type=ct, object_id=answer.id) statsd.incr('questions.answer') if Setting.get_for_user(request.user, 'questions_watch_after_reply'): QuestionReplyEvent.notify(request.user, question) return HttpResponseRedirect(answer.get_absolute_url()) return answers(request, question_id=question_id, form=form, answer_preview=answer_preview)
def watch_question(request, question_id): """Start watching a question for replies or solution.""" question = get_object_or_404(Question, pk=question_id) form = WatchQuestionForm(request.user, request.POST) # Process the form msg = None if form.is_valid(): user_or_email = (request.user if request.user.is_authenticated() else form.cleaned_data['email']) try: if form.cleaned_data['event_type'] == 'reply': QuestionReplyEvent.notify(user_or_email, question) else: QuestionSolvedEvent.notify(user_or_email, question) except ActivationRequestFailed: msg = _('Could not send message to that email address.') # Respond to ajax request if request.is_ajax(): if form.is_valid(): if not msg: msg = (_('You will be notified of updates by email.') if request.user.is_authenticated() else _('You should receive an email shortly ' 'to confirm your subscription.')) return HttpResponse(json.dumps({'message': msg})) if request.POST.get('from_vote'): tmpl = 'questions/includes/question_vote_thanks.html' else: tmpl = 'questions/includes/email_subscribe.html' html = jingo.render_to_string(request, tmpl, {'question': question, 'watch_form': form}) return HttpResponse(json.dumps({'html': html})) # Respond to normal request # TODO: show failure here if email fails to send. if form.is_valid(): return HttpResponseRedirect(question.get_absolute_url()) return answers(request, question.id, watch_form=form)
def save(self, no_update=False, *args, **kwargs): """Override save method to take care of updated.""" new = not self.id if not new and not no_update: self.updated = datetime.now() # Generate a confirmation_id if necessary if new and not self.confirmation_id: chars = [random.choice(string.ascii_letters) for x in xrange(10)] self.confirmation_id = "".join(chars) super(Question, self).save(*args, **kwargs) if new: # Avoid circular import, events.py imports Question from questions.events import QuestionReplyEvent # Authors should automatically watch their own questions. QuestionReplyEvent.notify(self.creator, self)
def test_answer_notification(self, get_current): """Assert that hitting the watch toggle toggles and that proper mails are sent to anonymous users, registered users, and the question asker.""" # TODO: This test is way too monolithic, and the fixtures encode # assumptions that aren't obvious here. Split this test into about 5, # each of which tests just 1 thing. Consider using instantiation # helpers. get_current.return_value.domain = 'testserver' # An arbitrary registered user (pcraciunoiu) watches: question = self._toggle_watch_question('reply', turn_on=True) # An anonymous user watches: QuestionReplyEvent.notify('*****@*****.**', question) # The question asker (jsocol) watches: QuestionReplyEvent.notify(question.creator, question) # Post a reply self.client.login(username='******', password='******') post(self.client, 'questions.reply', {'content': 'an answer'}, args=[question.id]) answer = Answer.uncached.filter().order_by('-id')[0] # Order of emails is not important. attrs_eq(mail.outbox[0], to=['user47963@nowhere'], subject='%s commented on a Firefox question ' "you're watching" % answer.creator.username) starts_with(mail.outbox[0].body, ANSWER_EMAIL.format(answer=answer.id)) attrs_eq(mail.outbox[1], to=[question.creator.email], subject='%s posted an answer to your question "%s"' % (answer.creator.username, question.title)) starts_with(mail.outbox[1].body, ANSWER_EMAIL_TO_ASKER.format( answer=answer.id)) attrs_eq(mail.outbox[2], to=['*****@*****.**'], subject="%s commented on a Firefox question you're watching" % answer.creator.username) starts_with(mail.outbox[2].body, ANSWER_EMAIL_TO_ANONYMOUS.format( answer=answer.id)) self._toggle_watch_question('reply', turn_on=False)
def reply(request, question_id): """Post a new answer to a question.""" question = get_object_or_404(Question, pk=question_id) answer_preview = None if question.is_locked: raise PermissionDenied form = AnswerForm(request.POST) # NOJS: delete images if 'delete_images' in request.POST: for image_id in request.POST.getlist('delete_image'): ImageAttachment.objects.get(pk=image_id).delete() return answers(request, question_id, form) # NOJS: upload image if 'upload_image' in request.POST: upload_imageattachment(request, question) return answers(request, question_id, form) if form.is_valid(): answer = Answer(question=question, creator=request.user, content=form.cleaned_data['content']) if 'preview' in request.POST: answer_preview = answer else: answer.save() ct = ContentType.objects.get_for_model(answer) # Move over to the answer all of the images I added to the # reply form up_images = question.images.filter(creator=request.user) up_images.update(content_type=ct, object_id=answer.id) statsd.incr('questions.answer') if Setting.get_for_user(request.user, 'questions_watch_after_reply'): QuestionReplyEvent.notify(request.user, question) return HttpResponseRedirect(answer.get_absolute_url()) return answers(request, question_id, form, answer_preview=answer_preview)
def watch_question(request, question_id): """Start watching a question for replies or solution.""" question = get_object_or_404(Question, pk=question_id) form = WatchQuestionForm(request.user, request.POST) # Process the form msg = None if form.is_valid(): user_or_email = request.user if request.user.is_authenticated() else form.cleaned_data["email"] try: if form.cleaned_data["event_type"] == "reply": QuestionReplyEvent.notify(user_or_email, question) else: QuestionSolvedEvent.notify(user_or_email, question) statsd.incr("questions.watches.new") except ActivationRequestFailed: msg = _("Could not send a message to that email address.") # Respond to ajax request if request.is_ajax(): if form.is_valid(): msg = msg or ( _("You will be notified of updates by email.") if request.user.is_authenticated() else _("You should receive an email shortly " "to confirm your subscription.") ) return HttpResponse(json.dumps({"message": msg})) if request.POST.get("from_vote"): tmpl = "questions/includes/question_vote_thanks.html" else: tmpl = "questions/includes/email_subscribe.html" html = jingo.render_to_string(request, tmpl, {"question": question, "watch_form": form}) return HttpResponse(json.dumps({"html": html})) if msg: messages.add_message(request, messages.ERROR, msg) return HttpResponseRedirect(question.get_absolute_url())