Example #1
0
    def get_message(self, chat, next_lesson, is_additional, *args, **kwargs) -> Message:
        _response_data = {
            'lesson': chat.state.unitLesson.lesson,
            'unitLesson': chat.state.unitLesson,
            'course': chat.enroll_code.courseUnit.course,
            'author': chat.user,
            'activity': chat.state.activity,
            'is_test': chat.is_test,
            'is_preview': chat.enroll_code.isPreview,
            'is_trial': chat.is_trial,
        }
        resp = Response(**_response_data)
        resp.save()

        _data = {
            'contenttype': 'response',
            'content_id': resp.id,
            'input_type': 'options',
            # This is needed to track the last response to handle status
            'lesson_to_answer_id': chat.state.unitLesson.id,
            'chat': chat,
            'owner': chat.user,
            'kind': 'response',
            'userMessage': True,
            'is_additional': is_additional
        }
        message = Message(**_data)
        message.save()
        return message
Example #2
0
 def setUp(self):
     self.user = User.objects.create_user(username='******', password='******')
     self.course = Course(title='test_title', addedBy=self.user)
     self.course.save()
     self.concept = Concept(title='test title', addedBy=self.user)
     self.concept.save()
     self.lesson = Lesson(title='ugh',
                          text='brr',
                          addedBy=self.user,
                          kind=Lesson.ORCT_QUESTION)
     self.lesson.save_root()
     self.lesson.add_concept_link(self.concept, ConceptLink.TESTS,
                                  self.user)
     self.unit = Unit(title='test unit title', addedBy=self.user)
     self.unit.save()
     self.unit_lesson = UnitLesson(unit=self.unit,
                                   addedBy=self.user,
                                   treeID=42,
                                   lesson=self.lesson)
     self.unit_lesson.save()
     self.response = Response(course=self.course,
                              lesson=self.lesson,
                              author=self.user,
                              unitLesson=self.unit_lesson,
                              confidence=Response.GUESS,
                              title='test title',
                              text='test text')
     self.response.save()
     self.context = {
         'actionTarget': '/ct/courses/1/units/1/',
         'ul': self.unit_lesson,
         'test_text': 'This is a test text',
         'r': self.response
     }
Example #3
0
 def setUp(self):
     self.user = User.objects.create_user(username="******", password="******")
     self.course = Course(title="test_title", addedBy=self.user)
     self.course.save()
     self.concept = Concept(title="test title", addedBy=self.user)
     self.concept.save()
     self.lesson = Lesson(title="ugh", text="brr", addedBy=self.user, kind=Lesson.ORCT_QUESTION)
     self.lesson.save_root()
     self.lesson.add_concept_link(self.concept, ConceptLink.TESTS, self.user)
     self.unit = Unit(title="test unit title", addedBy=self.user)
     self.unit.save()
     self.unit_lesson = UnitLesson(unit=self.unit, addedBy=self.user, treeID=42, lesson=self.lesson)
     self.unit_lesson.save()
     self.response = Response(
         course=self.course,
         lesson=self.lesson,
         author=self.user,
         unitLesson=self.unit_lesson,
         confidence=Response.GUESS,
         title="test title",
         text="test text",
     )
     self.response.save()
     self.context = {
         "actionTarget": "/ct/courses/1/units/1/",
         "ul": self.unit_lesson,
         "test_text": "This is a test text",
         "r": self.response,
     }
