diff --git a/mozillians/groups/tests/test_views/test_invite.py b/mozillians/groups/tests/test_views/test_invite.py index 7ae9b7cf9..214d68375 100644 --- a/mozillians/groups/tests/test_views/test_invite.py +++ b/mozillians/groups/tests/test_views/test_invite.py @@ -1,7 +1,9 @@ from django.core.urlresolvers import reverse +from mock import patch, ANY from nose.tools import eq_, ok_ +from mozillians.common.templatetags.helpers import urlparams from mozillians.common.tests import TestCase from mozillians.groups.models import GroupMembership, Invite from mozillians.groups.tests import InviteFactory @@ -59,3 +61,51 @@ def test_accept_reject_user_not_redeemer(self): url = reverse('groups:accept_reject_invitation', args=[invite.pk, 'accept']) response = client.get(url, follow=True) eq_(response.status_code, 404) + + @patch('mozillians.groups.views.notify_redeemer_invitation') + @patch('mozillians.groups.views.messages.success') + def test_send_invitation_email(self, mock_success, mock_notification): + curator = UserFactory.create() + redeemer = UserFactory.create(userprofile={'full_name': 'Foo Bar'}) + invite = InviteFactory.create(inviter=curator.userprofile, redeemer=redeemer.userprofile) + invite.group.curators.add(curator.userprofile) + + with self.login(curator) as client: + url = urlparams(reverse('groups:send_invitation_email', + args=[invite.pk]), 'invitation') + response = client.get(url, follow=True) + eq_(response.status_code, 200) + + mock_notification.delay.assert_called_once_with(invite.pk) + msg = 'Invitation to Foo Bar has been sent successfully.' + mock_success.assert_called_once_with(ANY, msg) + + @patch('mozillians.groups.views.notify_redeemer_invitation') + @patch('mozillians.groups.views.messages.success') + def test_send_invitation_email_different_curator(self, mock_success, mock_notification): + curator, inviter = UserFactory.create_batch(2) + redeemer = UserFactory.create(userprofile={'full_name': 'Foo Bar'}) + invite = InviteFactory.create(inviter=inviter.userprofile, redeemer=redeemer.userprofile) + invite.group.curators.add(curator.userprofile) + invite.group.curators.add(inviter.userprofile) + + with self.login(curator) as client: + url = urlparams(reverse('groups:send_invitation_email', + args=[invite.pk]), 'invitation') + response = client.get(url, follow=True) + eq_(response.status_code, 200) + + mock_notification.delay.assert_called_once_with(invite.pk) + msg = 'Invitation to Foo Bar has been sent successfully.' + mock_success.assert_called_once_with(ANY, msg) + + def test_send_invitation_email_no_curator_manager(self): + inviter, redeemer = UserFactory.create_batch(2) + invite = InviteFactory.create(inviter=inviter.userprofile, redeemer=redeemer.userprofile) + user = UserFactory.create() + + with self.login(user) as client: + url = urlparams(reverse('groups:send_invitation_email', + args=[invite.pk]), 'invitation') + response = client.get(url, follow=True) + eq_(response.status_code, 404) diff --git a/mozillians/groups/urls.py b/mozillians/groups/urls.py index 4df434dc4..080448597 100644 --- a/mozillians/groups/urls.py +++ b/mozillians/groups/urls.py @@ -46,6 +46,8 @@ name='curators-autocomplete'), # Invites section url('^groups/invite/(?P\d+)/delete/$', 'views.delete_invite', name='delete_invite'), + url('^groups/invite/(?P\d+)/notify/$', 'views.send_invitation_email', + name='send_invitation_email'), url('^groups/(?P\d+)/(?Paccept|reject)/$', 'views.accept_reject_invitation', name='accept_reject_invitation'), ) diff --git a/mozillians/groups/views.py b/mozillians/groups/views.py index 7f76a40ba..c44434838 100644 --- a/mozillians/groups/views.py +++ b/mozillians/groups/views.py @@ -21,8 +21,9 @@ from mozillians.groups import forms from mozillians.groups.models import Group, GroupMembership, Invite, Skill from mozillians.groups.tasks import (notify_curators_invitation_accepted, - notify_redeemer_invitation_invalid, - notify_curators_invitation_rejected) + notify_curators_invitation_rejected, + notify_redeemer_invitation, + notify_redeemer_invitation_invalid) from mozillians.users.models import UserProfile @@ -554,3 +555,23 @@ def accept_reject_invitation(request, invite_pk, action): invite.delete() return redirect(reverse('groups:show_group', args=[invite.group.url])) + + +@never_cache +def send_invitation_email(request, invite_pk): + """Send group invitation email.""" + + invite = get_object_or_404(Invite, pk=invite_pk) + is_curator = invite.group.curators.filter(pk=request.user.userprofile.pk).exists() + is_manager = request.user.userprofile.is_manager + + if not (is_curator or is_manager): + raise Http404 + + notify_redeemer_invitation.delay(invite.pk) + msg = _(u'Invitation to {0} has been sent successfully.'.format(invite.redeemer)) + messages.success(request, msg) + next_section = request.GET.get('next') + next_url = urlparams(reverse('groups:group_edit', args=[invite.group.url]), next_section) + + return HttpResponseRedirect(next_url) diff --git a/mozillians/jinja2/groups/includes/group_edit_invitation.html b/mozillians/jinja2/groups/includes/group_edit_invitation.html index cf6d428a2..0024dca42 100644 --- a/mozillians/jinja2/groups/includes/group_edit_invitation.html +++ b/mozillians/jinja2/groups/includes/group_edit_invitation.html @@ -30,10 +30,11 @@