def assert_data_generated_correctly(self,
                                     course_run,
                                     expected_team_data,
                                     creating=False):
     course = course_run.course
     expected = {
         'title':
         course_run.title_override or course.title,
         'org':
         course.organizations.first().key,
         'number':
         course.number,
         'run':
         StudioAPI.calculate_course_run_key_run_value(
             course.number, course_run.start_date_temporary),
         'schedule': {
             'start': serialize_datetime(course_run.start_date_temporary),
             'end': serialize_datetime(course_run.end_date_temporary),
         },
         'team':
         expected_team_data,
         'pacing_type':
         course_run.pacing_type_temporary,
     }
     assert StudioAPI.generate_data_for_studio_api(
         course_run, creating=creating) == expected
示例#2
0
 def update_course_run_image_in_studio(cls, course_run):
     if course_run.course.partner.studio_url:
         api = StudioAPI(course_run.course.partner.studio_api_client)
         api.update_course_run_image_in_studio(course_run)
     else:
         log.info('Not updating course run image for %s to Studio as partner %s has no studio_url set.',
                  course_run.key, course_run.course.partner.short_code)
示例#3
0
 def push_to_studio(cls, request, course_run, create=False, old_course_run_key=None):
     if course_run.course.partner.studio_url:
         api = StudioAPI(course_run.course.partner.studio_api_client)
         api.push_to_studio(course_run, create, old_course_run_key, user=request.user)
     else:
         log.info('Not pushing course run info for %s to Studio as partner %s has no studio_url set.',
                  course_run.key, course_run.course.partner.short_code)
示例#4
0
    def test_calculate_course_run_key_run_value_with_multiple_runs_per_trimester(self):
        start = datetime.datetime(2017, 2, 1)

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017')
        assert StudioAPI.calculate_course_run_key_run_value('TestX', start) == '1T2017a'

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017a')
        assert StudioAPI.calculate_course_run_key_run_value('TestX', start) == '1T2017b'
示例#5
0
 def test_generate_data_for_studio_api_without_team(self):
     run = CourseRunFactory()
     with mock.patch('course_discovery.apps.api.utils.logger.warning') as mock_logger:
         assert StudioAPI.generate_data_for_studio_api(run, True) == self.make_studio_data(run)
     mock_logger.assert_called_with(
         'No course team admin specified for course [%s]. This may result in a Studio course run '
         'being created without a course team.',
         run.key.split('/')[1]
     )
示例#6
0
 def test_generate_data_for_studio_api(self):
     run = CourseRunFactory()
     editor = CourseEditorFactory(course=run.course)
     team = [
         {
             'user': editor.user.username,
             'role': 'instructor',
         },
     ]
     assert StudioAPI.generate_data_for_studio_api(run, True) == self.make_studio_data(run, team=team)
示例#7
0
class StudioAPITests(TestCase):
    def setUp(self):
        super().setUp()
        self.client = mock.Mock()
        self.api = StudioAPI(self.client)

    def make_studio_data(self, run, add_pacing=True, add_schedule=True):
        key = CourseKey.from_string(run.key)
        data = {
            'title': run.title,
            'org': key.org,
            'number': key.course,
            'run': key.run,
            'team': [],
        }
        if add_pacing:
            data['pacing_type'] = run.pacing_type
        if add_schedule:
            data['schedule'] = {
                'start': serialize_datetime(run.start),
                'end': serialize_datetime(run.end),
            }
        return data

    def test_create_rerun(self):
        run1 = CourseRunFactory()
        run2 = CourseRunFactory(course=run1.course)
        self.api.create_course_rerun_in_studio(run2, run1.key)

        expected_data = self.make_studio_data(run2)
        self.assertEqual(self.client.course_runs.call_args_list,
                         [mock.call(run1.key)])
        self.assertEqual(
            self.client.course_runs.return_value.rerun.post.call_args_list[0]
            [0][0], expected_data)

    def test_create_run(self):
        run = CourseRunFactory()
        self.api.create_course_run_in_studio(run)

        expected_data = self.make_studio_data(run)
        self.assertEqual(self.client.course_runs.post.call_args_list[0][0][0],
                         expected_data)

    def test_update_run(self):
        run = CourseRunFactory()
        self.api.update_course_run_details_in_studio(run)

        expected_data = self.make_studio_data(run,
                                              add_pacing=False,
                                              add_schedule=False)
        self.assertEqual(self.client.course_runs.call_args_list,
                         [mock.call(run.key)])
        self.assertEqual(
            self.client.course_runs.return_value.patch.call_args_list[0][0][0],
            expected_data)
 def setUp(self):
     super().setUp()
     self.mock_access_token()
     self.api = StudioAPI(self.partner)
     self.studio_url = self.partner.studio_url
