Commit a03f6c3b by cahrens

More Selenium test, code cleanup.

parent dc89a4b3
......@@ -5,9 +5,8 @@ Feature: Course checklists
When I select Checklists from the Tools menu
Then I see the four default edX checklists
Scenario: A course author can mark tasks as complete
Given I have opened a new course in Studio
When I select Checklists from the Tools menu
Then I can select tasks in a checklist
And They are still selected after I reload the page
\ No newline at end of file
Then I can check and uncheck tasks in a checklist
And They are correctly selected after I reload the page
\ No newline at end of file
......@@ -22,14 +22,43 @@ def i_see_default_checklists(step):
assert_true(checklists[3].text.endswith('Draft your Course Introduction'))
@step('I can select tasks in a checklist$')
def i_can_select_tasks(step):
@step('I can check and uncheck tasks in a checklist$')
def i_can_check_and_uncheck_tasks(step):
# Use the 2nd checklist as a reference
assert_equal('0', css_find('#course-checklist1 .status-count').first.text)
assert_equal('7', css_find('#course-checklist1 .status-amount').first.text)
# TODO: check progress bar, select several items and check how things change
verifyChecklist2Status(0, 7, 0)
toggleTask(1, 0)
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$')
def tasks_still_selected_after_reload(step):
@step('They are correctly selected after I reload the page$')
def tasks_correctly_selected_after_reload(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):
#@ensure_csrf_cookie what is this cookie?
@login_required
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)
modulestore = get_modulestore(location)
......@@ -1303,29 +1308,41 @@ def get_checklists(request, org, course, name):
course_module.checklists = template_module.checklists
modulestore.update_metadata(location, own_metadata(course_module))
checklists = course_module.checklists
return render_to_response('checklists.html',
{
'context_course': course_module,
'checklists' : checklists,
'checklists_json' : json.dumps(checklists)
'checklists' : course_module.checklists
})
@login_required
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)
modulestore = get_modulestore(location)
course_module = modulestore.get_item(location)
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)
course_module.checklists[int(checklist_index)] = modified_checklist
modulestore.update_metadata(location, own_metadata(course_module))
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':
# 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")
......@@ -1594,7 +1611,12 @@ def render_404(request):
def render_500(request):
return HttpResponseServerError(render_to_string('500.html', {}))
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]
# check that logged in user has permissions to this item
......@@ -1603,7 +1625,12 @@ def get_location_and_verify_access(request, org, course, name):
return location
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!!!
if request.method == 'POST' and 'HTTP_X_HTTP_METHOD_OVERRIDE' in request.META:
real_method = request.META['HTTP_X_HTTP_METHOD_OVERRIDE']
......
// Model for checklists_view.js.
CMS.Models.Checklist = Backbone.Model.extend({
});
......
......@@ -10,7 +10,9 @@ CMS.Views.Checklists = Backbone.View.extend({
initialize : function() {
var self = this;
// instantiates an editor template for each update in the collection
this.collection.fetch({
complete: function () {
window.templateLoader.loadRemoteTemplate("checklist",
"/static/client_templates/checklist.html",
function (raw_template) {
......@@ -19,6 +21,10 @@ CMS.Views.Checklists = Backbone.View.extend({
}
);
},
error: CMS.ServerError
}
);
},
render: function() {
// catch potential outside call before template loaded
......
......@@ -13,8 +13,7 @@
<script type="text/javascript">
$(document).ready(function () {
// TODO: do a fetch instead of passing text into constructor.
var checklistCollection = new CMS.Models.ChecklistCollection(${checklists_json | n}, {parse: true});
var checklistCollection = new CMS.Models.ChecklistCollection();
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({
......@@ -22,8 +21,6 @@
collection: checklistCollection
});
editor.render();
});
</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