Example #4
0
    def perform_update(self, serializer):
        chat_id = self.request.data.get('chat_id')
        message = self.get_object()
        chat = Chat.objects.get(id=chat_id, user=self.request.user)
        activity = chat.state and chat.state.activity

        is_in_node = lambda node: message.chat.state.fsmNode.name == node

        # Check if message is not in current chat
        if not message.chat or message.chat != chat:
            return

        # Chat add unit lesson
        if is_chat_add_lesson(message):
            message.chat = chat
            text = self.request.data.get('text')
            option = self.request.data.get('option')
            course_unit = message.chat.enroll_code.courseUnit
            unit = course_unit.unit

            if message.input_type == 'options' and is_in_node('HAS_UNIT_ANSWER'):
                message = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request
                )
                chat.next_point = message
                chat.save()
                serializer.save(chat=chat, timestamp=timezone.now())

            if is_in_node('GET_UNIT_NAME_TITLE'):
                if course_unit and unit:
                    if not message.content_id:
                        lesson = Lesson.objects.create(title=text, addedBy=self.request.user,
                                                       kind=Lesson.ORCT_QUESTION, text='')
                        lesson.treeID = lesson.id
                        lesson.save()
                        ul = UnitLesson.create_from_lesson(
                            lesson=lesson, unit=unit, kind=UnitLesson.COMPONENT, order='APPEND',
                        )
                        chat.state.unitLesson = ul
                        chat.state.save()
                    else:
                        ul = message.content
                    if not message.timestamp:
                        serializer.save(
                            content_id=ul.id,
                            timestamp=timezone.now(),
                            chat=chat,
                            text=text,
                            contenttype='unitlesson'
                        )
                    else:
                        serializer.save()

            if is_in_node('GET_UNIT_QUESTION'):
                ul = message.content
                ul.lesson.text = text
                ul.lesson.save()
                if not message.timestamp:
                    serializer.save(
                        content_id=ul.id,
                        timestamp=timezone.now(),
                        chat=chat,
                        contenttype='unitlesson',
                        text=text
                    )
                else:
                    serializer.save()

            if is_in_node('GET_UNIT_ANSWER'):
                #  create answer
                ul = message.content

                if not message.timestamp:
                    answer = Lesson.objects.create(
                        title='Answer',
                        text=text,
                        addedBy=self.request.user,
                        kind=Lesson.ANSWER,
                    )
                    answer.save_root()
                    unit_lesson_answer = UnitLesson.create_from_lesson(
                        unit=ul.unit, lesson=answer, parent=ul, kind=UnitLesson.ANSWERS
                    )
                    # chat.next_point = message
                    chat.save()
                    serializer.save(content_id=ul.id, timestamp=timezone.now(), chat=chat,
                                    contenttype='unitlesson', text=text)
                else:
                    serializer.save()

            if is_in_node('GET_HAS_UNIT_ANSWER'):
                yes_no_map = {
                    'yes': True,
                    'no': False
                }
                ul = message.content
                has_answer = yes_no_map.get(self.request.data.get('option'))
                if has_answer is None:
                    raise ValueError("Recieved not valid response from user")

                ul.lesson.kind = Lesson.ORCT_QUESTION if has_answer else Lesson.BASE_EXPLANATION
                ul.lesson.save()
                message.text = self.request.data.get('option')
                message.save()

        if message.input_type == 'text' and not is_chat_add_lesson(message):
            message.chat = chat
            text = self.request.data.get('text')

            if message.lesson_to_answer.sub_kind == Lesson.EQUATION:
                text = text.strip("$")
                text = '.. math:: ' + text
            resp = StudentResponse(text=text)

            # convert base64 attachment string to django File
            data_attachment = self.request.data.get('attachment')
            if data_attachment and data_attachment.startswith('data:image'):
                format, image_string = data_attachment.split(';base64,')
                extension = format.split('/')[-1].split('+')[0]
                name = '{}.{}'.format('canvas', extension)
                resp.attachment = ContentFile(base64.b64decode(image_string), name=name)

            if not message.content_id:
                resp.lesson = message.lesson_to_answer.lesson
                resp.unitLesson = message.lesson_to_answer
                resp.course = message.chat.enroll_code.courseUnit.course
                resp.author = self.request.user
                resp.activity = activity
                resp.is_test = chat.is_test
                resp.is_preview = chat.enroll_code.isPreview
                resp.sub_kind = resp.lesson.sub_kind
            else:
                resp = message.content
                resp.text = text
            resp.is_trial = chat.is_trial
            resp.save()

            if not message.timestamp:
                message.content_id = resp.id
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id, timestamp=timezone.now(), chat=chat)
            else:
                serializer.save()

        message_is_response = message.contenttype == 'response'
        lesson_has_sub_kind = message.lesson_to_answer and message.lesson_to_answer.sub_kind
        content_is_not_additional = not message.content and not message.is_additional

        mc_selfeval = None
        if message_is_response and lesson_has_sub_kind and content_is_not_additional:
            resp_text = ''
            if message.lesson_to_answer.sub_kind == Lesson.MULTIPLE_CHOICES:
                selected_items = self.request.data.get('selected')
                try:
                    selected = selected_items[str(message.id)]['choices']
                except KeyError:
                    # here request.data is like {"option":1,"chat_id":9,"selected":{"116":{"choices":[0]}}}
                    selected_msg_ids = self.request.data.get(
                        'selected'
                    ).keys()
                    # selected_messages == tuple with keys of this dict {"116":{"choices":[0]}} - it will be ("116",)
                    msg_ids = Message.objects.filter(id__in=selected_msg_ids, chat=chat).values_list('id', flat=True)
                    correct_ids = set(msg_ids).intersection(
                        set(int(i) for i in selected_items.keys())
                    )
                    selected_choices = []
                    for i in correct_ids:
                        selected_choices.append(selected_items[str(i)]['choices'])
                    selected = chain(*selected_choices)

                resp_text = '[selected_choices] ' + ' '.join(str(i) for i in selected)

                correct_choices = set([_[0] for _ in message.lesson_to_answer.lesson.get_correct_choices()])
                selected_choices = set([_ for _ in chain(*selected_choices)])

                if not (correct_choices - selected_choices or correct_choices ^ selected_choices):
                    mc_selfeval = StudentResponse.CORRECT
                elif selected_choices & correct_choices:
                    mc_selfeval = StudentResponse.CLOSE
                else:
                    mc_selfeval = StudentResponse.DIFFERENT


            resp = StudentResponse(text=resp_text)
            # tes, preview flags
            resp.is_test = chat.is_test
            resp.selfeval = mc_selfeval or None
            resp.is_preview = chat.enroll_code.isPreview
            resp.is_trial = chat.is_trial

            resp.kind = message.lesson_to_answer.kind
            resp.sub_kind = message.lesson_to_answer.sub_kind
            resp.lesson = message.lesson_to_answer.lesson
            resp.unitLesson = message.lesson_to_answer
            resp.course = message.chat.enroll_code.courseUnit.course
            resp.author = self.request.user
            resp.activity = activity
            resp.save()

            if not message.timestamp:
                serializer.save(content_id=resp.id, timestamp=timezone.now(), chat=chat, response_to_check=resp)
            else:
                serializer.save()
            return
        if message.input_type == 'options' and message.kind != 'button':
            if (
                message.contenttype == 'uniterror' and
                'selected' in self.request.data
            ):
                # user selected error model
                message.chat = chat
                try:
                    selected = self.request.data.get(
                        'selected'
                    )[str(message.id)]['errorModel']
                except KeyError:
                    selected = []
                uniterror = message.content
                uniterror.save_response(user=self.request.user, response_list=selected)
                if not message.chat.is_live:
                    get_additional_messages(uniterror.response, chat)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request
                )
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(chat=chat)
            elif message.contenttype == 'NoneType' and message.kind == 'abort':
                # user selected abort model
                message.chat = chat
                try:
                    selected = self.request.data.get(
                        'selected'
                    )[str(message.id)]['errorModel']
                except KeyError:
                    selected = []
                if not message.chat.is_live and selected:
                    get_help_messages(chat)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request
                )
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(chat=chat)
            elif message.content_id and not message.student_error:
                # confidence and selfeval
                message.chat = chat
                opt_data = self.request.data.get('option')
                resp = message.content
                if chat.state and chat.state.fsmNode.node_name_is_one_of('GET_CONFIDENCE'):
                    resp.confidence = opt_data
                    text = resp.get_confidence_display()
                else:
                    resp.selfeval = opt_data
                    text = resp.get_selfeval_display()
                    # FIX if response was correct - user will not go to `else` section and response status should be set
                    if resp.selfeval == StudentResponse.CORRECT:
                        resp.status = DONE_STATUS
                message.text = text
                resp.save()
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id, chat=chat, text=text)
            else:
                #
                message.chat = chat
                selfeval = self.request.data.get('option')
                resp = message.student_error
                resp.status = selfeval
                resp.save()
                # pass status to main response
                resp.response.status = selfeval
                resp.response.save()
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                message.text = selfeval
                message.save()
                serializer.save(text=selfeval, chat=chat)
        if message.kind == 'button' and not (message.content_id and message.content and message.content.sub_kind):
            chat.last_modify_timestamp = timezone.now()
            chat.next_point = self.next_handler.next_point(
                current=message.content,
                chat=chat,
                message=message,
                request=self.request,
            )
            chat.save()