class StudioAPITests(OAuth2Mixin, APITestCase):
    def setUp(self):
        super().setUp()
        self.mock_access_token()
        self.api = StudioAPI(self.partner)
        self.studio_url = self.partner.studio_url

    def make_studio_data(self,
                         run,
                         add_pacing=True,
                         add_schedule=True,
                         team=None):
        key = CourseKey.from_string(run.key)
        data = {
            'title': run.title,
            'org': key.org,
            'number': key.course,
            'run': key.run,
            'team': team or [],
        }
        if add_pacing:
            data['pacing_type'] = run.pacing_type
        if add_schedule:
            data['schedule'] = {
                'start': serialize_datetime(run.start),
                'end': serialize_datetime(run.end),
            }
        return data

    def assert_data_generated_correctly(self,
                                        course_run,
                                        expected_team_data,
                                        creating=False):
        course = course_run.course
        expected = {
            'title':
            course_run.title_override or course.title,
            'org':
            course.organizations.first().key,
            'number':
            course.number,
            'run':
            StudioAPI.calculate_course_run_key_run_value(
                course.number, course_run.start_date_temporary),
            'schedule': {
                'start': serialize_datetime(course_run.start_date_temporary),
                'end': serialize_datetime(course_run.end_date_temporary),
            },
            'team':
            expected_team_data,
            'pacing_type':
            course_run.pacing_type_temporary,
        }
        assert StudioAPI.generate_data_for_studio_api(
            course_run, creating=creating) == expected

    def test_create_rerun(self):
        run1 = CourseRunFactory()
        run2 = CourseRunFactory(course=run1.course)

        expected_data = self.make_studio_data(run2)
        responses.add(responses.POST,
                      f'{self.studio_url}api/v1/course_runs/{run1.key}/rerun/',
                      match=[responses.json_params_matcher(expected_data)])

        self.api.create_course_rerun_in_studio(run2, run1.key)

    def test_create_run(self):
        run = CourseRunFactory()

        expected_data = self.make_studio_data(run)
        responses.add(responses.POST,
                      f'{self.studio_url}api/v1/course_runs/',
                      match=[responses.json_params_matcher(expected_data)])

        self.api.create_course_run_in_studio(run)

    def test_update_run(self):
        run = CourseRunFactory()

        expected_data = self.make_studio_data(run,
                                              add_pacing=False,
                                              add_schedule=False)
        responses.add(responses.PATCH,
                      f'{self.studio_url}api/v1/course_runs/{run.key}/',
                      match=[responses.json_params_matcher(expected_data)])

        self.api.update_course_run_details_in_studio(run)

    @ddt.data(
        *product(range(1, 5), ['1T2017']),
        *product(range(5, 9), ['2T2017']),
        *product(range(9, 13), ['3T2017']),
    )
    @ddt.unpack
    def test_calculate_course_run_key_run_value(self, month, expected):
        start = datetime.datetime(2017, month, 1)
        assert StudioAPI.calculate_course_run_key_run_value(
            'NONE', start=start) == expected

    def test_generate_data_for_studio_api(self):
        run = CourseRunFactory()
        editor = CourseEditorFactory(course=run.course)
        team = [
            {
                'user': editor.user.username,
                'role': 'instructor',
            },
        ]
        assert StudioAPI.generate_data_for_studio_api(
            run, True) == self.make_studio_data(run, team=team)

    def test_generate_data_for_studio_api_without_team(self):
        run = CourseRunFactory()
        with mock.patch('course_discovery.apps.api.utils.logger.warning'
                        ) as mock_logger:
            assert StudioAPI.generate_data_for_studio_api(
                run, True) == self.make_studio_data(run)
        mock_logger.assert_called_with(
            'No course team admin specified for course [%s]. This may result in a Studio course run '
            'being created without a course team.',
            run.key.split('/')[1])

    def test_calculate_course_run_key_run_value_with_multiple_runs_per_trimester(
            self):
        start = datetime.datetime(2017, 2, 1)

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017')
        assert StudioAPI.calculate_course_run_key_run_value('TestX',
                                                            start) == '1T2017a'

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017a')
        assert StudioAPI.calculate_course_run_key_run_value('TestX',
                                                            start) == '1T2017b'

    def test_update_course_run_image_in_studio_without_course_image(self):
        run = CourseRunFactory(course__image=None)
        with mock.patch(
                'course_discovery.apps.api.utils.logger') as mock_logger:
            self.api.update_course_run_image_in_studio(run)
            mock_logger.warning.assert_called_with(
                'Card image for course run [%d] cannot be updated. The related course [%d] has no image defined.',
                run.id, run.course.id)
示例#10
0
 def test_calculate_course_run_key_run_value(self, month, expected):
     start = datetime.datetime(2017, month, 1)
     assert StudioAPI.calculate_course_run_key_run_value(
         'NONE', start=start) == expected
示例#11
0
 def setUp(self):
     super().setUp()
     self.client = mock.Mock()
     self.api = StudioAPI(self.client)
