import glob
import json
import os
import random
from datetime import timedelta

from django.utils import timezone

from authenticate.models import User
from institute.models import InstituteStudent, Institute
from payment.models import UserBalanceHistory, InstituteBalanceHistory, WikiazmaBalanceHistory, QuizPurchase
from plan.models import Environment
from quiz.models import QuizSheet, QuizTemplate, Quiz, QuestionScore, QUIZ_SHEET_STATE_SCORES_PUBLISHED, \
    QUIZ_SHEET_STATE_IN_PROGRESS
from quiz.tests_helper import ENTRANCE_TYPE_API_INVITE, ENTRANCE_TYPE_PUBLIC, ALLOWED_ENTRANCE_TYPES, QUERY_QUESTION
from wikiazma.myTest import MyTestCase


class QuizTest(MyTestCase):

    def setUp(self):
        self.setUpHelpers()
        self.setBaseUser()

        Environment.objects.update(default_max_institutes_per_user=100, default_max_collaborators_per_institute=100)
        self.institute = self.instituteHelper.create_institute(name="unit_test_institute")

        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=60000)

    def tearDown(self):
        files = glob.glob('test_files/*')
        for file in files:
            if not file.endswith(('/image.png', '\image.png', 'fakepng.png', '.pdf')):
                os.remove(file)
        # Corrections.objects.all().delete()
        InstituteStudent.objects.all().delete()
        QuestionScore.objects.all().delete()
        QuizSheet.objects.all().delete()
        Quiz.objects.all().delete()
        QuizTemplate.objects.all().delete()
        Institute.objects.all().delete()
        User.objects.all().delete()

    def test_create_quiz_success(self):
        # default one group
        self.quizHelper.create_quiz_helper(self.institute['id'])
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'])
        # one group
        rule = {'retrievers': [self.quizHelper.referenced_question_retrievers[0]], 'groups': [{'name': 'group1', 'start_at': 0}]}
        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, expected_questions_count=1)

        # two groups
        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1]],
            'groups': [{'name': 'math1', 'start_at': 0}, {'name': 'physics1', 'start_at': 1}]}

        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, expected_questions_count=2)

        # default one group
        self.quizHelper.create_quiz_helper(self.institute['id'])

        # testing two public access_types of REFERENCED_QUESTION type
        # question_bank is also in our institute
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'], public=True, force_clear=True)

        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1]],
            'groups': [{'name': 'math1', 'start_at': 0}]}

        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, expected_questions_count=2)

        # testing two public access_types of REFERENCED_QUESTION type
        # question_bank is not in our institute
        (user2, token2) = self.authenticateHelper.new_user_with_email()
        institute2 = self.instituteHelper.create_institute(name="unit_test_institute2", token=token2)

        self.quizHelper.generate_referenced_question_retrievers(institute2['id'], public=True, force_clear=True, token=token2)

        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1],
                           self.quizHelper.referenced_question_retrievers[2]], 'groups': [{'name': 'math1', 'start_at': 0}]}

        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, expected_questions_count=3)

        # testing three public access_types and two owned access_types of REFERENCED_QUESTION type
        (user2, token2) = self.authenticateHelper.new_user_with_email()
        institute2 = self.instituteHelper.create_institute(name="unit_test_institute2", token=token2)
        self.quizHelper.generate_referenced_question_retrievers(institute2['id'], public=True, force_clear=True, token=token2)

        # three public questions
        retrievers = [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1],
                      self.quizHelper.referenced_question_retrievers[2], ]

        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'], public=False, force_clear=True)
        # two owned questions
        retrievers.append(self.quizHelper.referenced_question_retrievers[0])
        retrievers.append(self.quizHelper.referenced_question_retrievers[1])

        rule = {'retrievers': retrievers, 'groups': [{'name': 'math1', 'start_at': 0}]}

        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, expected_questions_count=5)

    def test_create_quiz_with_query_question_success(self):
        question_bank_id = self.questionbankHelper.create_question_bank(self.institute['id'])

        # one group
        rule = {'retrievers': [
            {"insert_type": QUERY_QUESTION, "count": 5, "positive_score": 2.5, "negative_score": 1.0, "duration": 20.0,
             "question_bank_id": question_bank_id, "tag_filters": [], 'type_filter': None}],
            'groups': [{'name': 'group1', 'start_at': 0}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)

    def test_create_public_exam_success(self):
        rule = self.quizHelper.get_general_rule2(self.institute['id'])
        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, public=True, expected_questions_count=12)

        # TODO change a public exam to private and vice versa
        # subscription_required=True  price=50000
        rule = self.quizHelper.get_general_rule2(self.institute['id'])
        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, public=True, price=50000, expected_questions_count=12)

        # subscription_required=True  price=0
        rule = self.quizHelper.get_general_rule2(self.institute['id'])
        self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule, public=True, price=0, expected_questions_count=12)

        # subscription_required=True price=None  None = 0 Null is the same as 0
        rule = self.quizHelper.get_general_rule2(self.institute['id'])
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False, public=True,
                                                                                         price=None)

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertIn('price', response_data['data']['quiz'], error_message)

    def test_create_public_quiz_success_and_error(self):
        # price=50000
        rule = self.quizHelper.get_general_rule2(self.institute['id'])
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False, public=True,
                                                                                         price=50000)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertIn('price', response_data['data']['quiz'], error_message)
        self.assertEqual(50000, response_data['data']['quiz']['price'], error_message)

        # negative price
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False, public=True,
                                                                                         price=-10000)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Ensure this value is greater than or equal to 0.', response_data['fields']['price'], error_message)

    def test_create_quiz_error(self):
        # long group name error
        question_bank_id = self.questionbankHelper.create_question_bank(self.institute['id'])
        rule = {'retrievers': [
            {"insert_type": QUERY_QUESTION, "count": 5, "positive_score": 2.5, "negative_score": 1.0, "duration": 20.0,
             "question_bank_id": question_bank_id, "tag_filters": [], 'type_filter': None, }],
            'groups': [{'name': MyTestCase.str1000, 'start_at': 0}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)
        self.assertEqual('In each group, name should be at most 1000 characters', response_data['fields']['rule'], error_message)

        # creating an invalid type in questions list
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'])
        self.quizHelper.referenced_question_retrievers[0]['insert_type'] = "invalid_type"

        rule = {'retrievers': [self.quizHelper.referenced_question_retrievers[0]], 'groups': [{'name': 'math1', 'start_at': 0}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('in each retriever, insert_type should be one of REFERENCED_QUESTION, QUERY_QUESTION, EXACT_QUESTION',
                         response_data['fields']['rule'], error_message)

        # creating an invalid id in questions list
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'])
        self.quizHelper.referenced_question_retrievers[1]['question_id'] = "invalid_id"
        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1]],
            'groups': [{'name': 'math1', 'start_at': 0}, {'name': 'physics1', 'start_at': 1}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('invalid_id is not a valid UUID.', response_data['fields']['rule'], error_message)

        # using a non-existing uuid
        self.quizHelper.referenced_question_retrievers[1]['question_id'] = "123e4567-e89b-12d3-a456-426614174000"
        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1]],
            'groups': [{'name': 'math1', 'start_at': 0}, {'name': 'physics1', 'start_at': 1}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Question "123e4567-e89b-12d3-a456-426614174000" not found', response_data['fields']['rule'],
                         error_message)

        # duplicate group name
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'])

        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1]],
            'groups': [{'name': 'math1', 'start_at': 0}, {'name': 'math1', 'start_at': 1}]}
        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)
        self.assertIn('rule', response_data['fields'], error_message)
        self.assertEqual('Duplicate group name "math1"', response_data['fields']['rule'], error_message)

        # using a question that we do not have access to
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'], force_clear=True)

        (user2, token2) = self.authenticateHelper.new_user_with_email()
        institute2 = self.instituteHelper.create_institute(name="unit_test_institute2", token=token2)

        self.quizHelper.generate_referenced_question_retrievers(institute2['id'], force_clear=True, token=token2)

        rule = {
            'retrievers': [self.quizHelper.referenced_question_retrievers[0], self.quizHelper.referenced_question_retrievers[1],
                           self.quizHelper.referenced_question_retrievers[2], ], 'groups': []}

        (response_data, status_code, error_message) = self.quizHelper.create_quiz_helper(self.institute['id'], rule=rule,
                                                                                         expected_questions_count=3,
                                                                                         validate_success=False)
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)

    def test_create_quiz_serializer_error(self):
        # rule without retrievers and groups
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'name': self.quizHelper.new_name(),
                                                                            'rule': json.dumps({}), 'theme': 'dark',
                                                                            "finish_message": 'test'})
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)
        self.assertIn('rule', response_data['fields'], error_message)
        self.assertEqual("valid 'retrievers' was not found in rule. rule must only contain retrievers(list)*, groups(list)*.",
                         response_data['fields']['rule'], error_message)

        # rule without groups
        self.quizHelper.generate_referenced_question_retrievers(self.institute['id'], force_clear=True)
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'name': self.quizHelper.new_name(),
                                                                            'rule': json.dumps({'retrievers': [
                                                                                self.quizHelper.referenced_question_retrievers[
                                                                                    0]]}), 'theme': 'dark',
                                                                            "finish_message": 'test'})
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Some fields are not valid', response_data['message'], error_message)
        self.assertIn('rule', response_data['fields'], error_message)
        self.assertEqual("valid 'groups' was not found in rule. rule must only contain retrievers(list)*, groups(list)*.",
                         response_data['fields']['rule'], error_message)

    def test_edit_quiz_success(self):
        with open('test_files/image.png', 'rb') as fp2:
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], name='test_quiz', public=True, reanswerable=True,
                                                         shuffle_questions=True, shuffle_choices=True,
                                                         single_question_at_a_time=True, poster=fp2, start=timezone.now(),
                                                         end=timezone.now() + timedelta(days=2), duration='01:00:12',
                                                         finish_message='test1', theme='light', description='test')

        with open('test_files/image.png', 'rb') as fp2:
            # ordinary update
            rule = {
                'retrievers': [self.quizHelper.referenced_question_retrievers[0],
                               self.quizHelper.referenced_question_retrievers[1]],
                'groups': [{'name': 'math1', 'start_at': 0}, {'name': 'physics1', 'start_at': 1}]}
            self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='edit_quiz1', public=False, reanswerable=False,
                                             shuffle_questions=False, shuffle_choices=False, single_question_at_a_time=False,
                                             poster=fp2, start=timezone.now(), end=timezone.now() + timedelta(days=1),
                                             duration='02:00:06', finish_message='test123', theme='dark', description='hello',
                                             rule=rule)

        # edit subscription_required=True and price=50000
        self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='edit_quiz2', public=False, reanswerable=True,
                                         shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                         remove_poster=True, price=50000)

        with open('test_files/image.png', 'rb') as fp2:
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], name='edit_quiz3', public=True, reanswerable=True,
                                                         shuffle_questions=True, shuffle_choices=True,
                                                         single_question_at_a_time=True, poster=fp2, price=30000)
            # edit subscription_required=False and  price = 45000
            self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='edit_quiz4', public=False, reanswerable=True,
                                             shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                             remove_poster=True, price=45000)

        # edit without any data (e.g. description)
        self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='edit_quiz5')

        # edit with description=''
        self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='edit_quiz5', description='')

    # TODO more complex edit and delete tests
    # TODO using a deleted exam in page/get and cover and enter, ...
    def test_archive_quiz_success(self):
        # archive public quiz
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True)
        self.quizHelper.archive_quiz_helper(self.institute['id'], quiz_id)

        # archive private quiz
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=False, name='test')
        self.quizHelper.archive_quiz_helper(self.institute['id'], quiz_id)

    def test_archived_quiz_enter_error(self):
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True)
        self.quizHelper.archive_quiz_helper(self.institute['id'], quiz_id)
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })

        # For now, we can still attend archived quizzes
        self.assertEqual(200, status_code, error_message)
        # self.assertEqual(404, status_code, error_message)
        # self.assertEqual('error', response_data['status'], error_message)
        # self.assertEqual('The quiz has been archived', response_data['message'], error_message)

    def test_list_quiz_success(self):
        # creating an active exam
        start = timezone.now() - timedelta(seconds=1)
        end = timezone.now() + timedelta(minutes=3)
        self.quizHelper.create_quiz_helper(self.institute['id'], name='present1', start=start, end=end)

        # creating an active exam without end
        start = timezone.now() - timedelta(seconds=1)
        self.quizHelper.create_quiz_helper(self.institute['id'], name='present2', start=start)

        # creating an active exam without start #12264 after next creation

        # creating an exam that has not yet started
        start = timezone.now() + timedelta(days=7)
        end = timezone.now() + timedelta(days=14)
        # this exam will be modified later
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], name='future__temp', start=start, end=end, public=True)

        # creating an active exam without start #12264
        end = timezone.now() + timedelta(minutes=3)
        self.quizHelper.create_quiz_helper(self.institute['id'], name='present3', end=end)

        # creating an exam that has passed
        start = timezone.now() - timedelta(days=14)
        end = timezone.now() - timedelta(days=7)
        self.quizHelper.create_quiz_helper(self.institute['id'], name='past', start=start, end=end)
        # creating an infinite
        self.quizHelper.create_quiz_helper(self.institute['id'], name='infinite')
        self.quizHelper.edit_quiz_helper(self.institute['id'], quiz_id, name='future')

        # testing created_at_asc sort
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'created_at_asc',
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'include'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(6, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('present1', response_data['data']['quizzes'][0]['name'], error_message)
        self.assertEqual('present2', response_data['data']['quizzes'][1]['name'], error_message)
        self.assertEqual('future', response_data['data']['quizzes'][2]['name'], error_message)
        self.assertEqual('present3', response_data['data']['quizzes'][3]['name'], error_message)
        self.assertEqual('past', response_data['data']['quizzes'][4]['name'], error_message)
        self.assertEqual('infinite', response_data['data']['quizzes'][5]['name'], error_message)

        # testing name_asc sort
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'include'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(6, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('future', response_data['data']['quizzes'][0]['name'], error_message)
        self.assertEqual('infinite', response_data['data']['quizzes'][1]['name'], error_message)
        self.assertEqual('past', response_data['data']['quizzes'][2]['name'], error_message)
        self.assertEqual('present1', response_data['data']['quizzes'][3]['name'], error_message)
        self.assertEqual('present2', response_data['data']['quizzes'][4]['name'], error_message)
        self.assertEqual('present3', response_data['data']['quizzes'][5]['name'], error_message)

        # testing q
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'q': 'fu', 'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'include'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('future', response_data['data']['quizzes'][0]['name'], error_message)

        # testing qid
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'qid': quiz_id, 'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'include'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('future', response_data['data']['quizzes'][0]['name'], error_message)

        # testing expired filter
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'exclude'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(5, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('future', response_data['data']['quizzes'][0]['name'], error_message)
        self.assertEqual('infinite', response_data['data']['quizzes'][1]['name'], error_message)
        self.assertEqual('present1', response_data['data']['quizzes'][2]['name'], error_message)
        self.assertEqual('present2', response_data['data']['quizzes'][3]['name'], error_message)
        self.assertEqual('present3', response_data['data']['quizzes'][4]['name'], error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'expired_filter': 'only'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, len(response_data['data']['quizzes']), error_message)
        self.assertEqual('past', response_data['data']['quizzes'][0]['name'], error_message)
        self.assertEqual(0, response_data['data']['quizzes'][0]['quiz_sheet_count'], error_message)

        # testing quiz_sheet_count
        # entering a quiz twice
        self.quizHelper.basic_enter_quiz_helper(quiz_id=quiz_id)
        quiz_sheet_id = self.quizHelper.basic_enter_quiz_helper(quiz_id=quiz_id)
        # finish one of the exams so that it become scores_published
        self.post_with_token(self.quizHelper.finish, {'quiz_sheet_id': quiz_sheet_id})

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'name_asc',
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'exclude',
                                                                            'expired_filter': 'exclude'})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual(2, response_data['data']['quizzes'][0]['quiz_sheet_count'], error_message)
        self.assertEqual(1, response_data['data']['quizzes'][0]['not_corrected_quiz_sheet_count'], error_message)

        # testing random filters
        filters = ['include', 'exclude', 'only']
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10, 'sort_by': 'created_at_asc',
                                                                            'reanswerable_filter': random.choice(filters),
                                                                            'shuffle_questions_filter': random.choice(filters),
                                                                            'shuffle_choices_filter': random.choice(filters),
                                                                            "single_question_at_a_time_filter": random.choice(
                                                                                filters),
                                                                            'archived_filter': random.choice(filters),
                                                                            'expired_filter': random.choice(filters)})
        self.assertEqual(200, status_code, error_message)

    def test_create_exam_template_success(self):
        with open('test_files/image.png', 'rb') as fp1:
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=True,
                                                         shuffle_questions=True, shuffle_choices=True,
                                                         single_question_at_a_time=True, poster=fp1)

            (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create_quiz_template,
                                                                               {'quiz_id': quiz_id})
            self.assertEqual(200, status_code, error_message)
            self.assertEqual('ok', response_data['status'], error_message)
            self.assertEqual('Successful', response_data['message'], error_message)

    def test_list_and_get_exam_template_success(self):
        # create a private quiz_template
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=False, reanswerable=True,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create_quiz_template,
                                                                           {'quiz_id': quiz_id, })
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        # create a public quiz_template
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=True, shuffle_questions=True,
                                                     shuffle_choices=True, single_question_at_a_time=True)
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create_quiz_template,
                                                                           {'quiz_id': quiz_id, })
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        # get list of my own quiz_templates
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.list_quiz_template,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10,
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'sort_by': 'name_asc',
                                                                            }, application_json=True)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(2, len(response_data['data']['quiz_templates']), error_message)
        self.assertIn('id', response_data['data']['quiz_templates'][0], error_message)

        # simulating admin featured setup for quiz_template market
        quiz_template = QuizTemplate.objects.get(id=response_data['data']['quiz_templates'][0]['id'])
        quiz_template.featured = True
        quiz_template.save()

        # market for quiz_template
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.market_quiz_template,
                                                                           {'context_institute_id': self.institute['id'],
                                                                            'skip': 0, 'take': 10,
                                                                            'reanswerable_filter': 'include',
                                                                            'shuffle_questions_filter': 'include',
                                                                            'shuffle_choices_filter': 'include',
                                                                            "single_question_at_a_time_filter": "include",
                                                                            'archived_filter': 'include',
                                                                            'sort_by': 'name_asc',

                                                                            }, application_json=True)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, len(response_data['data']['quiz_templates']), error_message)
        self.assertIn('id', response_data['data']['quiz_templates'][0], error_message)

        # get quiz_template
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.get_quiz_template, {
            'id': response_data['data']['quiz_templates'][0]['id']}, application_json=True)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('blueprint', response_data['data']['quiz_template'], error_message)

    # this test contains both QueryQuestionObjectById and QueryQuestionListByFiltering inside the default rule attribute
    def test_generate_quiz_sheet_for_institute_student_success(self):
        start = timezone.now()
        end = timezone.now() + timedelta(days=7)
        duration = "01:20:00"

        # with start and end and duration
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], start=start, end=end,
                                                                         duration=duration, )

        # without duration
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], start=start, end=end)

        # without end
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], start=start, duration=duration)

        # without start
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], end=end, duration=duration)

        # without start and duration
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], end=end)

        # without start and end
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], duration=duration)

        # without end and duration
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'], start=start)

        # without start and end and duration
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'])

    def test_gateway_success(self):
        # without token on a public quiz
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True)
        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway, {'quiz_id': quiz_id})
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)

    def test_gateway_by_institute_student_success(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)

        # getting the cover before attend
        quiz_sheet_id, entrance_token = self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'],
                                                                                                         start, end)

        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': entrance_token, })
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertIn('info', response_data['data'], error_message)
        for key in ['state', 'entrance_date', 'allowed_start_at', 'allowed_finish_at', 'duration', 'final_score']:
            self.assertIn(key, response_data['data']['history'][0], error_message)
        self.assertIsNone(response_data['data']['history'][0]['final_score'], error_message)
        for key in ['_questions_sheet', '_solutions_sheet', '_quizee_inputs_sheet', 'questions_sheet', 'quizee_inputs_sheet',
                    'solutions_sheet']:
            self.assertNotIn(key, response_data['data']['history'][0], error_message)

        # getting the cover after attend and before scores_published
        quiz_sheet_id, entrance_token = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                          entrance_type=ENTRANCE_TYPE_API_INVITE, start=start,
                                                                          end=end)

        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': entrance_token, })
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertIn('info', response_data['data'], error_message)
        for key in ['state', 'entrance_date', 'allowed_start_at', 'allowed_finish_at', 'duration', 'final_score']:
            self.assertIn(key, response_data['data']['history'][0], error_message)
        self.assertIsNone(response_data['data']['history'][0]['final_score'], error_message)
        for key in ['_questions_sheet', '_solutions_sheet', '_quizee_inputs_sheet', 'questions_sheet', 'quizee_inputs_sheet',
                    'solutions_sheet']:
            self.assertNotIn(key, response_data['data']['history'][0], error_message)

        # getting gateway after scores_published
        quiz_sheet_id, entrance_token = self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'],
                                                                                                         start, end)

        self.post_without_token(self.quizHelper.finish, {'entrance_token': entrance_token, })

        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': entrance_token, })
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertIn('info', response_data['data'], error_message)
        for key in ['state', 'entrance_date', 'allowed_start_at', 'allowed_finish_at', 'duration', 'final_score']:
            self.assertIn(key, response_data['data']['history'][0], error_message)
        self.assertEqual('0', response_data['data']['history'][0]['final_score'], error_message)
        for key in ['_questions_sheet', '_solutions_sheet', '_quizee_inputs_sheet', 'questions_sheet', 'quizee_inputs_sheet',
                    'solutions_sheet']:
            self.assertNotIn(key, response_data['data']['history'][0], error_message)
        # TODO corrections

    def test_get_gateway_by_institute_student_error(self):
        self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'])

        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': "invalid_entrance_token", })
        self.assertEqual(404, status_code, error_message)
        self.assertEqual('not_found', response_data['status'], error_message)

    def test_gateway_error(self):
        # empty request
        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway, {})
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)

        # test token_quiz_id_quiz_sheet_id_entrance_token_validator
        # sending both token and entrance_token
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.gateway, {'entrance_token': 'a'})
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Only one of these fields should be given: token, entrance_token',
                         response_data['fields']['entrance_token'], error_message)

        # sending both quiz_id and quiz_sheet_id
        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'quiz_id': 'a', 'quiz_sheet_id': 'a'})
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Only one of these fields should be given: quiz_id, quiz_sheet_id',
                         response_data['fields']['quiz_sheet_id'], error_message)

        # sending both entrance_token and quiz_sheet_id
        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': 'a', 'quiz_sheet_id': 'a'})
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Only one of these fields should be given: quiz_sheet_id, entrance_token',
                         response_data['fields']['quiz_sheet_id'], error_message)

        # sending both entrance_token and quiz_id
        (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.gateway,
                                                                              {'entrance_token': 'a', 'quiz_id': 'a'})
        self.assertEqual(400, status_code, error_message)
        self.assertEqual('validation_error', response_data['status'], error_message)
        self.assertEqual('Only one of these fields should be given: quiz_id, entrance_token', response_data['fields']['quiz_id'],
                         error_message)

    # TODO also test for public quizzes
    def test_enter_quiz_sheet_by_institute_student_success(self):
        # attending a non-reanswerable quiz in the start and end range
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)
        self.quizHelper.enter_exam_helper(self.institute['id'], start, end, reanswerable=False, single_question_at_a_time=False)

        # attending a renaswerable quiz in the start and end range
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)
        self.quizHelper.enter_exam_helper(self.institute['id'], ENTRANCE_TYPE_API_INVITE, start, end)

        # start and end and duration
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)
        duration = "01:20:00"

        self.quizHelper.enter_exam_helper(self.institute['id'], ENTRANCE_TYPE_API_INVITE, start, end, duration)

        # start
        start = timezone.now() - timedelta(days=7)
        self.quizHelper.enter_exam_helper(self.institute['id'], ENTRANCE_TYPE_API_INVITE, start)

    def test_enter_quiz_sheet_error(self):
        start = timezone.now() + timedelta(days=1)
        end = timezone.now() + timedelta(days=7)

        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            # entering a quiz before its start
            (response_data, status_code, error_message) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                                            start=start, end=end,
                                                                                            validate_success=False)

            self.assertEqual('quiz_not_started', response_data['status'], error_message)
            self.assertEqual('Quiz is not started.', response_data['message'], error_message)

            if entrance_type == ENTRANCE_TYPE_API_INVITE:
                self.assertIn('quiz_sheet', response_data['data'], error_message)
                self.assertIsNotNone(response_data['data']['quiz_sheet']['allowed_start_at'], error_message)
                self.assertNotIn('_questions_sheet', response_data['data']['quiz_sheet'], error_message)
                self.assertNotIn('_solutions_sheet', response_data['data']['quiz_sheet'], error_message)
                self.assertNotIn('_quizee_inputs_sheet', response_data['data']['quiz_sheet'], error_message)

                # If the quiz_sheet was started but the quiz was not started, we should be able to enter.
                # quiz_sheet values override quiz values
                quiz_sheet = QuizSheet.objects.get(pk=response_data['data']['quiz_sheet']['referer_id'])
                quiz_sheet.allowed_start_at = timezone.now() - timedelta(days=1)
                quiz_sheet.save()

                (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.enter, {
                    'entrance_token': quiz_sheet.entrance_token, })

                self.assertEqual('ok', response_data['status'], error_message)
            else:
                self.assertIn('quiz', response_data['data'], error_message)
                self.assertIsNotNone(response_data['data']['quiz']['start'], error_message)
                self.assertNotIn('_blueprint', response_data['data']['quiz'], error_message)
                self.assertIsNone(response_data['data']['quiz']['blueprint'], error_message)
            self.assertNotIn('corrections', response_data['data'], error_message)

    def test_enter_quiz_after_allowed_finish_at_error(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() - timedelta(days=4)
        # 6735673855
        # entering an exam after its end
        (response_data, status_code, error_message) = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                                        ENTRANCE_TYPE_API_INVITE, start, end,
                                                                                        validate_success=False)

        self.assertEqual('quiz_ended', response_data['status'], error_message)
        self.assertEqual('Quiz has ended.', response_data['message'], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheet']['allowed_finish_at'], error_message)
        self.assertNotIn('final_score', response_data['data']['quiz_sheet'], error_message)
        self.assertNotIn('generated_exam', response_data['data']['quiz_sheet'], error_message)
        self.assertNotIn('user_inputs', response_data['data']['quiz_sheet'], error_message)
        self.assertNotIn('corrections', response_data['data'], error_message)

    def test_set_answer_for_a_reanswerableable_quiz_sheet_success(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)

        duration = "01:20:00"

        # attending an exam in the start and end range
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            (quiz_sheet_id, entrance_token) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                                reanswerable=True,
                                                                                single_question_at_a_time=False, start=start,
                                                                                end=end, duration=duration, )

            # set the first answer
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']}]),
                                              quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # TODO check the answer_text in the database

            # re set the first answer
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']}]),
                                              quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # TODO check the answer_text in the database

            # set all three answers together
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']},
                                                          {'index': 1, 'selected_choices': ['12345674', '12345675']},
                                                          {'index': 2, 'selected_choices': ['12345674', '12345675']}]),
                                              quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

            self.assertEqual(3, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            QuizSheet.objects.all().delete()

        # TODO check the answer_text in the database

    def test_set_answer_for_a_descriptive_quiz_sheet_success(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)

        duration = "01:20:00"

        rule = self.quizHelper.get_general_descriptive_rule(self.institute['id'])

        # attending an exam in the start and end range
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            (quiz_sheet_id, entrance_token) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                                reanswerable=True, rule=rule,
                                                                                expected_questions_count=12,
                                                                                single_question_at_a_time=False, start=start,
                                                                                end=end, duration=duration, )

            # set the first answer
            self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'answer_text': 'answer_text', 'answer_text_format': 'htmlV1'}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # re set the first answer
            self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'answer_text': 'answer_text', 'answer_text_format': 'htmlV1'}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # set all three answers together
            self.quizHelper.set_answer_helper(json.dumps(
                [{'index': 0, 'answer_text': 'answer_text', 'answer_text_format': 'htmlV1'},
                 {'index': 1, 'answer_text': 'answer_text', 'answer_text_format': 'htmlV1'},
                 {'index': 2, 'answer_text': 'answer_text', 'answer_text_format': 'htmlV1'}]), quiz_sheet_id=quiz_sheet_id,
                entrance_token=entrance_token)

            self.assertEqual(3, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            QuizSheet.objects.all().delete()

    def test_set_answer_for_a_descriptive_quiz_sheet_error(self):
        rule = self.quizHelper.get_general_descriptive_rule(self.institute['id'])

        # attending an exam in the start and end range
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            (quiz_sheet_id, entrance_token) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                                reanswerable=True, rule=rule,
                                                                                expected_questions_count=12)

            # not sending answer_text_format
            response_data, status_code, error_message = self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'answer_text': 'answer_text'}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token, error_400=True, status='validation_error',
                message='Some fields are not valid')

            self.assertEqual('answer_text_format is required for question with index=0', response_data['fields']['user_inputs'],
                             error_message)

            # not sending answer_text
            response_data, status_code, error_message = self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'answer_text_format': 'htmlV1'}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token, error_400=True, status='validation_error',
                message='Some fields are not valid')

            self.assertEqual('answer_text is required for question with index=0', response_data['fields']['user_inputs'],
                             error_message)

            QuizSheet.objects.all().delete()

    def test_set_answer_for_a_not_reanswerableable_quiz_sheet_success_and_error(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)
        # attending an exam in the start and end range
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            quiz_sheet_id, entrance_token = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                              reanswerable=False, single_question_at_a_time=False,
                                                                              start=start, end=end)

            # set the first answer
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']}]),
                                              entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id)

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # re set the first answer
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']}]),
                                              entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id, error_400=True,
                                              message='You cannot answer this question again.')

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

            # set all three answers together
            self.quizHelper.set_answer_helper(json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345675']},
                                                          {'index': 1, 'selected_choices': ['12345674', '12345675']},
                                                          {'index': 2, 'selected_choices': ['12345674', '12345675']}]),
                                              entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id, error_400=True,
                                              message='You cannot answer this question again.')

            self.assertEqual(1, len(QuizSheet.objects.first()._quizee_inputs_sheet))

    def test_set_answer_validation_error(self):
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            (quiz_sheet_id, entrance_token) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type)

            # without user_inputs
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(None,
                                                                                            message='Some fields are not valid',
                                                                                            entrance_token=entrance_token,
                                                                                            quiz_sheet_id=quiz_sheet_id,
                                                                                            error_400=True,
                                                                                            status='validation_error')

            self.assertEqual('This field is required.', response_data['fields']['user_inputs'], error_message)

            # with invalid user_inputs type
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(json.dumps({'a': 'b'}),
                                                                                            message='Some fields are not valid',
                                                                                            entrance_token=entrance_token,
                                                                                            quiz_sheet_id=quiz_sheet_id,
                                                                                            error_400=True,
                                                                                            status='validation_error')

            self.assertEqual('user_inputs should be a list', response_data['fields']['user_inputs'], error_message)

            # with empty user_inputs
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(json.dumps([]),
                                                                                            message='Some fields are not valid',
                                                                                            entrance_token=entrance_token,
                                                                                            quiz_sheet_id=quiz_sheet_id,
                                                                                            error_400=True,
                                                                                            status='validation_error')

            self.assertEqual('At least one user_input is required', response_data['fields']['user_inputs'], error_message)

            # without selected_choices
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(json.dumps([{'index': 0}]),
                                                                                            message='Some fields are not valid',
                                                                                            entrance_token=entrance_token,
                                                                                            quiz_sheet_id=quiz_sheet_id,
                                                                                            error_400=True,
                                                                                            status='validation_error')

            self.assertEqual('selected_choices is required for question with index=0.', response_data['fields']['user_inputs'],
                             error_message)

            # invalid selected_choice type
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'selected_choices': [1, 2]}]), message='Some fields are not valid',
                entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id, error_400=True, status='validation_error')

            self.assertEqual('selected_choices must be a list of strings', response_data['fields']['user_inputs'], error_message)

            # duplicate question index
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'selected_choices': []}, {'index': 0, 'selected_choices': []}]),
                message='Some fields are not valid', entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id, error_400=True,
                status='validation_error')

            self.assertEqual('Duplicate index="0"', response_data['fields']['user_inputs'], error_message)

            # duplicate choice index
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(
                json.dumps([{'index': 0, 'selected_choices': ['12345674', '12345674']}]), message='Some fields are not valid',
                entrance_token=entrance_token, quiz_sheet_id=quiz_sheet_id, error_400=True, status='validation_error')

            self.assertEqual('duplicate choice=12345674 in the list of selected_choices for question_index=0',
                             response_data['fields']['user_inputs'], error_message)

    def test_set_answer_error(self):
        start = timezone.now() - timedelta(days=7)
        end = timezone.now() + timedelta(days=7)
        # attending an exam in the start and end range
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            (quiz_sheet_id, entrance_token) = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                                reanswerable=True,
                                                                                single_question_at_a_time=False, start=start,
                                                                                end=end)

            # without user_inputs
            self.quizHelper.set_answer_helper(user_inputs='effrg', quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token,
                                              error_400=True, message='Some fields are not valid', status='validation_error')

            # without quiz_sheet_id and without token
            request = {'user_inputs': json.dumps([{'index': 0, 'selected_choices': ['1', '2']}])}
            (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.set_answer, request)
            self.assertEqual(400, status_code, error_message)
            self.assertEqual('One of these fields should be given: quiz_id, quiz_sheet_id, entrance_token',
                             response_data['fields']['quiz_id'], error_message)

            # without any token
            if entrance_type is not ENTRANCE_TYPE_PUBLIC:
                self.quizHelper.set_answer_helper(user_inputs=json.dumps([{'index': 0, 'selected_choices': ['1', '2']}, ]),
                                                  quiz_sheet_id=quiz_sheet_id, entrance_token='ss', error_404=True,
                                                  status='not_found', message='No quiz found related to your request.')

            # with invalid question_index
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(
                user_inputs=json.dumps([{'index': 'wrong_question_index', 'selected_choices': ['1', '2']}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token, error_400=True, message='Some fields are not valid',
                status='validation_error')
            self.assertIn("user_inputs", response_data['fields'], error_message)
            self.assertEqual(
                "valid 'index' was not found in one of the items in user_inputs. Each item in user_inputs must only contain index(int)*, answer_text(str), answer_text_format(str), selected_choices(list).",
                response_data['fields']['user_inputs'], error_message)

            # with wrong answer_index
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(
                user_inputs=json.dumps([{'index': 0, 'selected_choices': ['1', '2']}]), quiz_sheet_id=quiz_sheet_id,
                entrance_token=entrance_token, error_400=True, message='Some fields are not valid', status='validation_error')
            self.assertIn("user_inputs", response_data['fields'], error_message)
            self.assertEqual(
                "answer_choice=1 was not found in the list of choices for question_index=0. choices are dict_keys(['12345674', '12345675', '12345676', '12345677', '12345678'])",
                response_data['fields']['user_inputs'], error_message)

            # with number of selected_choices more than max_selectable_choices
            (response_data, status_code, error_message) = self.quizHelper.set_answer_helper(user_inputs=json.dumps(
                [{'index': 0, 'selected_choices': ['12345674', '12345675', '12345676', '12345677', '12345678']}]),
                quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token, error_400=True, message='Some fields are not valid',
                status='validation_error')
            self.assertIn("user_inputs", response_data['fields'], error_message)
            self.assertEqual("max_selectable_choices is 2 but you have selected 3 choices",
                             response_data['fields']['user_inputs'], error_message)

    def test_finish_quiz_sheet_success(self):
        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            # TODO test with empty question groups

            # test with apply_negative_scores=True
            self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'], entrance_type=entrance_type,
                                                             apply_negative_scores=True)

            # test with apply_negative_scores=False
            self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'], entrance_type=entrance_type,
                                                             apply_negative_scores=False, selected_choices=['12345678'])

            # test with shuffle all
            self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'], entrance_type=entrance_type,
                                                             shuffle_questions=True, shuffle_choices=True,
                                                             apply_negative_scores=True)

            # test with only shuffle_questions and reanswerable=False
            self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'], entrance_type=entrance_type,
                                                             shuffle_questions=True, shuffle_choices=False, reanswerable=False,
                                                             apply_negative_scores=True)

    def test_institute_student_finish_quiz_sheet_redirect_url_Successful(self):

        institute = Institute.objects.get(id=self.institute['id'])
        institute.on_exam_finished_redirect_url = "http://google.com"
        institute.save()
        (response_data, status_code, error_message) = self.quizHelper.institute_student_finish_quiz_sheet_helper(
            institute_id=institute.id, shuffle_questions=True, shuffle_choices=False, reanswerable=False)
        self.assertEqual('ok', response_data['status'], error_message)

        institute.on_exam_finished_redirect_url = "http://google.com?"
        institute.save()
        (response_data, status_code, error_message) = self.quizHelper.institute_student_finish_quiz_sheet_helper(
            institute_id=institute.id, shuffle_questions=True, shuffle_choices=False, reanswerable=False)
        self.assertEqual('ok', response_data['status'], error_message)
        institute.on_exam_finished_redirect_url = ""
        institute.save()
        (response_data, status_code, error_message) = self.quizHelper.institute_student_finish_quiz_sheet_helper(
            institute_id=institute.id, shuffle_questions=True, shuffle_choices=False, reanswerable=False)

        self.assertEqual('ok', response_data['status'], error_message)

    def test_get_quiz_cover_success(self):
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=60000)
        # getting an quiz_sheet cover before it is generated
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, price=10000)

        self.quizHelper.get_exam_cover_helper(quiz_sheet_id=None, quiz_id=quiz_id)

        # getting an quiz_sheet cover before attendance
        quiz_sheet_id, entrance_token = self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'])
        self.quizHelper.get_exam_cover_helper(entrance_token=entrance_token)

        for entrance_type in ALLOWED_ENTRANCE_TYPES:
            # getting an quiz_sheet cover before scores_published
            quiz_sheet_id, entrance_token = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type,
                                                                              send_token=True)

            self.quizHelper.get_exam_cover_helper(quiz_sheet_id=quiz_sheet_id, entrance_token=entrance_token)

    def test_quiz_cover_should_fix_invalid_in_progress_state(self):
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=60000)
        # getting an quiz_sheet cover after allowed_finish_at
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=False,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                                     start=timezone.now() - timedelta(days=2),
                                                     end=timezone.now() + timedelta(days=1))

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual('in_progress', response_data['data']['quiz_sheet']['state'], error_message)

        quiz_sheet = QuizSheet.objects.get(referer_id=response_data['data']['quiz_sheet']['referer_id'])
        quiz_sheet.allowed_finish_at = timezone.now() - timedelta(days=4)
        quiz_sheet.save()

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.gateway,
                                                                           {'quiz_sheet_id': quiz_sheet.referer_id})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        #
        self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, response_data['data']['history'][0]['state'], error_message)
        ################################################################################################
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=60000)
        # getting an quiz_sheet cover after entrance_date + duration has passed
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=False,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                                     start=timezone.now(), duration="00:10:00")

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual('in_progress', response_data['data']['quiz_sheet']['state'], error_message)

        quiz_sheet = QuizSheet.objects.get(referer_id=response_data['data']['quiz_sheet']['referer_id'])
        quiz_sheet.allowed_started_at = timezone.now() - timedelta(minutes=20)
        quiz_sheet.entrance_date = timezone.now() - timedelta(minutes=20)
        quiz_sheet.save()

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.gateway,
                                                                           {'quiz_sheet_id': quiz_sheet.referer_id})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, response_data['data']['history'][0]['state'], error_message)

    def test_generate_invoice_success(self):
        # TODO ENTRANCE_TYPE_API_INVITE
        for entrance_type in [ENTRANCE_TYPE_PUBLIC]:
            # get invoice for an exam with price=10000
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'],
                                                         public=True if entrance_type == ENTRANCE_TYPE_PUBLIC else False,
                                                         price=10000)

            self.quizHelper.generate_invoice_helper(quiz_id=quiz_id, expected_total_cost=12208)

            # get invoice for an exam with price=0
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'],
                                                         public=True if entrance_type == ENTRANCE_TYPE_PUBLIC else False, price=0)

            self.quizHelper.generate_invoice_helper(quiz_id=quiz_id, expected_total_cost=1090)

    def test_generate_invoice_error(self):
        # TODO ENTRANCE_TYPE_API_INVITE
        for entrance_type in [ENTRANCE_TYPE_PUBLIC]:
            # get invoice for an exam without token
            quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'],
                                                         public=True if entrance_type == ENTRANCE_TYPE_PUBLIC else False,
                                                         price=10000)

            (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.invoice, {'quiz_id': quiz_id})
            self.assertEqual(401, status_code, error_message)
            self.assertEqual('error', response_data['status'], error_message)

    def test_enter_public_business_error(self):
        # balance is not enough
        # wage and tax will be added to exam price
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=10000)
        (response_data, status_code, error_message) = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                                        entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                        price=10000, validate_success=False,
                                                                                        send_token=True)

        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('balance is not enough', response_data['message'], error_message)
        self.assertEqual(10000, UserBalanceHistory.objects.order_by('created_at').last().remaining_balance, error_message)

        # enter a subscription_required exam without token
        (response_data, status_code, error_message) = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                                        entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                        price=50000, validate_success=False,
                                                                                        send_token=False)

        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Access denied', response_data['message'], error_message)

    def test_enter_public_business_success(self):
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=12208)
        # user does not have any plan
        (response_data, status_code, error_message) = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                                        entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                        price=10000, validate_success=False)

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        last_user_balance = UserBalanceHistory.objects.order_by('created_at').last()
        last_institute_balance = InstituteBalanceHistory.objects.order_by('created_at').last()
        last_wikiazma_balance = WikiazmaBalanceHistory.objects.order_by('created_at').last()

        self.assertEqual(0, last_user_balance.remaining_balance, error_message)
        self.assertEqual(QuizPurchase, last_user_balance.reason, error_message)
        self.assertEqual(10000, last_institute_balance.remaining_balance, error_message)
        self.assertEqual(QuizPurchase, last_institute_balance.reason, error_message)
        self.assertEqual(10000, last_institute_balance.amount, error_message)
        self.assertIsNotNone(last_institute_balance.quiz, error_message)
        self.assertEqual({'quiz_sheet_id': response_data['data']['quiz_sheet']['referer_id']},
                         last_institute_balance.reason_meta_data, error_message)
        # Wikiazma BalanceHistory
        self.assertEqual(2208, last_wikiazma_balance.remaining_balance)
        self.assertEqual(QuizPurchase, last_wikiazma_balance.reason)
        self.assertIsNone(last_wikiazma_balance.institute)
        self.assertIsNotNone(last_wikiazma_balance.user)

        # user buys an exam again
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=30000)
        quiz_sheet_id, entrance_token = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                          entrance_type=ENTRANCE_TYPE_PUBLIC, price=10000)

        last_user_balance = UserBalanceHistory.objects.order_by('created_at').last()
        last_institute_balance = InstituteBalanceHistory.objects.order_by('created_at').last()
        last_wikiazma_balance = WikiazmaBalanceHistory.objects.order_by('created_at').last()

        self.assertEqual(17792, last_user_balance.remaining_balance, error_message)
        self.assertEqual(10000, last_institute_balance.amount, error_message)
        self.assertEqual(20000, last_institute_balance.remaining_balance, error_message)
        # exam tax has been added to wikiazma
        self.assertEqual(4416, last_wikiazma_balance.remaining_balance)

        # user has the exam. So, balance should stay fixed.
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter,
                                                                           {'quiz_sheet_id': quiz_sheet_id, })

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        last_user_balance = UserBalanceHistory.objects.order_by('created_at').last()
        last_institute_balance = InstituteBalanceHistory.objects.order_by('created_at').last()
        last_wikiazma_balance = WikiazmaBalanceHistory.objects.order_by('created_at').last()

        self.assertEqual(17792, last_user_balance.remaining_balance, error_message)
        self.assertEqual(10000, last_institute_balance.amount, error_message)
        self.assertEqual(20000, last_institute_balance.remaining_balance, error_message)
        self.assertEqual(4416, last_wikiazma_balance.remaining_balance)

    def test_get_quiz_sheet_list_success(self):
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=False,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(0, len(response_data['data']['quiz_sheets']), error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(1, len(response_data['data']['quiz_sheets']), error_message)
        for key in ['state', 'final_score', 'duration', 'user', 'institute_student']:
            self.assertIn(key, response_data['data']['quiz_sheets'][0], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheets'][0]['user'], error_message)
        self.assertIsNone(response_data['data']['quiz_sheets'][0]['institute_student'], error_message)
        self.assertEqual('in_progress', response_data['data']['quiz_sheets'][0]['state'], error_message)

        quiz_sheet_id, entrance_token = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                                         entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                         shuffle_questions=True,
                                                                                         shuffle_choices=False,
                                                                                         reanswerable=False)

        quiz_id = QuizSheet.objects.get(referer_id=quiz_sheet_id).quiz.id

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc',
                                                                            'name_filter': 'stfirstna'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(1, len(response_data['data']['quiz_sheets']), error_message)
        for key in ['state', 'final_score', 'duration', 'user', 'institute_student']:
            self.assertIn(key, response_data['data']['quiz_sheets'][0], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheets'][0]['user'], error_message)
        self.assertIsNone(response_data['data']['quiz_sheets'][0]['institute_student'], error_message)
        self.assertEqual('scores_published', response_data['data']['quiz_sheets'][0]['state'], error_message)

        # test non-existence name
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc',
                                                                            'name_filter': 'non-existence'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(0, len(response_data['data']['quiz_sheets']), error_message)

    def test_quiz_sheet_attended_list_and_get_success(self):
        # creating the student user
        (student, student_token) = self.authenticateHelper.new_user_with_email()
        # The balance needed for paying the fees
        UserBalanceHistory.objects.filter(user=student).update(remaining_balance=10000)

        # creating multiple quizzes from multiple institutes for this test
        institute1 = self.instituteHelper.create_institute(name="unit_test_institute1")
        quiz1_id = self.quizHelper.create_quiz_helper(institute1['id'], public=True, reanswerable=False,
                                                      shuffle_questions=True, shuffle_choices=True,
                                                      single_question_at_a_time=True)

        institute2 = self.instituteHelper.create_institute(name="unit_test_institute2")
        quiz2_id = self.quizHelper.create_quiz_helper(institute2['id'], public=True, reanswerable=False,
                                                      shuffle_questions=True, shuffle_choices=True,
                                                      single_question_at_a_time=True)

        # use student's token for next requests
        self.setToken(student_token)

        self.quizHelper.basic_enter_quiz_helper(quiz_id=quiz1_id)
        self.quizHelper.basic_enter_quiz_helper(quiz_id=quiz2_id)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.attended_sheet_list,
                                                                           {'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(2, len(response_data['data']['quiz_sheets']), error_message)

        self.assertNotIn('questions_sheet', response_data['data']['quiz_sheets'][0], error_message)
        self.assertNotIn('quizee_inputs_sheet', response_data['data']['quiz_sheets'][0], error_message)
        self.assertNotIn('solutions_sheet', response_data['data']['quiz_sheets'][0], error_message)
        self.assertIn('quiz', response_data['data']['quiz_sheets'][0], error_message)
        self.assertIn('name', response_data['data']['quiz_sheets'][0]['quiz'], error_message)

        quiz_sheet1_id = response_data['data']['quiz_sheets'][0]['referer_id']

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.attended_sheet_get,
                                                                           {'quiz_sheet_id': quiz_sheet1_id})
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(QUIZ_SHEET_STATE_IN_PROGRESS, response_data['data']['quiz_sheet']['state'], error_message)
        self.assertIsNone(response_data['data']['quiz_sheet']['report_card'], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheet']['questions_sheet'], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheet']['quizee_inputs_sheet'], error_message)
        self.assertIsNone(response_data['data']['quiz_sheet']['solutions_sheet'], error_message)
        self.assertIn('quiz', response_data['data']['quiz_sheet'], error_message)
        self.assertIn('name', response_data['data']['quiz_sheet']['quiz'], error_message)

        # use institutes's token for next requests
        # institute should not have any attended_list
        self.setToken(self.token)

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.attended_sheet_list,
                                                                           {'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertIn('quiz_sheets', response_data['data'], error_message)
        self.assertEqual(0, len(response_data['data']['quiz_sheets']), error_message)

    def test_quiz_sheet_list_should_fix_invalid_in_progress_state(self):
        # The entered quiz will have in_progress state
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=10000000)
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=False,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                                     start=timezone.now() - timedelta(days=2),
                                                     end=timezone.now() + timedelta(days=1))

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual('in_progress', response_data['data']['quiz_sheet']['state'], error_message)

        # we change the end time so that it is passed. When we get the stat(or sheet_list), it should return scores_published state
        quiz_sheet = QuizSheet.objects.get(referer_id=response_data['data']['quiz_sheet']['referer_id'])
        quiz_sheet.allowed_finish_at = timezone.now() - timedelta(days=4)
        quiz_sheet.save()

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        for quiz_sheet in response_data['data']['quiz_sheets']:
            # if the quiz_sheet is auto correctable, it should become QUIZ_SHEET_STATE_SCORES_PUBLISHED
            # self.assertEqual(QUIZ_SHEET_STATE_FINISHED, quiz_sheet['state'], error_message)
            self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, quiz_sheet['state'], error_message)

        ##########################################################################################
        # This test is like the previous one except that we work with start and duration
        UserBalanceHistory.objects.order_by('created_at').update(remaining_balance=10000000)
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=False,
                                                     shuffle_questions=True, shuffle_choices=True, single_question_at_a_time=True,
                                                     start=timezone.now(), duration="00:10:00")

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.enter, {'quiz_id': quiz_id, })
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual('in_progress', response_data['data']['quiz_sheet']['state'], error_message)

        quiz_sheet = QuizSheet.objects.get(referer_id=response_data['data']['quiz_sheet']['referer_id'])
        quiz_sheet.entrance_date = timezone.now() - timedelta(minutes=20)
        quiz_sheet.allowed_start_at = timezone.now() - timedelta(minutes=20)
        quiz_sheet.save()
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.sheet_list,
                                                                           {'quiz_id': quiz_id, 'skip': 0, 'take': 10,
                                                                            'sort_by': 'entrance_date_asc'})

        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        for quiz_sheet in response_data['data']['quiz_sheets']:
            # if the quiz_sheet is auto correctable, it should become QUIZ_SHEET_STATE_SCORES_PUBLISHED
            # self.assertEqual(QUIZ_SHEET_STATE_FINISHED, quiz_sheet['state'], error_message)
            self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, quiz_sheet['state'], error_message)

    # def test_pause_exam_error_and_success(self):
    #
    #     for entrance_type in ALLOWED_ENTRANCE_TYPES:
    #
    #         public_id = None
    #         entrance_token = None
    #
    #         if entrance_type == ENTRANCE_TYPE_PUBLIC:
    #             exam_id, public_id = self.quizHelper.create_exam_helper(
    #                 self.institute['id'], public=True)
    #         elif entrance_type == ENTRANCE_TYPE_API_INVITE:
    #             exam_page_id = self.quizHelper.generate_quiz_sheet_for_institute_student_helper(
    #                 self.institute['id'])
    #             exam_id = QuizSheet.objects.get(id=exam_page_id).exam_id
    #
    #         else:
    #             return
    #
    #         self.quizHelper.pause_exam_helper(exam_id, pause=True)
    #
    #         (response_data, status_code, error_message) = self.quizHelper.basic_enter_exam_helper(entrance_type, public_id=public_id,
    #                                                                                               entrance_token=entrance_token)
    #
    #         self.assertEqual(400, status_code, error_message)
    #         self.assertEqual(
    #             'exam_paused', response_data['status'], error_message)
    #         self.assertEqual('The exam has paused',
    #                          response_data['message'], error_message)
    #
    #         self.quizHelper.pause_exam_helper(exam_id, pause=False)
    #
    #         (response_data, status_code, error_message) = self.quizHelper.basic_enter_exam_helper(entrance_type, public_id=public_id,
    #                                                                                               entrance_token=entrance_token)
    #         self.assertEqual(200, status_code, error_message)
    #         self.assertEqual('ok', response_data['status'], error_message)
    #         self.assertEqual(
    #             'Successful', response_data['message'], error_message)

    # def test_extend_exam_page(self):
    #
    #     for entrance_type in [ENTRANCE_TYPE_PUBLIC, ENTRANCE_TYPE_API_INVITE]:
    #
    #         public_id = None
    #         entrance_token = None
    #
    #         if entrance_type == ENTRANCE_TYPE_PUBLIC:
    #             exam_id, public_id = self.quizHelper.create_exam_helper(self.institute['id'], public=True, duration='02:00:00',
    #                                                                     start=timezone.now(),
    #                                                                     end=timezone.now() + timedelta(hours=10))
    #         elif entrance_type == ENTRANCE_TYPE_API_INVITE:
    #             exam_page_id = self.quizHelper.generate_quiz_sheet_for_institute_student_helper(self.institute['id'],
    #                                                                                             duration='02:00:00',
    #                                                                                             start=timezone.now(),
    #                                                                                             end=timezone.now() + timedelta(
    #                                                                                                 hours=10))
    #             exam_id = QuizSheet.objects.get(id=exam_page_id).exam_id
    #         else:
    #             return
    #
    #         self.quizHelper.basic_enter_exam_helper(entrance_type, public_id=public_id,
    #                                                 entrance_token=entrance_token)
    #
    #         (response_data, status_code, error_message) = self.quizHelper.extend_exam_page_helper(exam_id=exam_id, duration='03:00:00',
    #                                                                                               start=timezone.now(),
    #                                                                                               end=timezone.now() + timedelta(
    #                                                                                                   hours=10))
    #
    #         self.assertEqual(200, status_code, error_message)
    #         self.assertEqual('ok', response_data['status'], error_message)
    #         self.assertEqual(
    #             'Successful', response_data['message'], error_message)

    def test_edit_exam_template_successful_and_error(self):
        # Create an exam to get ID Quiz
        quiz_id = self.quizHelper.create_quiz_helper(self.institute['id'], public=True, reanswerable=True, shuffle_questions=True,
                                                     shuffle_choices=True, single_question_at_a_time=True)

        # Create an exam_template to get ID exam_template_id
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.create_quiz_template,
                                                                           {'quiz_id': quiz_id, })

        # I edited the name and name and theme and description and duration
        with open('test_files/image.png', 'rb') as fp1:
            (response_data, status_code, error_message) = self.quizHelper.edit_exam_template_helper(self.institute['id'],
                                                                                                    response_data['data'][
                                                                                                        'quiz_template']['id'],
                                                                                                    name='test_new', theme='dark',
                                                                                                    description='test',
                                                                                                    duration='10:00:00',
                                                                                                    poster=fp1)

            self.assertEqual('test_new', response_data['data']['quiz_template']['name'], error_message)
            self.assertEqual('dark', response_data['data']['quiz_template']['theme'], error_message)
            self.assertEqual('test', response_data['data']['quiz_template']['description'], error_message)
            self.assertEqual('10:00:00', response_data['data']['quiz_template']['duration'], error_message)
            self.assertIsNotNone(response_data['data']['quiz_template']['poster'], error_message)
            self.assertEqual(200, status_code, error_message)
            self.assertEqual('ok', response_data['status'], error_message)
            self.assertEqual('Successful', response_data['message'], error_message)
        (response_data, status_code, error_message) = self.quizHelper.edit_exam_template_helper(self.institute['id'],
                                                                                                response_data['data'][
                                                                                                    'quiz_template']['id'],
                                                                                                name='test_new', theme='dark',
                                                                                                description='test',
                                                                                                duration='10:00:00',
                                                                                                remove_poster=True)

        self.assertEqual('test_new', response_data['data']['quiz_template']['name'], error_message)
        self.assertEqual('dark', response_data['data']['quiz_template']['theme'], error_message)
        self.assertEqual('test', response_data['data']['quiz_template']['description'], error_message)
        self.assertEqual('10:00:00', response_data['data']['quiz_template']['duration'], error_message)
        self.assertIsNone(response_data['data']['quiz_template']['poster'], error_message)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        # exam_template_id deleted is message Forbidden
        (response_data, status_code, error_message) = self.quizHelper.edit_exam_template_helper(self.institute['id'],
                                                                                                '45bf2004-53ef-43a8-a2c5-473190137fd4',
                                                                                                name='test_new', theme='dark',
                                                                                                description='test',
                                                                                                duration='10:00:00')

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Forbidden', response_data['message'], error_message)
        # exam_template_id is valid
        (response_data, status_code, error_message) = self.quizHelper.edit_exam_template_helper(self.institute['id'],
                                                                                                '45bf2004-53ef-43a8-a',
                                                                                                name='test_new', theme='dark',
                                                                                                description='test',
                                                                                                duration='10:00:00')

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)

    # def test_get_exam_page_Successful(self):
    #     exam_page_id, public_id, device_token = self.quizHelper.enter_exam_helper(self.institute['id'],
    #                                                                               entrance_type=ENTRANCE_TYPE_PUBLIC)
    #     (response_data, status_code, error_message) = self.quizHelper.get_exam_page_helper(
    #         exam_page_id=exam_page_id)
    #
    #     self.assertEqual(200, status_code, error_message)
    #     self.assertEqual('ok', response_data['status'], error_message)
    #     self.assertEqual('Successful', response_data['message'], error_message)
    #     self.assertEqual(1, len(response_data['data']), error_message)
    #
    def test_get_quiz_sheet_error(self):

        (response_data, status_code, error_message) = self.quizHelper.get_quiz_sheet_helper(
            quiz_sheet_id='402ebea7-3e10-4c0b-b4e5-3601c1d903b8')

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Forbidden', response_data['message'], error_message)

        (self.non_permitted_user, self.non_permitted_user_token) = self.authenticateHelper.new_user_with_email(
            email="non_permitted_user@nisodynamic.com")

        quiz_sheet_id, device_token = self.quizHelper.enter_exam_helper(self.institute['id'], entrance_type=ENTRANCE_TYPE_PUBLIC)
        request = {'id': quiz_sheet_id}

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.get,
                                                                           request, test_token=self.non_permitted_user_token)

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Forbidden', response_data['message'], error_message)

    def test_get_quiz_sheet_report_successful(self):
        # finished exam correction add
        quiz_sheet_id, entrance_token = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                                         entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                         shuffle_questions=True,
                                                                                         shuffle_choices=False,
                                                                                         reanswerable=False)

        quiz_sheet = QuizSheet.objects.get(referer_id=quiz_sheet_id)
        self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, quiz_sheet.state)

        request = {'quiz_sheet_id': quiz_sheet_id}

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.report, request)

        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        for key in ['entrance_date', 'finished_at', 'final_score', 'report_card']:
            self.assertIn(key, response_data['data']['quiz_sheet'], error_message)
        self.assertIsNotNone(response_data['data']['quiz_sheet']['report_card'], error_message)

    def test_generate_quiz_report_successful(self):
        apply_negative_scores = True
        quiz_id = self.quizHelper.create_quiz_helper(
            self.institute['id'], public=True, shuffle_questions=True,
            apply_negative_scores=apply_negative_scores, shuffle_choices=False, reanswerable=False)

        # generate_quiz_report without any quiz_sheet
        request = {'quiz_id': quiz_id}
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.generate_quiz_report, request)

        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('No Quiz Sheet found', response_data['message'], error_message)

        # generate_quiz_report with only one quiz_sheet
        # both choices are incorrect
        quiz_sheet_ids = []
        quiz_sheet_id, _ = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'], quiz_id=quiz_id,
                                                                            apply_negative_scores=apply_negative_scores,
                                                                            entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                            selected_choices=['12345674', '12345675'])
        quiz_sheet_ids.append(quiz_sheet_id)

        request = {'quiz_id': quiz_id}

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.generate_quiz_report, request)

        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        report_card = QuizSheet.objects.get(pk=quiz_sheet_id).report_card

        for group in report_card['groups']:
            self.assertLess(-34, group['mean'], error_message)
            self.assertGreaterEqual(100, group['mean'], error_message)
            self.assertEqual(0, group['standard_deviation'], error_message)
            self.assertEqual(0, group['z'], error_message)
            self.assertEqual(5000, group['t'], error_message)
            self.assertEqual(1, group['country_rank'], error_message)
            self.assertEqual(1, group['country_total_students'], error_message)

        self.assertEqual(5000, report_card['overall']['t'], error_message)
        self.assertEqual(1, report_card['overall']['country_rank'], error_message)
        self.assertEqual(1, report_card['overall']['country_total_students'], error_message)

        # generate_quiz_report with two quiz_sheet
        # the choice is correct
        quiz_sheet_id, _ = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                            quiz_id=quiz_id,
                                                                            entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                            selected_choices=['12345678'])
        quiz_sheet_ids.append(quiz_sheet_id)

        request = {'quiz_id': quiz_id}

        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.generate_quiz_report, request)

        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        expected_tanks = [2, 1]
        for index, quiz_sheet_id in enumerate(quiz_sheet_ids):
            report_card = QuizSheet.objects.get(pk=quiz_sheet_id).report_card

            for group in report_card['groups']:
                self.assertLess(-34, group['mean'], error_message)
                self.assertGreaterEqual(100, group['mean'], error_message)
                self.assertNotEqual(0, group['standard_deviation'], error_message)
                self.assertNotEqual(0, group['z'], error_message)
                self.assertNotEqual(5000, group['t'], error_message)
                self.assertEqual(expected_tanks[index], group['country_rank'], error_message)
                self.assertEqual(2, group['country_total_students'], error_message)

            self.assertNotEqual(5000, report_card['overall']['t'], error_message)
            self.assertEqual(expected_tanks[index], report_card['overall']['country_rank'], error_message)
            self.assertEqual(2, report_card['overall']['country_total_students'], error_message)

    def test_quiz_sheet_correction_add_successful(self):
        # finished exam correction add
        quiz_sheet_id, entrance_token = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                                         entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                         shuffle_questions=True,
                                                                                         shuffle_choices=False,
                                                                                         reanswerable=False)

        quiz_sheet = QuizSheet.objects.get(referer_id=quiz_sheet_id)
        self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, quiz_sheet.state)
        # the auto_corrector adds a correction on exam finish
        self.assertEqual(1, QuestionScore.objects.filter(quiz_sheet_id=quiz_sheet_id, question_index=0).count())

        (response_data, status_code, error_message) = self.quizHelper.correction_add_helper(quiz_sheet_id=quiz_sheet_id, index=0,
                                                                                            score=2,
                                                                                            comment_for_other_correctors='test',
                                                                                            comment_for_student='test')
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)
        self.assertEqual(1, QuestionScore.objects.filter(quiz_sheet_id=quiz_sheet_id, question_index=0).count(), error_message)
        quiz_sheet = QuizSheet.objects.get(referer_id=quiz_sheet_id)
        self.assertEqual(QUIZ_SHEET_STATE_SCORES_PUBLISHED, quiz_sheet.state, error_message)
        # -----------------------------------------------------------------------
        # without comments and without adding correction for first question
        quiz_sheet_id, entrance_token = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                                         entrance_type=ENTRANCE_TYPE_PUBLIC,
                                                                                         shuffle_questions=True,
                                                                                         shuffle_choices=False,
                                                                                         reanswerable=False)
        (response_data, status_code, error_message) = self.quizHelper.correction_add_helper(quiz_sheet_id=quiz_sheet_id, index=1,
                                                                                            score=2)
        self.assertEqual(200, status_code, error_message)
        self.assertEqual('ok', response_data['status'], error_message)
        self.assertEqual('Successful', response_data['message'], error_message)

        # the auto_corrector adds a correction on exam finish
        self.assertEqual(1, QuestionScore.objects.filter(quiz_sheet_id=quiz_sheet_id, question_index=0).count(), error_message)
        self.assertEqual(1, QuestionScore.objects.filter(quiz_sheet_id=quiz_sheet_id, question_index=1).count(), error_message)

    def test_quiz_sheet_correction_add_error(self):
        # not finished exam
        quiz_sheet_id, entrance_token = self.quizHelper.enter_exam_helper(self.institute['id'],
                                                                          entrance_type=ENTRANCE_TYPE_PUBLIC)
        (response_data, status_code, error_message) = self.quizHelper.correction_add_helper(quiz_sheet_id=quiz_sheet_id, index=0,
                                                                                            score=2,
                                                                                            comment_for_other_correctors='test',
                                                                                            comment_for_student='test')

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Quiz not finished yet.', response_data['message'], error_message)
        self.assertEqual(0, QuestionScore.objects.filter(quiz_sheet_id=quiz_sheet_id, question_index=0).count(), error_message)

        # finished exam but invalid question_index
        quiz_sheet_id, entrance_token = self.quizHelper.finish_a_quiz_sheet_with_answers(institute_id=self.institute['id'],
                                                                                         selected_choices=['12345678'],
                                                                                         entrance_type=ENTRANCE_TYPE_PUBLIC)

        (response_data, status_code, error_message) = self.quizHelper.correction_add_helper(quiz_sheet_id=quiz_sheet_id, index=10,
                                                                                            score=2)
        self.assertEqual(404, status_code, error_message)
        self.assertEqual('not_found', response_data['status'], error_message)
        self.assertEqual('Question Not Found', response_data['message'], error_message)

        # user permission check
        (self.non_permitted_user, self.non_permitted_user_token) = self.authenticateHelper.new_user_with_email(
            email="non_permitted_user@nisodynamic.com", )
        request = {'quiz_sheet_id': quiz_sheet_id, 'index': 0, 'comment_for_other_correctors': 'test',
                   'comment_for_student': 'test', 'score': 3}
        (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.quiz_sheet_correction_add, request,
                                                                           test_token=self.non_permitted_user_token)

        self.assertEqual(403, status_code, error_message)
        self.assertEqual('error', response_data['status'], error_message)
        self.assertEqual('Forbidden', response_data['message'], error_message)

    # def test_exam_page_correction_publish_Successful(self):
    #     exam_page_id, public_id, device_token = self.quizHelper.finish_an_exam_page_with_answers(institute_id=self.institute['id'],
    #                                                                                              entrance_type=ENTRANCE_TYPE_PUBLIC,
    #                                                                                              shuffle_questions=True,
    #                                                                                              shuffle_choices=False,
    #                                                                                              reanswerable=False)
    #  #     (response_data, status_code, error_message) = self.quizHelper.exam_page_correction_publish_helper(
    #         exam_page_id=exam_page_id)  #     self.assertEqual(200, status_code, error_message)
    #     self.assertEqual('ok', response_data['status'], error_message)
    #     self.assertEqual('Successful', response_data['message'], error_message)
    #     self.assertEqual(['in_progress', 'finished', 'scores_published'], QuizSheet.objects.get(  #         id=exam_page_id).state_history, error_message)  #     exam_page_id, entrance_token, device_token = self.quizHelper.finish_an_exam_page_with_answers(institute_id=self.institute['id'],  #                                                                                                   entrance_type=ENTRANCE_TYPE_API_INVITE,  #                                                                                                   shuffle_questions=True,  #                                                                                                   shuffle_choices=False,  #                                                                                                   reanswerable=False)  #  #     (response_data, status_code, error_message) = self.quizHelper.exam_page_correction_publish_helper(  #         exam_page_id=exam_page_id)  #     self.assertEqual(200, status_code, error_message)
    #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertEqual(['not_attended', 'in_progress', 'finished', 'scores_published'],  #                      QuizSheet.objects.get(id=exam_page_id).state_history, error_message)  #  # def test_exam_page_correction_publish_error(self):  #     exam_page_id, public_id, device_token = self.quizHelper.finish_an_exam_page_with_answers(institute_id=self.institute['id'],  #                                                                                              entrance_type=ENTRANCE_TYPE_PUBLIC,  #                                                                                              shuffle_questions=True,
    #                                                                                              shuffle_choices=False,  #                                                                                              reanswerable=False)  #     (self.non_permitted_user, self.non_permitted_user_token) = self.authenticateHelper.new_user_with_email(
    #         email="non_permitted_user@nisodynamic.com", )  #     request = {'exam_page_id': exam_page_id}  #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.exam_page_correction_publish,
    #                                                                        request, test_token=self.non_permitted_user_token)  #  #     self.assertEqual(403, status_code, error_message)  #     self.assertEqual('error', response_data['status'], error_message)  #     self.assertEqual('Forbidden', response_data['message'], error_message)  #  #     (response_data, status_code, error_message) = self.post_without_token(self.quizHelper.exam_page_correction_publish,  #                                                                           request)  #  #     self.assertEqual(401, status_code, error_message)
    #     self.assertEqual('error', response_data['status'], error_message)  #     self.assertEqual(  #         'Access denied', response_data['message'], error_message)  #  #     exam_page_id, public_id, device_token = self.quizHelper.enter_exam_helper(self.institute['id'],  #                                                                               entrance_type=ENTRANCE_TYPE_PUBLIC)  #  #     (response_data, status_code, error_message) = self.quizHelper.exam_page_correction_publish_helper(
    #         exam_page_id=exam_page_id)  #     self.assertEqual(400, status_code, error_message)
    #     self.assertEqual('error', response_data['status'], error_message)  #     self.assertEqual('BadRequest', response_data['message'], error_message)  #  # def test_attended_exam_list_successful(self):  #     self.quizHelper.finish_an_exam_page_with_answers(institute_id=self.institute['id'],  #                                                      entrance_type=ENTRANCE_TYPE_PUBLIC,  #                                                      shuffle_questions=True,  #                                                      shuffle_choices=False,  #                                                      reanswerable=False)  #  #     institute2 = self.instituteHelper.create_institute(name="konkur")  #     exam_page_id, public_id, device_token = self.quizHelper.finish_an_exam_page_with_answers(institute_id=institute2['id'],  #                                                                                              entrance_type=ENTRANCE_TYPE_PUBLIC,
    #                                                                                              shuffle_questions=True,  #                                                                                              shuffle_choices=False,  #                                                                                              # a name without the letter 'e'  #                                                                                              exam_name='lord',  #                                                                                              reanswerable=False)  #  #     # test without q
    #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.taken_exam_page_list, {  #         'skip': 0,  #         'take': 10  #     })  #     self.assertEqual(200, status_code, error_message)  #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertIn('pages', response_data['data'], error_message)  #     self.assertEqual(2, len(response_data['data']['pages']), error_message)  #  #     # test with a q that will resolve to an exam  #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.taken_exam_page_list, {  #         'skip': 0,  #         'take': 10,  #         # exam name: lord  #         'q': 'lo'  #     })
    #     self.assertEqual(200, status_code, error_message)  #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertIn('pages', response_data['data'], error_message)  #     self.assertEqual(1, len(response_data['data']['pages']), error_message)
    #  #     # test with a q that resolves to an institute  #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.taken_exam_page_list, {  #         'skip': 0,  #         'take': 10,  #         # institute name: konkur  #         'q': 'konkur'  #     })  #     self.assertEqual(200, status_code, error_message)  #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertIn('pages', response_data['data'], error_message)  #     self.assertEqual(1, len(response_data['data']['pages']), error_message)  #  #     # test with a q that resolves to an institute and an exam  #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.taken_exam_page_list, {  #         'skip': 0,  #         'take': 10,  #         # exam name: new_name1  #         # institute name: konkur  #         'q': 'n'  #     })
    #     self.assertEqual(200, status_code, error_message)  #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertIn('pages', response_data['data'], error_message)
    #     self.assertEqual(2, len(response_data['data']['pages']), error_message)  #  #     # test with an available q  #     (response_data, status_code, error_message) = self.post_with_token(self.quizHelper.taken_exam_page_list, {  #         'skip': 0,  #         'take': 10,  #         'q': 'no_exam_or_institute_with_this_name_is_available'  #     })  #     self.assertEqual(200, status_code, error_message)  #     self.assertEqual('ok', response_data['status'], error_message)  #     self.assertEqual('Successful', response_data['message'], error_message)  #     self.assertIn('pages', response_data['data'], error_message)  #     self.assertEqual(0, len(response_data['data']['pages']), error_message)