Example #5
0
class TagsTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(username='******', password='******')
        self.course = Course(title='test_title', addedBy=self.user)
        self.course.save()
        self.concept = Concept(title='test title', addedBy=self.user)
        self.concept.save()
        self.lesson = Lesson(title='ugh',
                             text='brr',
                             addedBy=self.user,
                             kind=Lesson.ORCT_QUESTION)
        self.lesson.save_root()
        self.lesson.add_concept_link(self.concept, ConceptLink.TESTS,
                                     self.user)
        self.unit = Unit(title='test unit title', addedBy=self.user)
        self.unit.save()
        self.unit_lesson = UnitLesson(unit=self.unit,
                                      addedBy=self.user,
                                      treeID=42,
                                      lesson=self.lesson)
        self.unit_lesson.save()
        self.response = Response(course=self.course,
                                 lesson=self.lesson,
                                 author=self.user,
                                 unitLesson=self.unit_lesson,
                                 confidence=Response.GUESS,
                                 title='test title',
                                 text='test text')
        self.response.save()
        self.context = {
            'actionTarget': '/ct/courses/1/units/1/',
            'ul': self.unit_lesson,
            'test_text': 'This is a test text',
            'r': self.response
        }

    def render_template(self, string, context=None):
        context = context or {}
        context = Context(context)
        return Template(string).render(context)

    @unpack
    @data(
        ('{{ test_text | md2html }}', '<p>This is a test text</p>\n'),
        ('{{ actionTarget | get_object_url:ul }}',
         '/ct/courses/1/units/1/lessons/1/'),
        ('{{ actionTarget | get_home_url:ul }}',
         '/ct/courses/1/units/1/lessons/1/'),
        ('{{ actionTarget | get_thread_url:r }}',
         '/ct/courses/1/units/1/lessons/1/faq/1/'),
        ('{{ actionTarget | get_tasks_url:ul }}',
         '/ct/courses/1/units/1/lessons/1/tasks/'),
        ('{{ actionTarget | get_dummy_navbar }}',
         '<li><a href="/ct/courses/1/">Course</a></li>'),
    )
    def test_all_filters(self, template_variable, expected_result):
        rendered = self.render_template('{% load ct_extras %}' +
                                        template_variable,
                                        context=self.context)
        self.assertEqual(rendered, expected_result)

    @patch('ct.templatetags.ct_extras.pypandoc')
    def test_md2html_pandoc_exception(self, pypandoc):
        pypandoc.convert.side_effect = StandardError
        rendered = self.render_template(
            '{% load ct_extras %}'
            '{{ test_text | md2html }}',
            context=self.context)
        self.assertEqual(rendered, self.context['test_text'])

    @data('get_base_url', 'get_path_type')
    def test_get_base_url_exception(self, helper):
        with self.assertRaises(ValueError):
            getattr(inspect.getmodule(self),
                    helper).__call__('/ct/courses/1/units/1/lessons/1/',
                                     baseToken='non_existent_token')

    def test_get_object_url_exception(self):
        self.context[
            'ul'] = self.unit  # Unit object does not have get_url method
        rendered = self.render_template(
            '{% load ct_extras %}'
            '{{ actionTarget | get_object_url:ul }}',
            context=self.context)
        self.assertEqual(rendered, '/ct/courses/1/units/1/unit/1/teach/')

    @patch('ct.templatetags.ct_extras.timezone')
    def test_display_datetime(self, timezone_patched):
        saved_time = timezone.now()
        timezone_patched.now.return_value = saved_time
        context = {'dt': saved_time - timedelta(1)}
        rendered = self.render_template(
            '{% load ct_extras %}'
            '{{ dt|display_datetime }}',
            context=context)
        self.assertEqual(rendered, '1 day ago')

    def test_find_audio(self):
        result = find_audio('test tag head .. audio:: test tag tail \n', 4)
        self.assertEqual(result, (14, 39, 'test tag tail'))

    def test_audio_html(self):
        """
        Function should return string for embeding audio into html.
        """
        result = audio_html('audio.mp3')
        self.assertEqual(
            result,
            '''<audio controls><source src="audio.ogg" type="audio/ogg"><source src="audio.mp3" '''
            '''type="audio/mpeg">no support for audio!</audio>''')

    def test_video_html(self):
        """
        Function should return string for embeding youtube or vimeo link.
        """
        result = video_html('youtube:test_video_path')
        self.assertIn('test_video_path', result)
        self.assertIn('src="https://www.youtube.com/embed/', result)

        result = video_html('vimeo:test_video_path')
        self.assertIn('test_video_path', result)
        self.assertIn('src="https://player.vimeo.com/video/', result)

    def test_video_html_with_exception(self):
        """
        Test exception handling.
        """
        result = video_html('youtube')
        self.assertEqual(result, 'ERROR: bad video source: youtube')

        result = video_html('some_new_cdn:test_video_path')
        self.assertEqual(result, 'ERROR: unknown video sourceDB: some_new_cdn')

    def test_add_replace_temporary_markers(self):
        """
        Test add_temporary_markers and replace_temporary_markers in tandem.
        """
        result = add_temporary_markers(
            'test tag head .. audio:: test tag tail \n', find_audio)
        self.assertEqual(
            result,
            ('test tag head mArKeR:0:\n', [('mArKeR:0:', 'test tag tail')]))

        result = replace_temporary_markers(result[0], audio_html, result[1])
        self.assertEqual(
            result,
            '''test tag head <audio controls><source src="test tag tail.ogg" type="audio/ogg">'''
            '''<source src="test tag tail.mp3" type="audio/mpeg">no support for audio!</audio>\n'''
        )
