Skip to content

Commit

Permalink
fix conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
Rishav Chakraborty committed Jul 18, 2019
2 parents 4641e94 + 0350f08 commit e6d0593
Show file tree
Hide file tree
Showing 61 changed files with 1,990 additions and 1,167 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ jobs:
name: Generate frontend coverage report
command: |
sudo pip install codecov
codecov --file ../karma_coverage_reports/coverage-final.json
codecov --file ../karma_coverage_reports/lcov.info
when: on_success

backend_tests:
Expand Down
22 changes: 11 additions & 11 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -251,19 +251,19 @@
# New structures team.
# Question project.
/core/controllers/practice_sessions*.py @vinitamurthi
/core/controllers/question*.py @aks681
/core/controllers/review_tests*.py @sophiewu6
/core/domain/question*.py @aks681
/core/storage/question/ @aks681
/core/templates/dev/head/components/entity-creation-services/question-creation.service.ts @aks681
/core/controllers/question*.py @aks681 @vinitamurthi
/core/controllers/review_tests*.py @sophiewu6 @vinitamurthi
/core/domain/question*.py @aks681 @vinitamurthi
/core/storage/question/ @aks681 @vinitamurthi
/core/templates/dev/head/components/entity-creation-services/question-creation.service.ts @aks681 @vinitamurthi
/core/templates/dev/head/components/score-ring/ @vinitamurthi
/core/templates/dev/head/domain/question/ @aks681
/core/templates/dev/head/domain/question/ @aks681 @vinitamurthi
/core/templates/dev/head/pages/practice-session-page/ @vinitamurthi
/core/templates/dev/head/pages/review-test-page/ @sophiewu6
/core/templates/dev/head/services/QuestionsListService.ts @sophiewu6
/core/templates/dev/head/components/question-directives/question-editor/ @aks681
/core/templates/dev/head/components/question-directives/questions-list/ @aks681
/core/templates/dev/head/components/question-directives/modal-templates/ @aks681
/core/templates/dev/head/pages/review-test-page/ @sophiewu6 @vinitamurthi
/core/templates/dev/head/services/QuestionsListService.ts @sophiewu6 @vinitamurthi
/core/templates/dev/head/components/question-directives/question-editor/ @aks681 @vinitamurthi
/core/templates/dev/head/components/question-directives/questions-list/ @aks681 @vinitamurthi
/core/templates/dev/head/components/question-directives/modal-templates/ @aks681 @vinitamurthi
/core/templates/dev/head/components/question-directives/question-player/ @vinitamurthi

# Skill project.
Expand Down
52 changes: 41 additions & 11 deletions core/controllers/question_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,27 @@ class QuestionCreationHandler(base.BaseHandler):
"""A handler that creates the question model given a question dict."""

@acl_decorators.can_manage_question_skill_status
def post(self, comma_separated_skill_ids):
def post(self):
"""Handles POST requests."""
skill_ids = comma_separated_skill_ids.split(',')
skill_ids = self.payload.get('skill_ids')

if not skill_ids:
raise self.InvalidInputException(
'skill_ids parameter isn\'t present in the payload')

if len(skill_ids) > constants.MAX_SKILLS_PER_QUESTION:
raise self.InvalidInputException(
'More than %d QuestionSkillLinks for one question '
'is not supported.' % constants.MAX_SKILLS_PER_QUESTION)
try:
for skill_id in skill_ids:
skill_domain.Skill.require_valid_skill_id(skill_id)
except Exception:
raise self.InvalidInputException
except Exception as e:
raise self.InvalidInputException('Skill ID(s) aren\'t valid: ', e)

try:
skill_services.get_multi_skills(skill_ids)
except Exception, e:
except Exception as e:
raise self.PageNotFoundException(e)

question_dict = self.payload.get('question_dict')
Expand All @@ -54,24 +59,49 @@ def post(self, comma_separated_skill_ids):
('question_state_data' not in question_dict) or
('language_code' not in question_dict) or
(question_dict['version'] != 1)):
raise self.InvalidInputException
raise self.InvalidInputException(
'Question Data should contain id, state data, language code, ' +
'and its version should be set as 1')

question_dict['question_state_data_schema_version'] = (
feconf.CURRENT_STATE_SCHEMA_VERSION)
question_dict['id'] = question_services.get_new_question_id()
question_dict['linked_skill_ids'] = skill_ids

try:
question = question_domain.Question.from_dict(question_dict)
except Exception:
raise self.InvalidInputException
except Exception as e:
raise self.InvalidInputException(
'Question structure is invalid:', e)

skill_difficulties = self.payload.get('skill_difficulties')

if not skill_difficulties:
raise self.InvalidInputException(
'skill_difficulties not present in the payload')
if len(skill_ids) != len(skill_difficulties):
raise self.InvalidInputException(
'Skill difficulties don\'t match up with skill IDs')

try:
skill_difficulties = [
float(difficulty) for difficulty in skill_difficulties]
except (ValueError, TypeError):
raise self.InvalidInputException(
'Skill difficulties must be a float value')

