Commit a03f6c3b by cahrens

More Selenium test, code cleanup.

parent dc89a4b3
...@@ -5,9 +5,8 @@ Feature: Course checklists ...@@ -5,9 +5,8 @@ Feature: Course checklists
When I select Checklists from the Tools menu When I select Checklists from the Tools menu
Then I see the four default edX checklists Then I see the four default edX checklists
Scenario: A course author can mark tasks as complete Scenario: A course author can mark tasks as complete
Given I have opened a new course in Studio Given I have opened a new course in Studio
When I select Checklists from the Tools menu When I select Checklists from the Tools menu
Then I can select tasks in a checklist Then I can check and uncheck tasks in a checklist
And They are still selected after I reload the page And They are correctly selected after I reload the page
\ No newline at end of file \ No newline at end of file
...@@ -22,14 +22,43 @@ def i_see_default_checklists(step): ...@@ -22,14 +22,43 @@ def i_see_default_checklists(step):
assert_true(checklists[3].text.endswith('Draft your Course Introduction')) assert_true(checklists[3].text.endswith('Draft your Course Introduction'))
@step('I can select tasks in a checklist$') @step('I can check and uncheck tasks in a checklist$')
def i_can_select_tasks(step): def i_can_check_and_uncheck_tasks(step):
# Use the 2nd checklist as a reference # Use the 2nd checklist as a reference
assert_equal('0', css_find('#course-checklist1 .status-count').first.text) verifyChecklist2Status(0, 7, 0)
assert_equal('7', css_find('#course-checklist1 .status-amount').first.text) toggleTask(1, 0)
# TODO: check progress bar, select several items and check how things change verifyChecklist2Status(1, 7, 14)
toggleTask(1, 3)
verifyChecklist2Status(2, 7, 29)
toggleTask(1, 6)
verifyChecklist2Status(3, 7, 43)
toggleTask(1, 3)
verifyChecklist2Status(2, 7, 29)
@step('They are still selected after I reload the page$') @step('They are correctly selected after I reload the page$')
def tasks_still_selected_after_reload(step): def tasks_correctly_selected_after_reload(step):
reload_the_page(step) reload_the_page(step)
verifyChecklist2Status(2, 7, 29)
# verify that task 7 is still selected by toggling its checkbox state and making sure that it deselects
toggleTask(1, 6)
verifyChecklist2Status(1, 7, 14)
############### HELPER METHODS ####################
def verifyChecklist2Status(completed, total, percentage):
def verify_count(driver):
try:
statusCount = css_find('#course-checklist1 .status-count').first
return statusCount.text == str(completed)
except StaleElementReferenceException:
return False
wait_for(verify_count)
assert_equal(str(total), css_find('#course-checklist1 .status-amount').first.text)
# Would like to check the CSS width, but not sure how to do that.
assert_equal(str(percentage), css_find('#course-checklist1 .viz-checklist-status-value .int').first.text)
def toggleTask(checklist, task):
css_click('#course-checklist' + str(checklist) +'-task' + str(task))
\ No newline at end of file
...@@ -1291,6 +1291,11 @@ def course_advanced_updates(request, org, course, name): ...@@ -1291,6 +1291,11 @@ def course_advanced_updates(request, org, course, name):
#@ensure_csrf_cookie what is this cookie? #@ensure_csrf_cookie what is this cookie?
@login_required @login_required
def get_checklists(request, org, course, name): def get_checklists(request, org, course, name):
"""
Send models, views, and html for displaying the course checklists.
org, course, name: Attributes of the Location for the item to edit
"""
location = get_location_and_verify_access(request, org, course, name) location = get_location_and_verify_access(request, org, course, name)
modulestore = get_modulestore(location) modulestore = get_modulestore(location)
...@@ -1303,29 +1308,41 @@ def get_checklists(request, org, course, name): ...@@ -1303,29 +1308,41 @@ def get_checklists(request, org, course, name):
course_module.checklists = template_module.checklists course_module.checklists = template_module.checklists
modulestore.update_metadata(location, own_metadata(course_module)) modulestore.update_metadata(location, own_metadata(course_module))
checklists = course_module.checklists
return render_to_response('checklists.html', return render_to_response('checklists.html',
{ {
'context_course': course_module, 'context_course': course_module,
'checklists' : checklists, 'checklists' : course_module.checklists
'checklists_json' : json.dumps(checklists)
}) })
@login_required @login_required
def update_checklist(request, org, course, name, checklist_index=None): def update_checklist(request, org, course, name, checklist_index=None):
"""
restful CRUD operations on course checklists. The payload is a json rep of
the modified checklist. For PUT or POST requests, the index of the
checklist being modified must be included; the returned payload will
be just that one checklist. For GET requests, the returned payload
is a json representation of the list of all checklists.
org, course, name: Attributes of the Location for the item to edit
"""
location = get_location_and_verify_access(request, org, course, name) location = get_location_and_verify_access(request, org, course, name)
modulestore = get_modulestore(location) modulestore = get_modulestore(location)
course_module = modulestore.get_item(location) course_module = modulestore.get_item(location)
real_method = get_request_method(request) real_method = get_request_method(request)
if checklist_index is not None and (real_method == 'POST' or real_method == 'PUT'): if real_method == 'POST' or real_method == 'PUT':
if checklist_index is not None and 0 <= int(checklist_index) < len(course_module.checklists):
modified_checklist = json.loads(request.body) modified_checklist = json.loads(request.body)
course_module.checklists[int(checklist_index)] = modified_checklist course_module.checklists[int(checklist_index)] = modified_checklist
modulestore.update_metadata(location, own_metadata(course_module)) modulestore.update_metadata(location, own_metadata(course_module))
return HttpResponse(json.dumps(modified_checklist), mimetype="application/json") return HttpResponse(json.dumps(modified_checklist), mimetype="application/json")
else:
return HttpResponseBadRequest("Could not save checklist state because the checklist index was out of range or unspecified.",
content_type="text/plain")
elif request.method == 'GET': elif request.method == 'GET':
# TODO: Would we ever get in this condition? Any point in having this code? # In the JavaScript view initialize method, we do a fetch to get all the checklists.
return HttpResponse(json.dumps(course_module.checklists), mimetype="application/json") return HttpResponse(json.dumps(course_module.checklists), mimetype="application/json")
...@@ -1594,7 +1611,12 @@ def render_404(request): ...@@ -1594,7 +1611,12 @@ def render_404(request):
def render_500(request): def render_500(request):
return HttpResponseServerError(render_to_string('500.html', {})) return HttpResponseServerError(render_to_string('500.html', {}))
def get_location_and_verify_access(request, org, course, name): def get_location_and_verify_access(request, org, course, name):
"""
Create the location tuple verify that the user has permissions
to view the location.
"""
location = ['i4x', org, course, 'course', name] location = ['i4x', org, course, 'course', name]
# check that logged in user has permissions to this item # check that logged in user has permissions to this item
...@@ -1603,7 +1625,12 @@ def get_location_and_verify_access(request, org, course, name): ...@@ -1603,7 +1625,12 @@ def get_location_and_verify_access(request, org, course, name):
return location return location
def get_request_method(request): def get_request_method(request):
"""
Using HTTP_X_HTTP_METHOD_OVERRIDE, in the request metadata, determine
what type of request came from the client.
"""
# NB: we're setting Backbone.emulateHTTP to true on the client so everything comes as a post!!! # NB: we're setting Backbone.emulateHTTP to true on the client so everything comes as a post!!!
if request.method == 'POST' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META: if request.method == 'POST' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE'] real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE']
......
// Model for checklists_view.js.
CMS.Models.Checklist = Backbone.Model.extend({ CMS.Models.Checklist = Backbone.Model.extend({
}); });
......
...@@ -10,7 +10,9 @@ CMS.Views.Checklists = Backbone.View.extend({ ...@@ -10,7 +10,9 @@ CMS.Views.Checklists = Backbone.View.extend({
initialize : function() { initialize : function() {
var self = this; var self = this;
// instantiates an editor template for each update in the collection
this.collection.fetch({
complete: function () {
window.templateLoader.loadRemoteTemplate("checklist", window.templateLoader.loadRemoteTemplate("checklist",
"/static/client_templates/checklist.html", "/static/client_templates/checklist.html",
function (raw_template) { function (raw_template) {
...@@ -19,6 +21,10 @@ CMS.Views.Checklists = Backbone.View.extend({ ...@@ -19,6 +21,10 @@ CMS.Views.Checklists = Backbone.View.extend({
} }
); );
}, },
error: CMS.ServerError
}
);
},
render: function() { render: function() {
// catch potential outside call before template loaded // catch potential outside call before template loaded
......
...@@ -13,8 +13,7 @@ ...@@ -13,8 +13,7 @@
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function () { $(document).ready(function () {
// TODO: do a fetch instead of passing text into constructor. var checklistCollection = new CMS.Models.ChecklistCollection();
var checklistCollection = new CMS.Models.ChecklistCollection(${checklists_json | n}, {parse: true});
checklistCollection.url = "${reverse('checklists_updates', kwargs=dict(org=context_course.location.org, course=context_course.location.course, name=context_course.location.name))}"; checklistCollection.url = "${reverse('checklists_updates', kwargs=dict(org=context_course.location.org, course=context_course.location.course, name=context_course.location.name))}";
var editor = new CMS.Views.Checklists({ var editor = new CMS.Views.Checklists({
...@@ -22,8 +21,6 @@ ...@@ -22,8 +21,6 @@
collection: checklistCollection collection: checklistCollection
}); });
editor.render();
}); });
</script> </script>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment