-
-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix part of #6550: Write tests for controllers/editor #6849
Conversation
core/controllers/editor.py
Outdated
@@ -468,21 +453,6 @@ def post(self, unused_exploration_id): | |||
}) | |||
|
|||
|
|||
class ExplorationResourcesHandler(EditorHandler): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this handler is used in the front-end. Can anyone confirm this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, we can drop it and drop the corresponding stanza in main.py. Good catch!
practice_sessions.py looks fine to me, LGTM on that! Just one question though, is this test passing? |
@vinitamurthi yes they do. I removed those two conditions as the existence of topics are checked in their respective decorators, hence we don't need to double check it in the controller |
Okay that's great, thanks @lilithxxx ! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm! (from code owner's perspective)
Hi @lilithxxx. Due to recent changes in the "develop" branch, this PR now has a merge conflict. Please follow this link if you need help resolving the conflict, so that the PR can be merged. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM from code owner's perspective. Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, thanks @lilithxxx! Took a pass.
self.login(self.OWNER_EMAIL) | ||
with self.swap(self, 'testapp', self.mock_testapp): | ||
self.get_json( | ||
'/mock/invalid_collection_id', expected_status_int=404) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use a better name than /mock (might be happening in #6782 already though).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
core/controllers/editor.py
Outdated
@@ -271,11 +263,7 @@ def put(self, exploration_id): | |||
|
|||
elif make_community_owned: | |||
exploration = exp_services.get_exploration_by_id(exploration_id) | |||
try: | |||
exploration.validate(strict=True) | |||
except utils.ValidationError as e: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to stay, don't assume old production data is necessarily valid.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the line above, we are using exploration.validate(strict=True)
. Strict means that it will raise an exception from the validate function and hence this line becomes unreachable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it unreachable? The whole point of try/except is to catch an exception, and if a ValidationError is raised then the except clause will be triggered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -214,11 +208,9 @@ def put(self, exploration_id): | |||
except utils.ValidationError as e: | |||
raise self.InvalidInputException(e) | |||
|
|||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why delete?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_user_exploration_data()
's failure cases are handled by its decorator, i.e can_edit_exploration
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see a reference to the ExplorationUserData model there. What if it's just not present for some reason? Should still catch this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But how can I create an exception here? It won't throw an exception if ExplorationUserData model is None -- it will work fine. I think the possible reasons for raising an exception is covered by its decorator.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a line in that function that does:
exp_user_data = user_models.ExplorationUserDataModel.get(
user_id, exploration_id)
What happens if that model instance doesn't exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It returns None and the code below it works fine even if the model is None
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see, thanks for explaining. Yes, what you did sounds fine, then.
core/controllers/editor.py
Outdated
@@ -602,7 +563,7 @@ def get(self, exp_id): | |||
exp_issues = stats_services.get_exp_issues(exp_id, exp_version) | |||
if exp_issues is None: | |||
raise self.PageNotFoundException( | |||
'Invalid exploration ID %s' % (exp_id)) | |||
'Invalid exploration version %s' % (exp_version)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe a more specific error message might be better -- Invalid version %s for exploration ID %s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
core/controllers/editor_test.py
Outdated
(exp_id, feconf.OUTPUT_FORMAT_JSON)) | ||
response = self.get_json(download_url) | ||
|
||
# Check downloaded dict. | ||
self.assertEqual(self.SAMPLE_JSON_CONTENT, response) | ||
|
||
# Check downloading a specific version. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why delete all this? Please don't delete code/tests without explanation. (Ditto above -- I understand those that were deleted because the decorator took care of the check, but everything else needs to be justified.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops a mistake. Reverted it!
core/controllers/editor_test.py
Outdated
'/createhandler/state_rules_stats/%s/invalid_state_name' | ||
% (exp_id), expected_status_int=404) | ||
|
||
self.assertEqual(len(observed_log_messages), 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the following lines read oddly. Why are we only checking one of these?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
core/controllers/editor_test.py
Outdated
response = self.get_html_response('/create/%s' % exp_id) | ||
csrf_token = self.get_csrf_token_from_response(response) | ||
exploration = exp_services.get_exploration_by_id(exp_id) | ||
with self.assertRaisesRegexp( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this (and the following) have something that uses expected_status_int and response['error'], like all the other tests? We don't want to surface 500s to the user.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
core/controllers/editor_test.py
Outdated
response = self.get_html_response( | ||
'%s/%s' % (feconf.EDITOR_URL_PREFIX, exp_id)) | ||
csrf_token = self.get_csrf_token_from_response(response) | ||
with self.assertRaisesRegexp(Exception, 'Invalid message type.'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ditto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
core/controllers/editor_test.py
Outdated
@@ -1475,6 +1874,16 @@ def setUp(self): | |||
}] | |||
) | |||
|
|||
def test_cannot_fetch_issues_with_invalid_version(self): | |||
self.get_json( | |||
'/issuesdatahandler/%s' % (self.EXP_ID), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: No need parens around self.EXP_ID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
@@ -191,7 +191,7 @@ def get(self): | |||
header_i18n_id = feconf.LIBRARY_CATEGORY_TOP_RATED_EXPLORATIONS | |||
|
|||
else: | |||
return self.PageNotFoundException | |||
raise self.PageNotFoundException |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM for changes in main.py (as a codeowner)
Codecov Report
@@ Coverage Diff @@
## develop #6849 +/- ##
===========================================
+ Coverage 95.12% 95.18% +0.05%
===========================================
Files 371 371
Lines 50429 50839 +410
===========================================
+ Hits 47973 48392 +419
+ Misses 2456 2447 -9
Continue to review full report at Codecov.
|
Codecov Report
@@ Coverage Diff @@
## develop #6849 +/- ##
===========================================
+ Coverage 95.5% 95.67% +0.17%
===========================================
Files 371 371
Lines 51058 51285 +227
===========================================
+ Hits 48762 49068 +306
+ Misses 2296 2217 -79
Continue to review full report at Codecov.
|
@seanlip PTAL! |
core/controllers/editor_test.py
Outdated
@@ -762,39 +779,6 @@ def test_record_user_saw_tutorial(self): | |||
self.logout() | |||
|
|||
|
|||
class StateAnswerStatisticsHandlerTests(test_utils.GenericTestBase): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this deleted?
Consider preemptively justifying any deletions in a comment to the review thread, otherwise reviewers will just ask that question during reviews and that will slow things down.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
StateAnswerStatisticsHandlerTests was added in PR #6679. That's why I deleted this duplicate test class
@@ -872,6 +855,10 @@ def _mock_logging_function(msg, *args): | |||
observed_log_messages[0], | |||
'Could not find state: invalid_state_name') | |||
|
|||
self.assertEqual( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might as well replace these three assertions with a single self.assertEqual(observed_log_messages, ...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Please also note #6849 (comment) and #6849 (comment) above. |
@seanlip PTAL! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @lilithxxx! Only one comment left.
core/controllers/editor_test.py
Outdated
@@ -1467,6 +1466,40 @@ def test_transfering_ownership_to_the_community(self): | |||
|
|||
self.logout() | |||
|
|||
def test_cannot_transfer_ownership_to_the_community_with_invalid_lang_code( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"lang code" is a bit specific for what you're actually trying to validate. A developer will read this and wonder "what's so special about the lang code in particular?"
Suggest changing the test name to test_cannot_transfer_ownership_of_invalid_exp_to_the_community(), and adding the following lines in a separate "block" after line 1488:
# The exploration is now invalid.
{{ADD CODE HERE: create the domain object from the model and check that exploration.validate() raises an error.}}
This makes it clearer that what you are really testing is "invalid explorations" and that the language code is just a specific case of that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm I did not understand you completely. I have added a comment to explain that the exploration is now invalid. Is this what you wanted or do I need to add something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I actually meant using get_exploration_from_model to create the corresponding domain object and asserting a validation failure. But I think what you've done works too (in terms of comprehensibility), so let's go with that. Thanks!
@DubeySandeep PTAL as codeowner. Thanks! |
@DubeySandeep PTAL |
/cc @aks681 just flagging this... Needs to be cherrypicked. Thanks! |
Explanation
Fixes part of #6550: Write tests for controllers/editor
Checklist
python scripts/pre_commit_linter.py
andbash scripts/run_frontend_tests.sh
.