Commit 02c46b42 by Waheed Ahmed

Publisher cleanup.

ECOM-7314
parent 78289321
...@@ -345,10 +345,6 @@ class Seat(TimeStampedModel, ChangedByMixin): ...@@ -345,10 +345,6 @@ class Seat(TimeStampedModel, ChangedByMixin):
return '{course}: {type}'.format(course=self.course_run.course.title, type=self.type) return '{course}: {type}'.format(course=self.course_run.course.title, type=self.type)
@property @property
def post_back_url(self):
return reverse('publisher:publisher_seats_edit', kwargs={'pk': self.id})
@property
def is_valid_seat(self): def is_valid_seat(self):
return self.type == self.AUDIT or self.type in [self.VERIFIED, self.PROFESSIONAL] and self.price > 0 return self.type == self.AUDIT or self.type in [self.VERIFIED, self.PROFESSIONAL] and self.price > 0
......
...@@ -320,12 +320,6 @@ class SeatTests(TestCase): ...@@ -320,12 +320,6 @@ class SeatTests(TestCase):
) )
) )
def test_post_back_url(self):
self.assertEqual(
self.seat.post_back_url,
reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id})
)
class UserAttributeTests(TestCase): class UserAttributeTests(TestCase):
""" Tests for the publisher `UserAttribute` model. """ """ Tests for the publisher `UserAttribute` model. """
......
...@@ -493,175 +493,6 @@ class CreateCourseRunViewTests(TestCase): ...@@ -493,175 +493,6 @@ class CreateCourseRunViewTests(TestCase):
self.assertEqual(new_seat.course_run.course.course_team_admin, new_user) self.assertEqual(new_seat.course_run.course.course_team_admin, new_user)
class SeatsCreateUpdateViewTests(TestCase):
""" Tests for the publisher `CreateSeatView` and `UpdateSeatView`. """
def setUp(self):
super(SeatsCreateUpdateViewTests, self).setUp()
self.seat = factories.SeatFactory(type=Seat.PROFESSIONAL, credit_hours=0)
self.organization_extension = factories.OrganizationExtensionFactory()
self.seat.course_run.course.organizations.add(self.organization_extension.organization)
self.seat_dict = model_to_dict(self.seat)
self.seat_dict.pop('upgrade_deadline')
self.user = UserFactory()
self.site = Site.objects.get(pk=settings.SITE_ID)
self.client.login(username=self.user.username, password=USER_PASSWORD)
self.seat_edit_url = reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id})
def test_seat_form_without_login(self):
""" Verify that user can't access new seat form page when not logged in. """
self.client.logout()
response = self.client.get(reverse('publisher:publisher_seats_new'))
self.assertRedirects(
response,
expected_url='{url}?next={next}'.format(
url=reverse('login'),
next=reverse('publisher:publisher_seats_new')
),
status_code=302,
target_status_code=302
)
def test_seat_view_page(self):
""" Verify that we can open new seat page. """
response = self.client.get(reverse('publisher:publisher_seats_new'))
# Assert that we can load seat page.
self.assertEqual(response.status_code, 200)
def test_create_seat(self):
""" Verify that we can create a new seat. """
seat_price = 670.00
self.seat_dict['price'] = seat_price
response = self.client.post(reverse('publisher:publisher_seats_new'), self.seat_dict)
seat = Seat.objects.get(course_run=self.seat.course_run, price=seat_price)
self.user.groups.add(self.organization_extension.group)
# edit permission require on seat edit page only.
assign_perm(
OrganizationExtension.EDIT_COURSE_RUN, self.organization_extension.group, self.organization_extension
)
self.assertRedirects(
response,
expected_url=reverse('publisher:publisher_seats_edit', kwargs={'pk': seat.id}),
status_code=302,
target_status_code=200
)
self.assertEqual(seat.price, seat_price)
def test_update_seat_with_admin(self):
""" Verify that publisher admin can update an existing seat. """
self.user.groups.add(Group.objects.get(name=ADMIN_GROUP_NAME))
self.assertEqual(self.seat.type, Seat.PROFESSIONAL)
updated_seat_price = 470.00
self.seat_dict['price'] = updated_seat_price
self.seat_dict['type'] = Seat.VERIFIED
self.assertNotEqual(self.seat.price, updated_seat_price)
self.assertNotEqual(self.seat.changed_by, self.user)
response = self.client.post(
reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
self.seat_dict
)
self.assertRedirects(
response,
expected_url=self.seat_edit_url,
status_code=302,
target_status_code=200
)
seat = Seat.objects.get(id=self.seat.id)
# Assert that seat is updated.
self.assertEqual(seat.price, updated_seat_price)
self.assertEqual(seat.changed_by, self.user)
self.assertEqual(seat.type, Seat.VERIFIED)
self.seat_dict['type'] = Seat.HONOR
response = self.client.post(self.seat_edit_url, self.seat_dict)
seat = Seat.objects.get(id=self.seat.id)
# Assert that we can change seat type.
self.assertEqual(seat.type, Seat.HONOR)
self.assertRedirects(
response,
expected_url=self.seat_edit_url,
status_code=302,
target_status_code=200
)
# add new and check the comment on edit page.
comment = CommentFactory(content_object=self.seat, user=self.user, site=self.site)
response = self.client.get(self.seat_edit_url)
self.assertContains(response, 'Comment:')
self.assertContains(response, comment.comment)
def test_edit_seat_page_with_non_staff(self):
""" Verify that non internal user can't access seat edit page without permission. """
non_internal_user, __ = create_non_staff_user_and_login(self)
response = self.client.get(reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}))
self.assertEqual(response.status_code, 403)
non_internal_user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME))
response = self.client.get(reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}))
self.assertEqual(response.status_code, 200)
def test_update_seat_with_internal_user(self):
""" Tests update seat for internal user. """
non_internal_user, __ = create_non_staff_user_and_login(self)
self.assertEqual(self.seat.type, Seat.PROFESSIONAL)
updated_seat_price = 470.00
self.seat_dict['price'] = updated_seat_price
self.seat_dict['type'] = Seat.VERIFIED
self.assertNotEqual(self.seat.price, updated_seat_price)
response = self.client.post(
reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
self.seat_dict
)
# verify that non internal user can't update course seat without permission
self.assertEqual(response.status_code, 403)
non_internal_user.groups.add(Group.objects.get(name=INTERNAL_USER_GROUP_NAME))
response = self.client.post(
reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
self.seat_dict
)
self.assertRedirects(
response,
expected_url=reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
status_code=302,
target_status_code=200
)
seat = Seat.objects.get(id=self.seat.id)
# Assert that seat is updated.
self.assertEqual(seat.price, updated_seat_price)
self.assertEqual(seat.type, Seat.VERIFIED)
self.seat_dict['type'] = Seat.HONOR
response = self.client.post(
reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
self.seat_dict
)
seat = Seat.objects.get(id=self.seat.id)
# Assert that we can change seat type.
self.assertEqual(seat.type, Seat.HONOR)
self.assertRedirects(
response,
expected_url=reverse('publisher:publisher_seats_edit', kwargs={'pk': self.seat.id}),
status_code=302,
target_status_code=200
)
@ddt.ddt @ddt.ddt
class CourseRunDetailTests(TestCase): class CourseRunDetailTests(TestCase):
""" Tests for the course-run detail view. """ """ Tests for the course-run detail view. """
......
...@@ -19,8 +19,6 @@ urlpatterns = [ ...@@ -19,8 +19,6 @@ urlpatterns = [
), ),
url(r'^course_runs/(?P<pk>\d+)/$', views.CourseRunDetailView.as_view(), name='publisher_course_run_detail'), url(r'^course_runs/(?P<pk>\d+)/$', views.CourseRunDetailView.as_view(), name='publisher_course_run_detail'),
url(r'^course_runs/(?P<pk>\d+)/edit/$', views.CourseRunEditView.as_view(), name='publisher_course_runs_edit'), url(r'^course_runs/(?P<pk>\d+)/edit/$', views.CourseRunEditView.as_view(), name='publisher_course_runs_edit'),
url(r'^seats/new/$', views.CreateSeatView.as_view(), name='publisher_seats_new'),
url(r'^seats/(?P<pk>\d+)/edit/$', views.UpdateSeatView.as_view(), name='publisher_seats_edit'),
url( url(
r'^user/toggle/email_settings/$', r'^user/toggle/email_settings/$',
views.ToggleEmailNotification.as_view(), views.ToggleEmailNotification.as_view(),
......
...@@ -20,9 +20,9 @@ from guardian.shortcuts import get_objects_for_user ...@@ -20,9 +20,9 @@ from guardian.shortcuts import get_objects_for_user
from course_discovery.apps.core.models import User from course_discovery.apps.core.models import User
from course_discovery.apps.publisher import emails, mixins from course_discovery.apps.publisher import emails, mixins
from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole from course_discovery.apps.publisher.choices import CourseRunStateChoices, CourseStateChoices, PublisherUserRole
from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, CustomSeatForm, SeatForm from course_discovery.apps.publisher.forms import CustomCourseForm, CustomCourseRunForm, CustomSeatForm
from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole, from course_discovery.apps.publisher.models import (Course, CourseRun, CourseRunState, CourseState, CourseUserRole,
OrganizationExtension, Seat, UserAttributes) OrganizationExtension, UserAttributes)
from course_discovery.apps.publisher.utils import (get_internal_users, is_internal_user, is_project_coordinator_user, from course_discovery.apps.publisher.utils import (get_internal_users, is_internal_user, is_project_coordinator_user,
is_publisher_admin, make_bread_crumbs) is_publisher_admin, make_bread_crumbs)
from course_discovery.apps.publisher.wrappers import CourseRunWrapper from course_discovery.apps.publisher.wrappers import CourseRunWrapper
...@@ -30,8 +30,6 @@ from course_discovery.apps.publisher.wrappers import CourseRunWrapper ...@@ -30,8 +30,6 @@ from course_discovery.apps.publisher.wrappers import CourseRunWrapper
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
SEATS_HIDDEN_FIELDS = ['price', 'currency', 'upgrade_deadline', 'credit_provider', 'credit_hours']
ROLE_WIDGET_HEADINGS = { ROLE_WIDGET_HEADINGS = {
PublisherUserRole.PartnerManager: _('PARTNER MANAGER'), PublisherUserRole.PartnerManager: _('PARTNER MANAGER'),
PublisherUserRole.ProjectCoordinator: _('PROJECT COORDINATOR'), PublisherUserRole.ProjectCoordinator: _('PROJECT COORDINATOR'),
...@@ -614,40 +612,6 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix ...@@ -614,40 +612,6 @@ class CourseRunEditView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMix
return render(request, self.template_name, context, status=400) return render(request, self.template_name, context, status=400)
class CreateSeatView(mixins.LoginRequiredMixin, mixins.FormValidMixin, CreateView):
""" Create Seat View."""
model = Seat
form_class = SeatForm
template_name = 'publisher/seat_form.html'
success_url = 'publisher:publisher_seats_edit'
def get_context_data(self, **kwargs):
context = super(CreateSeatView, self).get_context_data(**kwargs)
context['hidden_fields'] = SEATS_HIDDEN_FIELDS
return context
def get_success_url(self):
return reverse(self.success_url, kwargs={'pk': self.object.id})
class UpdateSeatView(mixins.LoginRequiredMixin, mixins.PublisherPermissionMixin, mixins.FormValidMixin, UpdateView):
""" Update Seat View."""
model = Seat
form_class = SeatForm
permission = OrganizationExtension.EDIT_COURSE_RUN
template_name = 'publisher/seat_form.html'
success_url = 'publisher:publisher_seats_edit'
def get_context_data(self, **kwargs):
context = super(UpdateSeatView, self).get_context_data(**kwargs)
context['hidden_fields'] = SEATS_HIDDEN_FIELDS
context['comment_object'] = self.object
return context
def get_success_url(self):
return reverse(self.success_url, kwargs={'pk': self.object.id})
class ToggleEmailNotification(mixins.LoginRequiredMixin, View): class ToggleEmailNotification(mixins.LoginRequiredMixin, View):
""" Toggle User Email Notification Settings.""" """ Toggle User Email Notification Settings."""
......
from django.conf import settings
from django.contrib.sites.models import Site
from django.core import mail
from django.core.urlresolvers import reverse
from django.forms import model_to_dict
from django.test import TestCase
from course_discovery.apps.core.tests.factories import USER_PASSWORD, UserFactory
from course_discovery.apps.course_metadata.tests import toggle_switch
from course_discovery.apps.publisher.choices import PublisherUserRole
from course_discovery.apps.publisher.models import Seat
from course_discovery.apps.publisher.tests import factories
from course_discovery.apps.publisher_comments.tests.factories import CommentFactory
# pylint: disable=no-member
class CommentsTests(TestCase):
""" Tests for the Comment functionality on `Courser`, `CourseRun` And `Seat` edit pages. """
def setUp(self):
super(CommentsTests, self).setUp()
self.user = UserFactory(is_staff=True, is_superuser=True)
self.organization_extension = factories.OrganizationExtensionFactory()
self.client.login(username=self.user.username, password=USER_PASSWORD)
self.site = Site.objects.get(pk=settings.SITE_ID)
self.course_edit_page = 'publisher:publisher_courses_edit'
self.course_run_edit_page = 'publisher:publisher_course_runs_edit'
self.seat_edit_page = 'publisher:publisher_seats_edit'
self.edit_comment_page = 'publisher_comments:comment_edit'
self.seat = factories.SeatFactory(type=Seat.PROFESSIONAL, credit_hours=0)
self.course_run = self.seat.course_run
self.course = self.course_run.course
self.course.organizations.add(self.organization_extension.organization)
# assign the role against a course
factories.CourseUserRoleFactory(
course=self.course, role=PublisherUserRole.MarketingReviewer, user=self.user
)
toggle_switch('enable_publisher_email_notifications', True)
def test_comment_edit_with_seat(self):
""" Verify that only comments attached with specific seat appears on edited page. """
comments = self._generate_comments_for_all_content_types()
response = self.client.get(reverse(self.seat_edit_page, kwargs={'pk': self.seat.id}))
self.assertContains(response, comments.get(self.seat).comment)
self.assertNotContains(response, comments.get(self.course).comment)
self.assertNotContains(response, comments.get(self.course_run).comment)
def test_edit_course_comment(self):
""" Verify that course comment can be edited. """
self._edit_comment_page(
self.course, reverse(self.course_edit_page, kwargs={'pk': self.course.id})
)
def test_edit_seat_comment(self):
""" Verify that seat comment can be edited. """
self._edit_comment_page(
self.seat, reverse(self.seat_edit_page, kwargs={'pk': self.seat.id})
)
def test_mail_outbox_count(self):
""" Verify that separate emails send for adding and editing the comment . """
self._edit_comment_page(
self.course, reverse(self.course_edit_page, kwargs={'pk': self.course.id})
)
# mail has 2 emails one due to newly added comment and other is due to editing.
self.assertEqual(len(mail.outbox), 2)
def test_edit_comment_of_other_user(self):
""" Verify that comment can be edited by the comment author only. """
comment = self._generate_comment(content_object=self.course, user=self.user)
comment_url = reverse(self.edit_comment_page, kwargs={'pk': comment.id})
response = self.client.get(comment_url)
self.assertEqual(response.status_code, 200)
# logout and login with other user.
self.client.logout()
user = UserFactory(is_staff=True, is_superuser=True)
self.client.login(username=user.username, password=USER_PASSWORD)
response = self.client.get(reverse(self.edit_comment_page, kwargs={'pk': comment.id}))
self.assertEqual(response.status_code, 404)
def _edit_comment_page(self, content_object, expected_url):
""" DRY method for posting the edited comment."""
comment = self._generate_comment(content_object=content_object, user=self.user)
comment_url = reverse(self.edit_comment_page, kwargs={'pk': comment.id})
response = self.client.get(comment_url)
self._assert_edit_comment(response, comment)
new_comment = "This is updated comment"
content_object_dict = model_to_dict(comment)
content_object_dict['comment'] = new_comment
response = self.client.post(comment_url, content_object_dict)
self.assertRedirects(
response,
expected_url=expected_url,
status_code=302, target_status_code=200
)
response = self.client.get(comment_url)
self.assertContains(response, new_comment)
def _generate_comment(self, content_object, user):
""" DRY method to generate the comment."""
return CommentFactory(content_object=content_object, user=user, site=self.site)
def _assert_edit_comment(self, response, comment):
""" DRY method for asserting the edited comment page."""
self.assertContains(response, 'Edit Comment')
self.assertContains(response, 'Submit date')
self.assertContains(response, comment.comment)
self.assertContains(response, comment.submit_date)
# assert the customize fields exists in comment object
self.assertTrue(hasattr(comment, 'modified'))
def _generate_comments_for_all_content_types(self):
""" DRY method generate the comments for all available content types"""
data = {}
for content in [self.course, self.course_run, self.seat]:
data[content] = self._generate_comment(content_object=content, user=self.user)
return data
def _add_assert_multiple_comments(self, content_object, page_path):
""" DRY method to add comments on edit page for specific object. """
response = self.client.get(reverse(page_path, kwargs={'pk': content_object.id}))
self.assertContains(response, 'Total Comments 0')
comments = []
for __ in range(1, 2):
comments.append(self._generate_comment(content_object=content_object, user=self.user))
# assert emails send
self.assertEqual(len(mail.outbox), 1)
response = self.client.get(reverse(page_path, kwargs={'pk': content_object.id}))
for comment in comments:
self.assertContains(response, comment.comment)
self.assertContains(response, 'Total Comments 1')
...@@ -3,9 +3,7 @@ URLs for the course publisher comments views. ...@@ -3,9 +3,7 @@ URLs for the course publisher comments views.
""" """
from django.conf.urls import include, url from django.conf.urls import include, url
from course_discovery.apps.publisher_comments import views
urlpatterns = [ urlpatterns = [
url(r'^api/', include('course_discovery.apps.publisher_comments.api.urls', namespace='api')), url(r'^api/', include('course_discovery.apps.publisher_comments.api.urls', namespace='api')),
url(r'^(?P<pk>\d+)/edit/$', views.UpdateCommentView.as_view(), name='comment_edit'),
] ]
"""
Customize custom views.
"""
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponseRedirect
from django.views.generic.edit import UpdateView
from course_discovery.apps.publisher_comments.forms import CommentEditForm
from course_discovery.apps.publisher_comments.models import Comments
# pylint: disable=attribute-defined-outside-init
class UpdateCommentView(UpdateView):
""" Update Comment View."""
model = Comments
form_class = CommentEditForm
template_name = 'comments/edit_comment.html'
success_url = 'publisher:publisher_seats_edit'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
if request.user != self.object.user:
raise Http404
return super(UpdateCommentView, self).get(request, *args, **kwargs)
def form_valid(self, form):
self.object = form.save()
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
url = reverse('publisher:publisher_seats_edit', kwargs={'pk': self.object.object_pk})
if self.object.content_type.model == 'seat':
url = url
elif self.object.content_type.model == 'course':
url = reverse('publisher:publisher_courses_edit', kwargs={'pk': self.object.object_pk})
elif self.object.content_type.model == 'courserun':
url = reverse('publisher:publisher_course_runs_edit', kwargs={'pk': self.object.object_pk})
return url
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment