def test_canvas_section_error_sends_support_email(
            self, send_failure_msg_to_support,
            course_generation_job__objects__filter,
            course_generation_job__objects__create,
            update_course_generation_workflow_state, get_course_data,
            create_course_section, create_new_course,
            get_default_template_for_school):
        """
        Test to assert that a support email is sent when there is a
        CanvasAPIError resulting in CanvasSectionCreateError.
        """
        job = Mock(spec=CanvasCourseGenerationJob())
        course_generation_job__objects__create.return_value = job
        query_set = Mock(get=Mock(return_value=job))
        course_generation_job__objects__filter.return_value = query_set
        create_course_section.side_effect = CanvasAPIError(status_code=400)

        exception_data = CanvasSectionCreateError(self.sis_course_id)
        get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
            self.school_id)
        with self.assertRaises(CanvasSectionCreateError):
            controller.create_canvas_course(self.sis_course_id,
                                            self.sis_user_id)

        send_failure_msg_to_support.assert_called_with(
            self.sis_course_id, self.sis_user_id, exception_data.display_text)
 def test_404_exception_n_create_new_course_method_invokes_update_workflow_state_with_bulk_job_id(
         self, update_mock, course_generation_job__objects__filter,
         get_course_data, create_course_section, create_new_course,
         get_default_template_for_school):
     """
     Test to assert that a CanvasCourseCreateError is raised when the 
     create_new_course SDK call throws a CanvasAPIError,
     and update_content_migration_workflow_state is invoked to update the
     status to STATUS_SETUP_FAILED
     """
     query_set = Mock(get=Mock(return_value=Mock(
         spec=CanvasCourseGenerationJob)))
     course_generation_job__objects__filter.return_value = query_set
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     create_new_course.side_effect = CanvasAPIError(status_code=404)
     with self.assertRaises(CanvasCourseCreateError):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id,
                                         bulk_job=self.bulk_job)
     update_mock.assert_called_with(
         self.sis_course_id,
         CanvasCourseGenerationJob.STATUS_SETUP_FAILED,
         course_job_id=None,
         bulk_job_id=self.bulk_job_id)
    def test_instance_str_for_canvas_api_error(self):
        """ Test string representation of CanvasAPIError with custom attributes """
        status = 404
        error_msg = 'This is a test message'
        error_json = {'Some error json'}

        api_error = CanvasAPIError(status_code=status, msg=error_msg, error_json=error_json)
        self.assertEqual('%d: %s' % (status, error_msg), str(api_error))
Beispiel #4
0
 def test_add_to_section_logs_exception_on_failure_status_code(
         self, log_replacement, add_to_section_replacement):
     """ Assert that logger is logging an exception when return from backend
     is status code 4XX """
     request = self.add_to_section_stub()
     add_to_section_replacement.side_effect = CanvasAPIError()
     response = add_to_section(request)
     assert log_replacement.called
     self.assertEqual(len(json.loads(response.content)['failed']), 2)
 def test_exception_when_create_new_course_method_raises_api_400(
         self, get_course_data, create_course_section, create_new_course,
         get_default_template_for_school):
     """
     Test to assert that a CanvasCourseAlreadyExistsError is raised when the create_new_course method
     throws a CanvasAPIError
     """
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     create_new_course.side_effect = CanvasAPIError(status_code=400)
     with self.assertRaises(CanvasCourseAlreadyExistsError):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id)
 def test_exception_when_create_new_course_method_raises_api_404(
         self, send_failure_msg_to_support, get_course_data,
         create_course_section, create_new_course,
         get_default_template_for_school):
     """
     Test to assert that a RenderableException is raised when the create_new_course SDK call
     throws an CanvasAPIError
     """
     create_new_course.side_effect = CanvasAPIError(status_code=404)
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     with self.assertRaises(CanvasCourseCreateError):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id)
    def test_canvas_course_already_exists_error_doesnt_set_support_notified(
            self, send_failure_msg_to_support, get_course_data,
            create_course_section, create_new_course,
            get_default_template_for_school):
        """
        Test to assert that support_notified is NOT set on CanvasCourseAlreadyExistsError
        """
        create_new_course.side_effect = CanvasAPIError(status_code=400)
        get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
            self.school_id)
        with self.assertRaises(CanvasCourseAlreadyExistsError) as cm:
            controller.create_canvas_course(self.sis_course_id,
                                            self.sis_user_id)

        self.assertTrue('support_notified' not in cm.exception)
    def test_canvas_course_exists_error_doesnt_send_support_email(
            self, send_failure_msg_to_support, get_course_data,
            create_course_section, create_new_course,
            get_default_template_for_school):
        """
        Test to assert that a support email is NOT sent when canvas course already exists
        (there is a CanvasCourseAlreadyExistsError)
        
        """
        create_new_course.side_effect = CanvasAPIError(status_code=400)
        get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
            self.school_id)
        with self.assertRaises(CanvasCourseAlreadyExistsError):
            controller.create_canvas_course(self.sis_course_id,
                                            self.sis_user_id)

        self.assertFalse(send_failure_msg_to_support.called)