Example #6
0
    def setUp(self):
        self.username, self.password = '******', 'test'
        self.user = User.objects.create_user(self.username, '*****@*****.**', self.password)

        self.instructor = Instructor.objects.create(user=self.user, institution='institute',
                                                    what_do_you_teach='something')

        self.username2, self.password2 = 'test1', 'test'
        self.user2 = User.objects.create_user(self.username2, '*****@*****.**', self.password2)
        self.instructor2 = Instructor.objects.create(user=self.user2, institution='institute',
                                                     what_do_you_teach='something')

        self.unit = Unit(title='Test title', addedBy=self.user)
        self.unit.save()
        self.course = Course(title='Test title',
                             description='test description',
                             access='Public',
                             enrollCode='111',
                             lockout='222',
                             addedBy=self.user)
        self.course.save()

        self.courseunit = CourseUnit(
            unit=self.unit, course=self.course,
            order=0, addedBy=self.user, releaseTime=timezone.now()
        )
        self.courseunit.save()
        self.lesson = Lesson(title='title', text='text', addedBy=self.user)
        self.lesson.save()
        self.unitlesson = UnitLesson(
            unit=self.unit, order=0,
            lesson=self.lesson, addedBy=self.user,
            treeID=self.lesson.id
        )
        self.unitlesson.save()

        self.resp1 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may respond",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp1.save()

        self.resp2 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may be responded 2",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp2.save()
        self.default_data = {}

        self.client.login(username=self.username, password=self.password)
        self.url = reverse('ctms:course_settings', kwargs={'pk': self.course.id})
Example #7
0
class MyTestCase(TestCase):
    models_to_check = tuple()
    context_should_contain_keys = tuple()

    def setUp(self):
        self.username, self.password = '******', 'test'
        self.user = User.objects.create_user(self.username, '*****@*****.**', self.password)

        self.instructor = Instructor.objects.create(user=self.user, institution='institute',
                                                    what_do_you_teach='something')

        self.username2, self.password2 = 'test1', 'test'
        self.user2 = User.objects.create_user(self.username2, '*****@*****.**', self.password2)
        self.instructor2 = Instructor.objects.create(user=self.user2, institution='institute',
                                                     what_do_you_teach='something')

        self.unit = Unit(title='Test title', addedBy=self.user)
        self.unit.save()
        self.course = Course(title='Test title',
                             description='test description',
                             access='Public',
                             enrollCode='111',
                             lockout='222',
                             addedBy=self.user)
        self.course.save()

        self.courseunit = CourseUnit(
            unit=self.unit, course=self.course,
            order=0, addedBy=self.user, releaseTime=timezone.now()
        )
        self.courseunit.save()
        self.lesson = Lesson(title='title', text='text', addedBy=self.user)
        self.lesson.save()
        self.unitlesson = UnitLesson(
            unit=self.unit, order=0,
            lesson=self.lesson, addedBy=self.user,
            treeID=self.lesson.id
        )
        self.unitlesson.save()

        self.resp1 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may respond",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp1.save()

        self.resp2 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may be responded 2",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp2.save()
        self.default_data = {}

        self.client.login(username=self.username, password=self.password)
        self.url = reverse('ctms:course_settings', kwargs={'pk': self.course.id})

    def get_page(self):
        return self.client.get(self.url)

    def post_data(self, data={'name': 'some test name'}):
        response = self.client.post(self.url, data, follow=True)
        return response

    def get_client_method(self, method='post'):
        client_method = getattr(self.client, method)
        if not client_method:
            raise KeyError('self.client has no property {}'.format(method))
        return client_method

    def post_valid_data(self, data={'name': 'some test name'}, method='post'):
        client_method = self.get_client_method(method)
        copied_data = {}
        if getattr(self, 'default_data', False):
            copied_data.update(self.default_data)
            copied_data.update(data)
        response = client_method(self.url, copied_data, follow=True)
        return response

    def post_invalid_data(self, data={'name': ''}, method='post'):
        client_method = self.get_client_method(method)
        copied_data = {}
        if getattr(self, 'default_data', False):
            copied_data.update(self.default_data)
            copied_data.update(data)
        response = client_method(self.url, copied_data, follow=True)
        return response

    def get_my_courses(self):
        return Course.objects.filter(
            models.Q(addedBy=self.user) |
            models.Q(role__role=Role.INSTRUCTOR, role__user=self.user)
        )

    def get_test_course(self):
        return Course.objects.get(id=self.course.id)

    def get_test_unitlessons(self):
        return self.courseunit.unit.unitlesson_set.filter(
            kind=UnitLesson.COMPONENT,
            order__isnull=False
        ).order_by('order').annotate(
            responses_count=models.Count('response')
        )

    def get_test_unitlesson(self):
        return self.courseunit.unit.unitlesson_set.filter(
            kind=UnitLesson.COMPONENT,
            order__isnull=False
        ).order_by('order').annotate(
            responses_count=models.Count('response')
        )[0]

    get_test_courslet = get_test_unitlesson

    get_test_response = lambda self: self.get_test_responses()[0]

    def get_test_courseunit(self):
        return CourseUnit.objects.get(id=self.courseunit.id)

    def get_test_responses(self):
        return Response.objects.filter(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
        )

    def get_model_counts(self, **kwargs):
        if isinstance(self.models_to_check, (list, tuple)):
            return {model: model.objects.filter().count() for model in self.models_to_check}
        return {self.models_to_check: self.models_to_check.objects.filter().count()}

    def validate_model_counts(self, first_counts, second_counts, must_equal=False):
        if isinstance(self.models_to_check, (list, tuple)):
            all_models = self.models_to_check
        else:
            all_models = [self.models_to_check]

        for model in all_models:
            if must_equal:
                self.assertEqual(
                    first_counts[model], second_counts[model],
                    "{} ({}) != {} ({}), with must_equal={}".format(
                        model, first_counts[model], model, second_counts[model], must_equal
                    )
                )
            else:
                self.assertNotEqual(
                    first_counts[model], second_counts[model],
                    "{} ({}) == {} ({}), with must_equal={}".format(
                        model, first_counts[model], model, second_counts[model], must_equal
                    )
                )

    def check_context_keys(self, response):
        for key in self.context_should_contain_keys:
            self.assertIn(key, response.context)

    def am_i_instructor(self, method='GET'):
        methods_map = {'GET', self.client.get, 'POST', self.client.post}
        client_method = methods_map.get(method)
        self.assertIsNotNone(client_method)

        if getattr(self, 'url'):
            if getattr(self, 'NEED_INSTRUCTOR'):
                response = client_method(self.url)
                if getattr(self, 'instructor'):
                    self.assertEqual(response.status_code, 200)
                    self.instructor.delete()
                    response = client_method(self.url)
                    self.assertEqual(response.status_code, 403)
                else:
                    self.assertEqual(response.status_code, 403)
            else:
                response = client_method(self.url)
                self.assertEqual(response.status_code, 200)
