616 lines
26 KiB
Python
616 lines
26 KiB
Python
"""Tests for the Zendesk"""
|
|
|
|
import json
|
|
from smtplib import SMTPException
|
|
|
|
import httpretty
|
|
import mock
|
|
from ddt import data, ddt, unpack
|
|
from django.contrib.auth.models import AnonymousUser
|
|
from django.http import Http404
|
|
from django.test import TestCase
|
|
from django.test.client import RequestFactory
|
|
from django.test.utils import override_settings
|
|
from zendesk import ZendeskError
|
|
|
|
from openedx.core.djangoapps.site_configuration.tests.factories import SiteFactory
|
|
from openedx.features.enterprise_support.tests.mixins.enterprise import EnterpriseServiceMockMixin
|
|
from student.tests.factories import CourseEnrollmentFactory, UserFactory
|
|
from student.tests.test_configuration_overrides import fake_get_value
|
|
from util import views
|
|
|
|
TEST_SUPPORT_EMAIL = "support@example.com"
|
|
TEST_ZENDESK_CUSTOM_FIELD_CONFIG = {
|
|
"course_id": 1234,
|
|
"enrollment_mode": 5678,
|
|
'enterprise_customer_name': 'enterprise_customer_name'
|
|
}
|
|
TEST_REQUEST_HEADERS = {
|
|
"HTTP_REFERER": "test_referer",
|
|
"HTTP_USER_AGENT": "test_user_agent",
|
|
"REMOTE_ADDR": "1.2.3.4",
|
|
"SERVER_NAME": "test_server",
|
|
}
|
|
|
|
|
|
def fake_support_backend_values(name, default=None): # pylint: disable=unused-argument
|
|
"""
|
|
Method for getting configuration override values for support email.
|
|
"""
|
|
config_dict = {
|
|
"CONTACT_FORM_SUBMISSION_BACKEND": "email",
|
|
"email_from_address": TEST_SUPPORT_EMAIL,
|
|
}
|
|
return config_dict[name]
|
|
|
|
|
|
@ddt
|
|
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": True})
|
|
@override_settings(
|
|
DEFAULT_FROM_EMAIL=TEST_SUPPORT_EMAIL,
|
|
ZENDESK_URL="dummy",
|
|
ZENDESK_USER="dummy",
|
|
ZENDESK_API_KEY="dummy",
|
|
ZENDESK_CUSTOM_FIELDS={},
|
|
)
|
|
@mock.patch("util.views._ZendeskApi", autospec=True)
|
|
class SubmitFeedbackTest(EnterpriseServiceMockMixin, TestCase):
|
|
"""
|
|
Class to test the submit_feedback function in views.
|
|
"""
|
|
def setUp(self):
|
|
"""Set up data for the test case"""
|
|
super(SubmitFeedbackTest, self).setUp()
|
|
self._request_factory = RequestFactory()
|
|
self._anon_user = AnonymousUser()
|
|
self._auth_user = UserFactory.create(
|
|
email="test@edx.org",
|
|
username="test",
|
|
profile__name="Test User"
|
|
)
|
|
self._anon_fields = {
|
|
"email": "test@edx.org",
|
|
"name": "Test User",
|
|
"subject": "a subject",
|
|
"details": "some details",
|
|
"issue_type": "test_issue"
|
|
}
|
|
# This does not contain issue_type nor course_id to ensure that they are optional
|
|
self._auth_fields = {"subject": "a subject", "details": "some details"}
|
|
|
|
# Create a service user, because the track selection page depends on it
|
|
UserFactory.create(
|
|
username='enterprise_worker',
|
|
email="enterprise_worker@example.com",
|
|
password="edx",
|
|
)
|
|
|
|
def _build_and_run_request(self, user, fields):
|
|
"""
|
|
Generate a request and invoke the view, returning the response.
|
|
|
|
The request will be a POST request from the given `user`, with the given
|
|
`fields` in the POST body.
|
|
"""
|
|
req = self._request_factory.post(
|
|
"/submit_feedback",
|
|
data=fields,
|
|
HTTP_REFERER=TEST_REQUEST_HEADERS["HTTP_REFERER"],
|
|
HTTP_USER_AGENT=TEST_REQUEST_HEADERS["HTTP_USER_AGENT"],
|
|
REMOTE_ADDR=TEST_REQUEST_HEADERS["REMOTE_ADDR"],
|
|
SERVER_NAME=TEST_REQUEST_HEADERS["SERVER_NAME"],
|
|
)
|
|
req.site = SiteFactory.create()
|
|
req.user = user
|
|
return views.submit_feedback(req)
|
|
|
|
def _assert_bad_request(self, response, field, zendesk_mock_class):
|
|
"""
|
|
Assert that the given `response` contains correct failure data.
|
|
|
|
It should have a 400 status code, and its content should be a JSON
|
|
object containing the specified `field` and an `error`.
|
|
"""
|
|
self.assertEqual(response.status_code, 400)
|
|
resp_json = json.loads(response.content)
|
|
self.assertIn("field", resp_json)
|
|
self.assertEqual(resp_json["field"], field)
|
|
self.assertIn("error", resp_json)
|
|
# There should be absolutely no interaction with Zendesk
|
|
self.assertFalse(zendesk_mock_class.return_value.mock_calls)
|
|
|
|
def _test_bad_request_omit_field(self, user, fields, omit_field, zendesk_mock_class):
|
|
"""
|
|
Invoke the view with a request missing a field and assert correctness.
|
|
|
|
The request will be a POST request from the given `user`, with POST
|
|
fields taken from `fields` minus the entry specified by `omit_field`.
|
|
The response should have a 400 (bad request) status code and specify
|
|
the invalid field and an error message, and the Zendesk API should not
|
|
have been invoked.
|
|
"""
|
|
filtered_fields = {k: v for (k, v) in fields.items() if k != omit_field}
|
|
resp = self._build_and_run_request(user, filtered_fields)
|
|
self._assert_bad_request(resp, omit_field, zendesk_mock_class)
|
|
|
|
def _test_bad_request_empty_field(self, user, fields, empty_field, zendesk_mock_class):
|
|
"""
|
|
Invoke the view with an empty field and assert correctness.
|
|
|
|
The request will be a POST request from the given `user`, with POST
|
|
fields taken from `fields`, replacing the entry specified by
|
|
`empty_field` with the empty string. The response should have a 400
|
|
(bad request) status code and specify the invalid field and an error
|
|
message, and the Zendesk API should not have been invoked.
|
|
"""
|
|
altered_fields = fields.copy()
|
|
altered_fields[empty_field] = ""
|
|
resp = self._build_and_run_request(user, altered_fields)
|
|
self._assert_bad_request(resp, empty_field, zendesk_mock_class)
|
|
|
|
def _test_success(self, user, fields):
|
|
"""
|
|
Generate a request, invoke the view, and assert success.
|
|
|
|
The request will be a POST request from the given `user`, with the given
|
|
`fields` in the POST body. The response should have a 200 (success)
|
|
status code.
|
|
"""
|
|
resp = self._build_and_run_request(user, fields)
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
def _build_zendesk_ticket(self, recipient, name, email, subject, details, tags, custom_fields=None):
|
|
"""
|
|
Build a Zendesk ticket that can be used in assertions to verify that the correct
|
|
data was submitted to create a Zendesk ticket.
|
|
"""
|
|
ticket = {
|
|
"ticket": {
|
|
"recipient": recipient,
|
|
"requester": {"name": name, "email": email},
|
|
"subject": subject,
|
|
"comment": {"body": details},
|
|
"tags": tags
|
|
}
|
|
}
|
|
|
|
if custom_fields is not None:
|
|
ticket["ticket"]["custom_fields"] = custom_fields
|
|
|
|
return ticket
|
|
|
|
def _build_zendesk_ticket_update(self, request_headers, username=None):
|
|
"""
|
|
Build a Zendesk ticket update that can be used in assertions to verify that the correct
|
|
data was submitted to update a Zendesk ticket.
|
|
"""
|
|
body = []
|
|
if username:
|
|
body.append("username: {}".format(username))
|
|
|
|
# FIXME the tests rely on the body string being built in this specific order, which doesn't seem
|
|
# reliable given that the view builds the string by iterating over a dictionary.
|
|
header_text_mapping = [
|
|
("Client IP", "REMOTE_ADDR"),
|
|
("Host", "SERVER_NAME"),
|
|
("Page", "HTTP_REFERER"),
|
|
("Browser", "HTTP_USER_AGENT")
|
|
]
|
|
|
|
for text, header in header_text_mapping:
|
|
body.append("{}: {}".format(text, request_headers[header]))
|
|
|
|
body = "Additional information:\n\n" + "\n".join(body)
|
|
return {"ticket": {"comment": {"public": False, "body": body}}}
|
|
|
|
def _assert_zendesk_called(self, zendesk_mock, ticket_id, ticket, ticket_update):
|
|
"""Assert that Zendesk was called with the correct ticket and ticket_update."""
|
|
expected_zendesk_calls = [mock.call.create_ticket(ticket), mock.call.update_ticket(ticket_id, ticket_update)]
|
|
self.assertEqual(zendesk_mock.mock_calls, expected_zendesk_calls)
|
|
|
|
def test_bad_request_anon_user_no_name(self, zendesk_mock_class):
|
|
"""Test a request from an anonymous user not specifying `name`."""
|
|
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "name", zendesk_mock_class)
|
|
|
|
def test_bad_request_anon_user_no_email(self, zendesk_mock_class):
|
|
"""Test a request from an anonymous user not specifying `email`."""
|
|
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "email", zendesk_mock_class)
|
|
|
|
def test_bad_request_anon_user_invalid_email(self, zendesk_mock_class):
|
|
"""Test a request from an anonymous user specifying an invalid `email`."""
|
|
fields = self._anon_fields.copy()
|
|
fields["email"] = "This is not a valid email address!"
|
|
resp = self._build_and_run_request(self._anon_user, fields)
|
|
self._assert_bad_request(resp, "email", zendesk_mock_class)
|
|
|
|
def test_bad_request_anon_user_no_subject(self, zendesk_mock_class):
|
|
"""Test a request from an anonymous user not specifying `subject`."""
|
|
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "subject", zendesk_mock_class)
|
|
|
|
def test_bad_request_anon_user_no_details(self, zendesk_mock_class):
|
|
"""Test a request from an anonymous user not specifying `details`."""
|
|
self._test_bad_request_omit_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._anon_user, self._anon_fields, "details", zendesk_mock_class)
|
|
|
|
def test_valid_request_anon_user(self, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an anonymous user.
|
|
|
|
The response should have a 200 (success) status code, and a ticket with
|
|
the given information should have been submitted via the Zendesk API.
|
|
"""
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._anon_user
|
|
fields = self._anon_fields
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=TEST_SUPPORT_EMAIL,
|
|
name=fields["name"],
|
|
email=fields["email"],
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=[fields["issue_type"], "LMS"]
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
|
|
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
@mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_get_value)
|
|
def test_valid_request_anon_user_configuration_override(self, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an anonymous user to a mocked out site with configuration override
|
|
|
|
The response should have a 200 (success) status code, and a ticket with
|
|
the given information should have been submitted via the Zendesk API with the additional
|
|
tag that will come from site configuration override.
|
|
"""
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._anon_user
|
|
fields = self._anon_fields
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=fake_get_value("email_from_address"),
|
|
name=fields["name"],
|
|
email=fields["email"],
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=[fields["issue_type"], "LMS", "site_name_{}".format(fake_get_value("SITE_NAME").replace(".", "_"))]
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
|
|
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
@data("course-v1:testOrg+testCourseNumber+testCourseRun", "", None)
|
|
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
|
|
def test_valid_request_anon_user_with_custom_fields(self, course_id, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an anonymous user when configured to use Zendesk Custom Fields.
|
|
|
|
The response should have a 200 (success) status code, and a ticket with
|
|
the given information should have been submitted via the Zendesk API. When course_id is
|
|
present, it should be sent to Zendesk via a custom field. When course_id is blank or missing,
|
|
the request should still be processed successfully.
|
|
"""
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._anon_user
|
|
|
|
fields = self._anon_fields.copy()
|
|
if course_id is not None:
|
|
fields["course_id"] = course_id
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
zendesk_tags = [fields["issue_type"], "LMS"]
|
|
zendesk_custom_fields = None
|
|
if course_id:
|
|
# FIXME the tests rely on the tags being in this specific order, which doesn't seem
|
|
# reliable given that the view builds the list by iterating over a dictionary.
|
|
zendesk_tags.insert(0, course_id)
|
|
zendesk_custom_fields = [
|
|
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
|
|
]
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=TEST_SUPPORT_EMAIL,
|
|
name=fields["name"],
|
|
email=fields["email"],
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=zendesk_tags,
|
|
custom_fields=zendesk_custom_fields
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS)
|
|
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
def test_bad_request_auth_user_no_subject(self, zendesk_mock_class):
|
|
"""Test a request from an authenticated user not specifying `subject`."""
|
|
self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "subject", zendesk_mock_class)
|
|
|
|
def test_bad_request_auth_user_no_details(self, zendesk_mock_class):
|
|
"""Test a request from an authenticated user not specifying `details`."""
|
|
self._test_bad_request_omit_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)
|
|
self._test_bad_request_empty_field(self._auth_user, self._auth_fields, "details", zendesk_mock_class)
|
|
|
|
def test_valid_request_auth_user(self, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an authenticated user.
|
|
|
|
The response should have a 200 (success) status code, and a ticket with
|
|
the given information should have been submitted via the Zendesk API.
|
|
"""
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._auth_user
|
|
fields = self._auth_fields
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=TEST_SUPPORT_EMAIL,
|
|
name=user.profile.name,
|
|
email=user.email,
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=["LMS"]
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
|
|
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
@data(
|
|
("course-v1:testOrg+testCourseNumber+testCourseRun", True),
|
|
("course-v1:testOrg+testCourseNumber+testCourseRun", False),
|
|
("", None),
|
|
(None, None)
|
|
)
|
|
@unpack
|
|
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
|
|
def test_valid_request_auth_user_with_custom_fields(self, course_id, enrolled, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an authenticated user when configured to use Zendesk Custom Fields.
|
|
|
|
The response should have a 200 (success) status code, and a ticket with
|
|
the given information should have been submitted via the Zendesk API. When course_id is
|
|
present, it should be sent to Zendesk via a custom field, along with the enrollment mode
|
|
if the user has an active enrollment for that course. When course_id is blank or missing,
|
|
the request should still be processed successfully.
|
|
"""
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._auth_user
|
|
|
|
fields = self._auth_fields.copy()
|
|
if course_id is not None:
|
|
fields["course_id"] = course_id
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
zendesk_tags = ["LMS"]
|
|
zendesk_custom_fields = None
|
|
if course_id:
|
|
# FIXME the tests rely on the tags being in this specific order, which doesn't seem
|
|
# reliable given that the view builds the list by iterating over a dictionary.
|
|
zendesk_tags.insert(0, course_id)
|
|
zendesk_custom_fields = [
|
|
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id}
|
|
]
|
|
if enrolled is not None:
|
|
enrollment = CourseEnrollmentFactory.create(
|
|
user=user,
|
|
course_id=course_id,
|
|
is_active=enrolled
|
|
)
|
|
if enrollment.is_active:
|
|
zendesk_custom_fields.append(
|
|
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
|
|
)
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=TEST_SUPPORT_EMAIL,
|
|
name=user.profile.name,
|
|
email=user.email,
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=zendesk_tags,
|
|
custom_fields=zendesk_custom_fields
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
|
|
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
@httpretty.activate
|
|
@data(
|
|
("course-v1:testOrg+testCourseNumber+testCourseRun", True),
|
|
("course-v1:testOrg+testCourseNumber+testCourseRun", False),
|
|
)
|
|
@unpack
|
|
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
|
|
@mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
|
|
def test_valid_request_auth_user_with_enterprise_info(self, course_id, enrolled, zendesk_mock_class):
|
|
"""
|
|
Test a valid request from an authenticated user with enterprise tags.
|
|
"""
|
|
self.mock_enterprise_learner_api()
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
user = self._auth_user
|
|
|
|
fields = self._auth_fields.copy()
|
|
if course_id is not None:
|
|
fields["course_id"] = course_id
|
|
|
|
ticket_id = 42
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
zendesk_tags = ["enterprise_learner", "LMS"]
|
|
zendesk_custom_fields = []
|
|
|
|
if course_id:
|
|
zendesk_tags.insert(0, course_id)
|
|
zendesk_custom_fields.append({"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["course_id"], "value": course_id})
|
|
if enrolled is not None:
|
|
enrollment = CourseEnrollmentFactory.create(
|
|
user=user,
|
|
course_id=course_id,
|
|
is_active=enrolled
|
|
)
|
|
if enrollment.is_active:
|
|
zendesk_custom_fields.append(
|
|
{"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enrollment_mode"], "value": enrollment.mode}
|
|
)
|
|
|
|
zendesk_custom_fields.append(
|
|
{
|
|
"id": TEST_ZENDESK_CUSTOM_FIELD_CONFIG["enterprise_customer_name"],
|
|
"value": 'TestShib'
|
|
}
|
|
)
|
|
|
|
ticket = self._build_zendesk_ticket(
|
|
recipient=TEST_SUPPORT_EMAIL,
|
|
name=user.profile.name,
|
|
email=user.email,
|
|
subject=fields["subject"],
|
|
details=fields["details"],
|
|
tags=zendesk_tags,
|
|
custom_fields=zendesk_custom_fields
|
|
)
|
|
|
|
ticket_update = self._build_zendesk_ticket_update(TEST_REQUEST_HEADERS, user.username)
|
|
self._test_success(user, fields)
|
|
self._assert_zendesk_called(zendesk_mock_instance, ticket_id, ticket, ticket_update)
|
|
|
|
@httpretty.activate
|
|
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
|
|
@mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
|
|
def test_request_with_anonymous_user_without_enterprise_info(self, zendesk_mock_class):
|
|
"""
|
|
Test tags related to enterprise should not be there in case an unauthenticated user.
|
|
"""
|
|
ticket_id = 42
|
|
self.mock_enterprise_learner_api()
|
|
user = self._anon_user
|
|
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
resp = self._build_and_run_request(user, self._anon_fields)
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
@httpretty.activate
|
|
@override_settings(ZENDESK_CUSTOM_FIELDS=TEST_ZENDESK_CUSTOM_FIELD_CONFIG)
|
|
@mock.patch.dict("django.conf.settings.FEATURES", dict(ENABLE_ENTERPRISE_INTEGRATION=True))
|
|
def test_tags_in_request_with_auth_user_with_enterprise_info(self, zendesk_mock_class):
|
|
"""
|
|
Test tags related to enterprise should be there in case the request is generated by an authenticated user.
|
|
"""
|
|
ticket_id = 42
|
|
self.mock_enterprise_learner_api()
|
|
user = self._auth_user
|
|
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
zendesk_mock_instance.create_ticket.return_value = ticket_id
|
|
|
|
resp = self._build_and_run_request(user, self._auth_fields)
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
def test_get_request(self, zendesk_mock_class):
|
|
"""Test that a GET results in a 405 even with all required fields"""
|
|
req = self._request_factory.get("/submit_feedback", data=self._anon_fields)
|
|
req.user = self._anon_user
|
|
resp = views.submit_feedback(req)
|
|
self.assertEqual(resp.status_code, 405)
|
|
self.assertIn("Allow", resp)
|
|
self.assertEqual(resp["Allow"], "POST")
|
|
# There should be absolutely no interaction with Zendesk
|
|
self.assertFalse(zendesk_mock_class.mock_calls)
|
|
|
|
def test_zendesk_error_on_create(self, zendesk_mock_class):
|
|
"""
|
|
Test Zendesk returning an error on ticket creation.
|
|
|
|
We should return a 500 error with no body
|
|
"""
|
|
err = ZendeskError(msg="", error_code=404)
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
zendesk_mock_instance.create_ticket.side_effect = err
|
|
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
self.assertEqual(resp.status_code, 500)
|
|
self.assertFalse(resp.content)
|
|
|
|
def test_zendesk_error_on_update(self, zendesk_mock_class):
|
|
"""
|
|
Test for Zendesk returning an error on ticket update.
|
|
|
|
If Zendesk returns any error on ticket update, we return a 200 to the
|
|
browser because the update contains additional information that is not
|
|
necessary for the user to have submitted their feedback.
|
|
"""
|
|
err = ZendeskError(msg="", error_code=500)
|
|
zendesk_mock_instance = zendesk_mock_class.return_value
|
|
zendesk_mock_instance.update_ticket.side_effect = err
|
|
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
@mock.patch.dict("django.conf.settings.FEATURES", {"ENABLE_FEEDBACK_SUBMISSION": False})
|
|
def test_not_enabled(self, zendesk_mock_class):
|
|
"""
|
|
Test for Zendesk submission not enabled in `settings`.
|
|
|
|
We should raise Http404.
|
|
"""
|
|
with self.assertRaises(Http404):
|
|
self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
|
|
def test_zendesk_not_configured(self, zendesk_mock_class):
|
|
"""
|
|
Test for Zendesk not fully configured in `settings`.
|
|
|
|
For each required configuration parameter, test that setting it to
|
|
`None` causes an otherwise valid request to return a 500 error.
|
|
"""
|
|
def test_case(missing_config):
|
|
with mock.patch(missing_config, None):
|
|
with self.assertRaises(Exception):
|
|
self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
|
|
test_case("django.conf.settings.ZENDESK_URL")
|
|
test_case("django.conf.settings.ZENDESK_USER")
|
|
test_case("django.conf.settings.ZENDESK_API_KEY")
|
|
|
|
@mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_support_backend_values)
|
|
def test_valid_request_over_email(self, zendesk_mock_class): # pylint: disable=unused-argument
|
|
with mock.patch("util.views.send_mail") as patched_send_email:
|
|
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
self.assertEqual(patched_send_email.call_count, 1)
|
|
self.assertIn(self._anon_fields["email"], str(patched_send_email.call_args))
|
|
self.assertEqual(resp.status_code, 200)
|
|
|
|
@mock.patch("openedx.core.djangoapps.site_configuration.helpers.get_value", fake_support_backend_values)
|
|
def test_exception_request_over_email(self, zendesk_mock_class): # pylint: disable=unused-argument
|
|
with mock.patch("util.views.send_mail", side_effect=SMTPException) as patched_send_email:
|
|
resp = self._build_and_run_request(self._anon_user, self._anon_fields)
|
|
self.assertEqual(patched_send_email.call_count, 1)
|
|
self.assertIn(self._anon_fields["email"], str(patched_send_email.call_args))
|
|
self.assertEqual(resp.status_code, 500)
|