Beispiel #9
0
 def _get_course(context, course_id):
     url = "{}/v1/courses/{}?include[]=syllabus_body&include[]=term".format(
         context.base_api_url, course_id)
     response = requests.get(
         url,
         headers={"Authorization": "Bearer {}".format(context.auth_token)})
     if response.status_code != 200:
         if response.status_code == 401 and 'WWW-Authenticate' in response.headers:
             raise InvalidOAuthTokenError(
                 "OAuth Token used to make request to %s is invalid" %
                 response.url)
         raise CanvasAPIError(
             status_code=response.status_code,
             msg=unicode(response.json()),
             error_json=response.json(),
         )
     return response.json()
    def test_canvas_course_create_error_sets_support_notified(
            self, send_failure_msg_to_support, get_course_data,
            create_course_section, create_new_course,
            get_default_template_for_school):
        """
        Test to assert that support_notified is set on CanvasCourseCreateError
        """
        create_new_course.side_effect = CanvasAPIError(status_code=404)
        exception_data = CanvasCourseCreateError(
            msg_details=self.sis_course_id)
        get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
            self.school_id)
        with self.assertRaises(CanvasCourseCreateError):
            controller.create_canvas_course(self.sis_course_id,
                                            self.sis_user_id)

        self.assertTrue(exception_data.support_notified)
 def test_when_create_course_section_method_raises_api_error(
         self, course_generation_job__objects__create,
         update_course_generation_workflow_state,
         send_failure_msg_to_support, get_course_data,
         create_course_section, create_new_course,
         get_default_template_for_school):
     """
     Test to assert that a RenderableException is raised when the create_course_section SDK call
     throws an CanvasAPIError
     """
     job = Mock(spec=CanvasCourseGenerationJob())
     course_generation_job__objects__create.return_value = job
     create_course_section.side_effect = CanvasAPIError(status_code=400)
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     with self.assertRaises(RenderableException):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id, None)
 def test_canvas_course_create_error_doesnt_send_support_email_for_bulk_created_course(
         self, send_failure_msg_to_support,
         course_generation_job__objects__filter,
         update_course_generation_workflow_state, get_course_data,
         create_course_section, create_new_course,
         get_default_template_for_school):
     """
     Test to assert that a for a course that is created as part of a bulk 
     job, the support email is not sent when there is an CanvasAPIError
     resulting in CanvasCourseCreateError.
     """
     query_set = Mock(get=Mock(return_value=Mock(
         spec=CanvasCourseGenerationJob)))
     course_generation_job__objects__filter.return_value = query_set
     create_new_course.side_effect = CanvasAPIError(status_code=404)
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     with self.assertRaises(CanvasCourseCreateError):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id, self.bulk_job)
     self.assertFalse(send_failure_msg_to_support.called)
 def test_404_exception_n_create_new_course_method_invokes_update_workflow_state(
         self, update_mock, get_course_data, create_course_section,
         create_new_course, get_default_template_for_school):
     """
     A RenderableException should be raised and and
     update_content_generation_workflow_state() is invoked
     when the create_new_course SDK call throws an CanvasAPIError
     """
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     create_new_course.side_effect = CanvasAPIError(status_code=404)
     get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
         self.school_id)
     with self.assertRaises(CanvasCourseCreateError):
         controller.create_canvas_course(self.sis_course_id,
                                         self.sis_user_id)
     update_mock.assert_called_with(
         self.sis_course_id,
         CanvasCourseGenerationJob.STATUS_SETUP_FAILED,
         course_job_id=ANY,
         bulk_job_id=None)
    def test_canvas_course_create_error_sends_support_email(
            self, send_failure_msg_to_support, get_course_data,
            create_course_section, create_new_course,
            get_default_template_for_school):
        """
        Test to assert that a support email is sent  when  there is an CanvasAPIError resulting in CanvasCourseCreateError
        and that the correct error message from the exception is sent as a param  to the mail helper method
        """
        create_new_course.side_effect = CanvasAPIError(status_code=404)
        exception_data = CanvasCourseCreateError(
            msg_details=self.sis_course_id)
        get_default_template_for_school.side_effect = NoTemplateExistsForSchool(
            self.school_id)
        with self.assertRaises(CanvasCourseCreateError):
            controller.create_canvas_course(self.sis_course_id,
                                            self.sis_user_id)

        send_failure_msg_to_support.assert_called_with(
            self.sis_course_id, self.sis_user_id, exception_data.display_text)
        self.assertTrue(
            'Error: SIS ID not applied for CID' in exception_data.display_text)