Example #8
0
class TagsTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(username="******", password="******")
        self.course = Course(title="test_title", addedBy=self.user)
        self.course.save()
        self.concept = Concept(title="test title", addedBy=self.user)
        self.concept.save()
        self.lesson = Lesson(title="ugh", text="brr", addedBy=self.user, kind=Lesson.ORCT_QUESTION)
        self.lesson.save_root()
        self.lesson.add_concept_link(self.concept, ConceptLink.TESTS, self.user)
        self.unit = Unit(title="test unit title", addedBy=self.user)
        self.unit.save()
        self.unit_lesson = UnitLesson(unit=self.unit, addedBy=self.user, treeID=42, lesson=self.lesson)
        self.unit_lesson.save()
        self.response = Response(
            course=self.course,
            lesson=self.lesson,
            author=self.user,
            unitLesson=self.unit_lesson,
            confidence=Response.GUESS,
            title="test title",
            text="test text",
        )
        self.response.save()
        self.context = {
            "actionTarget": "/ct/courses/1/units/1/",
            "ul": self.unit_lesson,
            "test_text": "This is a test text",
            "r": self.response,
        }

    def render_template(self, string, context=None):
        context = context or {}
        context = Context(context)
        return Template(string).render(context)

    @unpack
    @data(
        ("{{ test_text | md2html }}", "<p>This is a test text</p>\n"),
        ("{{ actionTarget | get_object_url:ul }}", "/ct/courses/1/units/1/lessons/1/"),
        ("{{ actionTarget | get_home_url:ul }}", "/ct/courses/1/units/1/lessons/1/"),
        ("{{ actionTarget | get_thread_url:r }}", "/ct/courses/1/units/1/lessons/1/faq/1/"),
        ("{{ actionTarget | get_tasks_url:ul }}", "/ct/courses/1/units/1/lessons/1/tasks/"),
        ("{{ actionTarget | get_dummy_navbar }}", '<li><a href="/ct/courses/1/">Course</a></li>'),
    )
    def test_all_filters(self, template_variable, expected_result):
        rendered = self.render_template("{% load ct_extras %}" + template_variable, context=self.context)
        self.assertEqual(rendered, expected_result)

    @patch("ct.templatetags.ct_extras.pypandoc")
    def test_md2html_pandoc_exception(self, pypandoc):
        pypandoc.convert.side_effect = StandardError
        rendered = self.render_template("{% load ct_extras %}" "{{ test_text | md2html }}", context=self.context)
        self.assertEqual(rendered, self.context["test_text"])

    @data("get_base_url", "get_path_type")
    def test_get_base_url_exception(self, helper):
        with self.assertRaises(ValueError):
            getattr(inspect.getmodule(self), helper).__call__(
                "/ct/courses/1/units/1/lessons/1/", baseToken="non_existent_token"
            )

    def test_get_object_url_exception(self):
        self.context["ul"] = self.unit  # Unit object does not have get_url method
        rendered = self.render_template(
            "{% load ct_extras %}" "{{ actionTarget | get_object_url:ul }}", context=self.context
        )
        self.assertEqual(rendered, "/ct/courses/1/units/1/unit/1/teach/")

    @patch("ct.templatetags.ct_extras.timezone")
    def test_display_datetime(self, timezone_patched):
        saved_time = timezone.now()
        timezone_patched.now.return_value = saved_time
        context = {"dt": saved_time - timedelta(1)}
        rendered = self.render_template("{% load ct_extras %}" "{{ dt|display_datetime }}", context=context)
        self.assertEqual(rendered, "1 day ago")

    def test_find_audio(self):
        result = find_audio("test tag head .. audio:: test tag tail \n", 4)
        self.assertEqual(result, (14, 39, "test tag tail"))

    def test_audio_html(self):
        """
        Function should return string for embeding audio into html.
        """
        result = audio_html("audio.mp3")
        self.assertEqual(
            result,
            """<audio controls><source src="audio.ogg" type="audio/ogg"><source src="audio.mp3" """
            """type="audio/mpeg">no support for audio!</audio>""",
        )

    def test_video_html(self):
        """
        Function should return string for embeding youtube or vimeo link.
        """
        result = video_html("youtube:test_video_path")
        self.assertIn("test_video_path", result)
        self.assertIn('src="https://www.youtube.com/embed/', result)

        result = video_html("vimeo:test_video_path")
        self.assertIn("test_video_path", result)
        self.assertIn('src="https://player.vimeo.com/video/', result)

    def test_video_html_with_exception(self):
        """
        Test exception handling.
        """
        result = video_html("youtube")
        self.assertEqual(result, "ERROR: bad video source: youtube")

        result = video_html("some_new_cdn:test_video_path")
        self.assertEqual(result, "ERROR: unknown video sourceDB: some_new_cdn")

    def test_add_replace_temporary_markers(self):
        """
        Test add_temporary_markers and replace_temporary_markers in tandem.
        """
        result = add_temporary_markers("test tag head .. audio:: test tag tail \n", find_audio)
        self.assertEqual(result, ("test tag head mArKeR:0:\n", [("mArKeR:0:", "test tag tail")]))

        result = replace_temporary_markers(result[0], audio_html, result[1])
        self.assertEqual(
            result,
            """test tag head <audio controls><source src="test tag tail.ogg" type="audio/ogg">"""
            """<source src="test tag tail.mp3" type="audio/mpeg">no support for audio!</audio>\n""",
        )