if any((
difficulty < 0 or difficulty > 1)
for difficulty in skill_difficulties):
raise self.InvalidInputException(
'Skill difficulties must be between 0 and 1')

question_services.add_question(self.user_id, question)
# TODO(vinitamurthi): Replace DEFAULT_SKILL_DIFFICULTY
# with a value passed from the frontend.
question_services.link_multiple_skills_for_question(
self.user_id,
question.id,
skill_ids,
[constants.DEFAULT_SKILL_DIFFICULTY] * len(skill_ids))
skill_difficulties)

self.values.update({
'question_id': question.id
Expand Down
118 changes: 95 additions & 23 deletions core/controllers/question_editor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ def test_post_with_non_admin_or_topic_manager_email_disallows_access(self):
self.login(self.NEW_USER_EMAIL)
csrf_token = self.get_new_csrf_token()
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id),
{}, csrf_token=csrf_token, expected_status_int=401)
feconf.NEW_QUESTION_URL, {
'skill_ids': [self.skill_id]
}, csrf_token=csrf_token, expected_status_int=401)
self.logout()

def test_post_with_editor_email_does_not_allow_question_creation(self):
Expand All @@ -79,8 +80,9 @@ def test_post_with_editor_email_does_not_allow_question_creation(self):
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id]
}, csrf_token=csrf_token, expected_status_int=401)
self.logout()

Expand All @@ -89,26 +91,37 @@ def test_post_with_incorrect_skill_id_returns_404(self):
csrf_token = self.get_new_csrf_token()
incorrect_skill_id = 'abc123456789'
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, incorrect_skill_id),
{}, csrf_token=csrf_token, expected_status_int=404)
feconf.NEW_QUESTION_URL, {
'skill_ids': [incorrect_skill_id]
}, csrf_token=csrf_token, expected_status_int=404)
self.logout()

def test_post_with_no_skill_ids_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
self.post_json(
feconf.NEW_QUESTION_URL, {},
csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_incorrect_list_of_skill_ids_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
incorrect_skill_id = [1, 2]
incorrect_skill_ids = [1, 2]
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, incorrect_skill_id),
{}, csrf_token=csrf_token, expected_status_int=400)
feconf.NEW_QUESTION_URL, {
'skill_ids': incorrect_skill_ids
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_incorrect_type_of_skill_ids_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
incorrect_skill_id = 1
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, incorrect_skill_id),
{}, csrf_token=csrf_token, expected_status_int=400)
feconf.NEW_QUESTION_URL, {
'skill_ids': [incorrect_skill_id],
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_incorrect_question_id_returns_400(self):
Expand All @@ -117,8 +130,9 @@ def test_post_with_incorrect_question_id_returns_400(self):
question_dict = self.question.to_dict()
question_dict['id'] = 'abc123456789'
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id]
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

Expand All @@ -128,8 +142,60 @@ def test_post_with_incorrect_question_schema_returns_400(self):
question_dict = self.question.to_dict()
del question_dict['question_state_data']['content']
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_no_skill_difficulty_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id]
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_wrong_skill_difficulty_length_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
'skill_difficulties': [0.6, 0.8]
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_invalid_skill_difficulty_type_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
'skill_difficulties': ['test']
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

def test_post_with_invalid_skill_difficulty_value_returns_400(self):
self.login(self.ADMIN_EMAIL)
csrf_token = self.get_new_csrf_token()
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
'skill_difficulties': [2.0]
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

Expand All @@ -139,8 +205,10 @@ def test_post_with_admin_email_allows_question_creation(self):
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
'skill_difficulties': [0.6]
}, csrf_token=csrf_token, expected_status_int=200)
all_models = question_models.QuestionModel.get_all()
questions = [
Expand All @@ -156,8 +224,10 @@ def test_post_with_topic_manager_email_allows_question_creation(self):
question_dict = self.question.to_dict()
question_dict['id'] = None
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
'skill_difficulties': [0.6]
}, csrf_token=csrf_token)
all_models = question_models.QuestionModel.get_all()
questions = [
Expand All @@ -174,8 +244,9 @@ def test_post_with_invalid_question_returns_400_status(self):
question_dict['id'] = None
question_dict['question_state_data'] = 'invalid_question_state_data'
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, self.skill_id), {
'question_dict': question_dict
feconf.NEW_QUESTION_URL, {
'question_dict': question_dict,
'skill_ids': [self.skill_id],
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()

Expand All @@ -184,8 +255,9 @@ def test_post_with_too_many_skills_returns_400(self):
csrf_token = self.get_new_csrf_token()
skill_ids = [1, 2, 3, 4]
self.post_json(
'%s/%s' % (feconf.NEW_QUESTION_URL, skill_ids),
{}, csrf_token=csrf_token, expected_status_int=400)
feconf.NEW_QUESTION_URL, {
'skill_ids': skill_ids
}, csrf_token=csrf_token, expected_status_int=400)
self.logout()


Expand Down
Loading

0 comments on commit e6d0593

Please sign in to comment.