Beispiel #15
0
def call(action,
         url,
         request_context,
         params=None,
         data=None,
         max_retries=None,
         auth_token=None,
         files=None,
         headers=None,
         cookies=None,
         timeout=None,
         proxies=None,
         verify=None,
         cert=None,
         allow_redirects=True):
    """This method servers as a pass-through to the requests library request functionality, but provides some configurable default
    values.  Constructs and sends a :class:`requests.Request <Request>`.
    Returns :class:`requests.Response <Response>` object.

    :param action: method for the new :class:`Request` object.
    :param url: Absolute url path to API method
    :param request_context: Instance of :class:`RequestContext` that holds a request session and other default values
    :param params: (optional) Dictionary or bytes to be sent in the query string for the :class:`Request`.
    :param data: (optional) Dictionary, bytes, or file-like object to send in the body of the :class:`Request`.
    :param int max_retries: (optional) Number of times a request that generates a certain class of HTTP exception will be retried
        before being raised back to the caller.  See :py:mod:`client.base` for a list of those error types.
    :param files: (optional) Dictionary of 'name': file-like-objects (or {'name': ('filename', fileobj)}) for multipart encoding upload.
    :param dictionary headers: (optional) dictionary of headers to send for each request.  Will be merged with a default set of headers.
    :param cookies: (optional) Cookies to attach to each requests.
    :type cookies: dictionary or CookieJar
    :param str auth_token: (optional) OAuth2 token retrieved from a Canvas site
    :param float timeout: (optional) The timeout of the request in seconds.
    :param dictionary proxies: (optional) Mapping protocol to the URL of the proxy.
    :param verify: (optional) if ``True``, the SSL cert will be verified.  A CA_BUNDLE path can also be provided.
    :type verify: boolean or str
    :param cert: (optional) if String, path to ssl client cert file (.pem).  If Tuple, ('cert', 'key') pair.
    :type cert: str or Tuple
    :param bool allow_redirects: (optional) Set to True if POST/PUT/DELETE redirect following is allowed.  Defaults to True.
    """
    # This will be a requests.Session object with defaults set for context
    canvas_session = request_context.session
    retries = max_retries or request_context.max_retries  # Default back to value in request_context
    if retries is None:
        retries = 0  # Fall back in case max_retries in context was explicitly set to None
    # Set up an authentication callable using OAuth2Bearer if a token was passed in
    auth = None
    if auth_token:
        auth = OAuth2Bearer(auth_token)
    # try the request until max_retries is reached.  we need to account for the
    # fact that the first iteration through isn't a retry, so add 1 to max_retries
    for retry in range(retries + 1):
        try:
            # build and send the request
            response = canvas_session.request(action,
                                              url,
                                              params=params,
                                              data=data,
                                              headers=headers,
                                              cookies=cookies,
                                              files=files,
                                              auth=auth,
                                              timeout=timeout,
                                              proxies=proxies,
                                              verify=verify,
                                              cert=cert,
                                              allow_redirects=allow_redirects)

            # raise an http exception if one occured
            response.raise_for_status()

        except HTTPError as http_error:
            # Need to check its an error code that can be retried
            status_code = http_error.response.status_code
            # If we can't retry the request, raise a CanvasAPIError
            if status_code not in RETRY_ERROR_CODES or retry >= retries:
                error_json = http_error.response.json()
                raise CanvasAPIError(
                    status_code=status_code,
                    msg=str(error_json),
                    error_json=error_json,
                )
        else:
            return response
Beispiel #16
0
 def mock_unauthorized_exception(self):
     exception = CanvasAPIError()
     exception.response = MagicMock()
     exception.status_code = 401
     return exception
Beispiel #17
0
 def test_redirect_on_API_auth_error(self, oauth_mock):
     with patch('edx2canvas.canvas_api.get_courses') as courses_mock:
         courses_mock.side_effect = CanvasAPIError(status_code=401)
         views.main(self.request)
     oauth_mock.assert_called_once_with(self.request, self.canvas_user_id)
Beispiel #18
0
 def mock_api_exception(self):
     exception = CanvasAPIError()
     exception.response = MagicMock()
     return exception
 def setUp(self):
     self.default_api_error = CanvasAPIError()