Example #9
0
    def perform_update(self, serializer):
        chat_id = self.request.data.get('chat_id')
        message = self.get_object()
        node = message.chat.state.fsmNode
        chat = Chat.objects.get(id=chat_id, user=self.request.user)
        activity = chat.state and chat.state.activity

        def is_in_node(node: str) -> bool:
            return message.chat.state.fsmNode.name == node

        # Check if message is not in current chat
        if not message.chat or message.chat != chat:
            return

        # Do procced the user response in the FSMNode
        if hasattr(node._plugin, 'handler'):
            node._plugin.handler(message, chat, self.request,
                                 self.next_handler)
            return

        if is_chat_add_faq(message) and is_in_node('GET_NEW_FAQ'):
            message.text = self.request.data.get('option', 'no')
            message.save()
            chat.last_modify_timestamp = timezone.now()
            chat.save()

        if message.input_type == 'text' and not message.sub_kind == 'add_faq':
            message.chat = chat
            text = self.request.data.get('text')

            if message.lesson_to_answer.sub_kind == Lesson.EQUATION:
                text = text.strip("$")
                text = '.. math:: ' + text
            resp = StudentResponse(text=text)

            # convert base64 attachment string to django File
            data_attachment = self.request.data.get('attachment')
            if data_attachment and data_attachment.startswith('data:image'):
                format, image_string = data_attachment.split(';base64,')
                extension = format.split('/')[-1].split('+')[0]
                name = '{}-{}.{}'.format('canvas', key_secret_generator(),
                                         extension)
                resp.attachment = ContentFile(base64.b64decode(image_string),
                                              name=name)

            if not message.content_id:
                resp.lesson = message.lesson_to_answer.lesson
                resp.unitLesson = message.lesson_to_answer
                resp.course = message.chat.enroll_code.courseUnit.course
                resp.author = self.request.user
                resp.activity = activity
                resp.is_test = chat.is_test
                resp.is_preview = chat.enroll_code.isPreview
                resp.sub_kind = resp.lesson.sub_kind
            else:
                resp = message.content
                resp.text = text
            resp.is_trial = chat.is_trial
            resp.save()
            if not message.timestamp:
                message.content_id = resp.id
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id,
                                timestamp=timezone.now(),
                                chat=chat)
            else:
                serializer.save()

        message_is_response = message.contenttype == 'response'
        lesson_has_sub_kind = message.lesson_to_answer and message.lesson_to_answer.sub_kind
        content_is_not_additional = not message.content and not message.is_additional
        mc_selfeval = None

        if (message_is_response and lesson_has_sub_kind
                and content_is_not_additional) or (
                    message_is_response and message.lesson_to_answer
                    and message.lesson_to_answer.sub_kind == 'choices'
                    and not content_is_not_additional):
            resp_text = ''
            if message.lesson_to_answer.sub_kind == Lesson.MULTIPLE_CHOICES:
                selected_items = self.request.data.get('selected')
                try:
                    selected = selected_items[str(message.id)]['choices']
                except KeyError:
                    # here request.data is like {"option":1,"chat_id":9,"selected":{"116":{"choices":[0]}}}
                    selected_msg_ids = list(
                        self.request.data.get('selected').keys())
                    # selected_messages == tuple with keys of this dict {"116":{"choices":[0]}} - it will be ("116",)
                    msg_ids = Message.objects.filter(id__in=selected_msg_ids,
                                                     chat=chat).values_list(
                                                         'id', flat=True)
                    correct_ids = set(msg_ids).intersection(
                        set(int(i) for i in list(selected_items.keys())))
                    selected_choices = []
                    for i in correct_ids:
                        selected_choices.append(
                            selected_items[str(i)]['choices'])
                    selected = chain(*selected_choices)

                resp_text = '[selected_choices] ' + ' '.join(
                    str(i) for i in selected)

                correct_choices = set([
                    _[0] for _ in
                    message.lesson_to_answer.lesson.get_correct_choices()
                ])
                selected_choices = set([_ for _ in chain(*selected_choices)])

                if not (correct_choices - selected_choices
                        or correct_choices ^ selected_choices):
                    mc_selfeval = StudentResponse.CORRECT
                elif selected_choices & correct_choices:
                    mc_selfeval = StudentResponse.CLOSE
                else:
                    mc_selfeval = StudentResponse.DIFFERENT

            resp = StudentResponse(text=resp_text)
            # tes, preview flags
            resp.is_test = chat.is_test
            resp.selfeval = mc_selfeval or None
            resp.is_preview = chat.enroll_code.isPreview
            resp.is_trial = chat.is_trial

            resp.kind = message.lesson_to_answer.kind
            resp.sub_kind = message.lesson_to_answer.sub_kind
            resp.lesson = message.lesson_to_answer.lesson
            resp.unitLesson = message.lesson_to_answer
            resp.course = message.chat.enroll_code.courseUnit.course
            resp.author = self.request.user
            resp.activity = activity
            resp.save()

            if not message.timestamp:
                serializer.save(content_id=resp.id,
                                timestamp=timezone.now(),
                                chat=chat,
                                response_to_check=resp)
            else:
                serializer.save()
            return
        if (is_in_node('GET_NEW_FAQ_TITLE') or is_in_node('GET_NEW_FAQ_DESCRIPTION')) \
                and message_is_response and message.sub_kind == 'add_faq':
            text = self.request.data.get('text')
            faq_request = message.content
            if is_in_node('GET_NEW_FAQ_TITLE'):
                faq_request.title = text
            else:
                faq_request.text = text
            faq_request.save()
            faq_request.notify_instructors()
            message.text = text
            message.save()
        if is_in_node('GET_FOR_FAQ_ANSWER'):
            message.text = self.request.data.get('option', 'help')
            message.save()
        if is_in_node('GET_UNDERSTANDING'):
            message.text = self.request.data.get('option', 'no')
            message.save()
        if message.input_type == 'options' and message.kind != 'button':
            if (message.contenttype == 'uniterror'
                    and 'selected' in self.request.data):
                # user selected error model
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['errorModel']
                except KeyError:
                    selected = []
                uniterror = message.content
                uniterror.save_response(user=self.request.user,
                                        response_list=selected)

                message.text = message.get_html()
                message.save()
                if not message.chat.is_live:
                    get_additional_messages(uniterror.response, chat, selected)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()

                serializer = self.get_serializer(message,
                                                 data=self.request.data)
                serializer.is_valid()
                serializer.save(chat=chat)

            elif (message.kind == 'add_faq' and message.sub_kind == 'add_faq') or \
                 (message.kind == 'get_faq_answer' and message.sub_kind == 'get_faq_answer') or \
                 (message.kind == 'ask_faq_understanding'):
                pass
            elif (message.contenttype == 'unitlesson'
                  and message.kind == 'faqs'
                  and 'selected' in self.request.data):
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['faqModel']
                except KeyError:
                    selected = []

                if selected:
                    c_faq_data().update_one(
                        {
                            "chat_id": chat.id,
                            "ul_id": message.content.id
                        }, {
                            "$set": {
                                "faqs": {
                                    str(faq_id): {
                                        'status': {
                                            "done": False
                                        }
                                    }
                                    for faq_id in selected
                                }
                            }
                        })
                # Save presented in message FAQs to avoid futher bugs in wrong dadta selection
                message.text = message.get_html()
                message.save()

                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()

                serializer = self.get_serializer(message,
                                                 data=self.request.data)
                serializer.is_valid()
                serializer.save(chat=chat)
            elif message.contenttype == 'NoneType' and message.kind == 'abort':
                # user selected abort model
                message.chat = chat
                try:
                    selected = self.request.data.get('selected')[str(
                        message.id)]['errorModel']
                except KeyError:
                    selected = []
                if not message.chat.is_live and selected:
                    get_help_messages(chat)
                chat.next_point = self.next_handler.next_point(
                    current=message.content,
                    chat=chat,
                    message=message,
                    request=self.request)
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(chat=chat)
            elif message.content_id and not message.student_error:
                # confidence and selfeval
                message.chat = chat
                opt_data = self.request.data.get('option')
                resp = message.content
                if chat.state and chat.state.fsmNode.node_name_is_one_of(
                        'GET_CONFIDENCE', 'ADDITIONAL_GET_CONFIDENCE'):
                    resp.confidence = opt_data
                    text = resp.get_confidence_display()
                else:
                    resp.selfeval = opt_data
                    text = resp.get_selfeval_display()
                    # FIX if response was correct - user will not go to `else` section and response status should be set
                    if not resp.is_locked:
                        resp.status = EVAL_TO_STATUS_MAP.get(opt_data)

                message.text = text
                resp.save()
                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                serializer.save(content_id=resp.id, chat=chat, text=text)
            else:
                #
                message.chat = chat
                selfeval = self.request.data.get('option')
                resp = message.student_error
                resp.status = selfeval
                resp.save()

                # CRITICAL note - do not override response status
                # pass status to main response ONLY in case of absence the status at all
                # is_locked status is setted in TRANSITION node in chat FSM
                if not resp.response.is_locked:
                    resp.response.status = selfeval
                    resp.response.save()

                chat.next_point = message
                chat.last_modify_timestamp = timezone.now()
                chat.save()
                message.text = selfeval
                message.save()
                serializer.save(text=selfeval, chat=chat)
        if message.kind == 'button' and not (message.content_id
                                             and message.content
                                             and message.content.sub_kind):
            chat.last_modify_timestamp = timezone.now()
            chat.next_point = self.next_handler.next_point(
                current=message.content,
                chat=chat,
                message=message,
                request=self.request,
            )
            chat.save()