class StudioAPITests(TestCase):
    def setUp(self):
        super().setUp()
        self.client = mock.Mock()
        self.api = StudioAPI(self.client)

    def make_studio_data(self,
                         run,
                         add_pacing=True,
                         add_schedule=True,
                         team=None):
        key = CourseKey.from_string(run.key)
        data = {
            'title': run.title,
            'org': key.org,
            'number': key.course,
            'run': key.run,
            'team': team or [],
        }
        if add_pacing:
            data['pacing_type'] = run.pacing_type
        if add_schedule:
            data['schedule'] = {
                'start': serialize_datetime(run.start),
                'end': serialize_datetime(run.end),
            }
        return data

    def assert_data_generated_correctly(self,
                                        course_run,
                                        expected_team_data,
                                        creating=False):
        course = course_run.course
        expected = {
            'title':
            course_run.title_override or course.title,
            'org':
            course.organizations.first().key,
            'number':
            course.number,
            'run':
            StudioAPI.calculate_course_run_key_run_value(
                course.number, course_run.start_date_temporary),
            'schedule': {
                'start': serialize_datetime(course_run.start_date_temporary),
                'end': serialize_datetime(course_run.end_date_temporary),
            },
            'team':
            expected_team_data,
            'pacing_type':
            course_run.pacing_type_temporary,
        }
        self.assertEqual(
            StudioAPI.generate_data_for_studio_api(course_run,
                                                   creating=creating),
            expected)

    def test_create_rerun(self):
        run1 = CourseRunFactory()
        run2 = CourseRunFactory(course=run1.course)
        self.api.create_course_rerun_in_studio(run2, run1.key)

        expected_data = self.make_studio_data(run2)
        self.assertEqual(self.client.course_runs.call_args_list,
                         [mock.call(run1.key)])
        self.assertEqual(
            self.client.course_runs.return_value.rerun.post.call_args_list[0]
            [0][0], expected_data)

    def test_create_run(self):
        run = CourseRunFactory()
        self.api.create_course_run_in_studio(run)

        expected_data = self.make_studio_data(run)
        self.assertEqual(self.client.course_runs.post.call_args_list[0][0][0],
                         expected_data)

    def test_update_run(self):
        run = CourseRunFactory()
        self.api.update_course_run_details_in_studio(run)

        expected_data = self.make_studio_data(run,
                                              add_pacing=False,
                                              add_schedule=False)
        self.assertEqual(self.client.course_runs.call_args_list,
                         [mock.call(run.key)])
        self.assertEqual(
            self.client.course_runs.return_value.patch.call_args_list[0][0][0],
            expected_data)

    @ddt.data(
        *product(range(1, 5), ['1T2017']),
        *product(range(5, 9), ['2T2017']),
        *product(range(9, 13), ['3T2017']),
    )
    @ddt.unpack
    def test_calculate_course_run_key_run_value(self, month, expected):
        start = datetime.datetime(2017, month, 1)
        self.assertEqual(
            StudioAPI.calculate_course_run_key_run_value('NONE', start=start),
            expected)

    def test_generate_data_for_studio_api(self):
        run = CourseRunFactory()
        editor = CourseEditorFactory(course=run.course)
        team = [
            {
                'user': editor.user.username,
                'role': 'instructor',
            },
        ]
        self.assertEqual(StudioAPI.generate_data_for_studio_api(run, True),
                         self.make_studio_data(run, team=team))

    def test_generate_data_for_studio_api_without_team(self):
        run = CourseRunFactory()
        with mock.patch('course_discovery.apps.api.utils.logger.warning'
                        ) as mock_logger:
            self.assertEqual(StudioAPI.generate_data_for_studio_api(run, True),
                             self.make_studio_data(run))
        mock_logger.assert_called_with(
            'No course team admin specified for course [%s]. This may result in a Studio course run '
            'being created without a course team.',
            run.key.split('/')[1])

    def test_calculate_course_run_key_run_value_with_multiple_runs_per_trimester(
            self):
        start = datetime.datetime(2017, 2, 1)

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017')
        self.assertEqual(
            StudioAPI.calculate_course_run_key_run_value('TestX', start),
            '1T2017a')

        CourseRunFactory(key='course-v1:TestX+Testing101x+1T2017a')
        self.assertEqual(
            StudioAPI.calculate_course_run_key_run_value('TestX', start),
            '1T2017b')

    def test_update_course_run_image_in_studio_without_course_image(self):
        run = CourseRunFactory(course__image=None)
        with mock.patch(
                'course_discovery.apps.api.utils.logger') as mock_logger:
            self.api.update_course_run_image_in_studio(run)
            mock_logger.warning.assert_called_with(
                'Card image for course run [%d] cannot be updated. The related course [%d] has no image defined.',
                run.id, run.course.id)