Example #10
0
    def setUp(self):
        self.username, self.password = '******', 'test'
        self.user = User.objects.create_user(self.username, '*****@*****.**', self.password)

        self.instructor = Instructor.objects.create(user=self.user, institution='institute',
                                                    what_do_you_teach='something')

        self.username2, self.password2 = 'test1', 'test'
        self.user2 = User.objects.create_user(self.username2, '*****@*****.**', self.password2)
        self.instructor2 = Instructor.objects.create(user=self.user2, institution='institute',
                                                     what_do_you_teach='something')

        self.unit = Unit(title='Test title', addedBy=self.user)
        self.unit.save()
        self.course = Course(title='Test title',
                             description='test description',
                             access='Public',
                             enrollCode='111',
                             lockout='222',
                             addedBy=self.user)
        self.course.save()

        self.courseunit = CourseUnit(
            unit=self.unit, course=self.course,
            order=0, addedBy=self.user, releaseTime=timezone.now()
        )
        self.courseunit.save()
        self.lesson = Lesson(title='title', text='text', addedBy=self.user)
        self.lesson.save()
        self.unitlesson = UnitLesson(
            unit=self.unit, order=0,
            lesson=self.lesson, addedBy=self.user,
            treeID=self.lesson.id
        )
        self.unitlesson.save()

        self.resp1 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may respond",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp1.save()

        self.resp2 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may be responded 2",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp2.save()
        self.default_data = {}

        self.client.login(username=self.username, password=self.password)
        self.url = reverse('ctms:course_settings', kwargs={'pk': self.course.id})
Example #11
0
class MyTestCase(TestCase):
    models_to_check = tuple()
    context_should_contain_keys = tuple()

    def setUp(self):
        self.username, self.password = '******', 'test'
        self.user = User.objects.create_user(self.username, '*****@*****.**', self.password)

        self.instructor = Instructor.objects.create(user=self.user, institution='institute',
                                                    what_do_you_teach='something')

        self.username2, self.password2 = 'test1', 'test'
        self.user2 = User.objects.create_user(self.username2, '*****@*****.**', self.password2)
        self.instructor2 = Instructor.objects.create(user=self.user2, institution='institute',
                                                     what_do_you_teach='something')

        self.unit = Unit(title='Test title', addedBy=self.user)
        self.unit.save()
        self.course = Course(title='Test title',
                             description='test description',
                             access='Public',
                             enrollCode='111',
                             lockout='222',
                             addedBy=self.user)
        self.course.save()

        self.courseunit = CourseUnit(
            unit=self.unit, course=self.course,
            order=0, addedBy=self.user, releaseTime=timezone.now()
        )
        self.courseunit.save()
        self.lesson = Lesson(title='title', text='text', addedBy=self.user)
        self.lesson.save()
        self.unitlesson = UnitLesson(
            unit=self.unit, order=0,
            lesson=self.lesson, addedBy=self.user,
            treeID=self.lesson.id
        )
        self.unitlesson.save()

        self.resp1 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may respond",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp1.save()

        self.resp2 = Response(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
            text="Some text user may be responded 2",
            author=self.user,
            status=NEED_HELP_STATUS,
            selfeval=Response.DIFFERENT
        )
        self.resp2.save()
        self.default_data = {}

        self.client.login(username=self.username, password=self.password)
        self.url = reverse('ctms:course_settings', kwargs={'pk': self.course.id})

    def get_page(self):
        return self.client.get(self.url)

    def post_data(self, data={'name': 'some test name'}):
        response = self.client.post(self.url, data, follow=True)
        return response

    def get_client_method(self, method='post'):
        client_method = getattr(self.client, method)
        if not client_method:
            raise KeyError('self.client has no property {}'.format(method))
        return client_method

    def post_valid_data(self, data={'name': 'some test name'}, method='post'):
        client_method = self.get_client_method(method)
        copied_data = {}
        if getattr(self, 'default_data', False):
            copied_data.update(self.default_data)
            copied_data.update(data)
        response = client_method(self.url, copied_data, follow=True)
        return response

    def post_invalid_data(self, data={'name': ''}, method='post'):
        client_method = self.get_client_method(method)
        copied_data = {}
        if getattr(self, 'default_data', False):
            copied_data.update(self.default_data)
            copied_data.update(data)
        response = client_method(self.url, copied_data, follow=True)
        return response

    def get_my_courses(self):
        return Course.objects.filter(addedBy=self.user)

    def get_test_course(self):
        return Course.objects.get(id=self.course.id)

    def get_test_unitlessons(self):
        return self.courseunit.unit.unitlesson_set.filter(
            kind=UnitLesson.COMPONENT,
            order__isnull=False
        ).order_by('order').annotate(
            responses_count=models.Count('response')
        )

    def get_test_unitlesson(self):
        return self.courseunit.unit.unitlesson_set.filter(
            kind=UnitLesson.COMPONENT,
            order__isnull=False
        ).order_by('order').annotate(
            responses_count=models.Count('response')
        )[0]

    get_test_courslet = get_test_unitlesson

    get_test_response = lambda self: self.get_test_responses()[0]

    def get_test_courseunit(self):
        return CourseUnit.objects.get(id=self.courseunit.id)

    def get_test_responses(self):
        return Response.objects.filter(
            unitLesson=self.unitlesson,
            kind=Response.ORCT_RESPONSE,
            lesson=self.lesson,
            course=self.course,
        )

    def get_model_counts(self, **kwargs):
        if isinstance(self.models_to_check, (list, tuple)):
            return {model: model.objects.filter().count() for model in self.models_to_check}
        return {self.models_to_check: self.models_to_check.objects.filter().count()}

    def validate_model_counts(self, first_counts, second_counts, must_equal=False):
        if isinstance(self.models_to_check, (list, tuple)):
            all_models = self.models_to_check
        else:
            all_models = [self.models_to_check]

        for model in all_models:
            if must_equal:
                self.assertEqual(
                    first_counts[model], second_counts[model],
                    "{} ({}) != {} ({}), with must_equal={}".format(
                        model, first_counts[model], model, second_counts[model], must_equal
                    )
                )
            else:
                self.assertNotEqual(
                    first_counts[model], second_counts[model],
                    "{} ({}) == {} ({}), with must_equal={}".format(
                        model, first_counts[model], model, second_counts[model], must_equal
                    )
                )

    def check_context_keys(self, response):
        for key in self.context_should_contain_keys:
            self.assertIn(key, response.context)

    def am_i_instructor(self, method='GET'):
        methods_map = {'GET', self.client.get, 'POST', self.client.post}
        client_method = methods_map.get(method)
        self.assertIsNotNone(client_method)

        if getattr(self, 'url'):
            if getattr(self, 'NEED_INSTRUCTOR'):
                response = client_method(self.url)
                if getattr(self, 'instructor'):
                    self.assertEqual(response.status_code, 200)
                    self.instructor.delete()
                    response = client_method(self.url)
                    self.assertEqual(response.status_code, 403)
                else:
                    self.assertEqual(response.status_code, 403)
            else:
                response = client_method(self.url)
                self.assertEqual(response.status_code, 200)