Commit 2a92a140 by David Baumgold

Wrote simple lettuce tests for pdf textbooks

parent 1b945dd6
Feature: Textbooks
Scenario: No textbooks
Given I have opened a new course in Studio
When I go to the textbooks page
Then I should see a message telling me to create a new textbook
Scenario: Create a textbook
Given I have opened a new course in Studio
And I go to the textbooks page
When I click on the New Textbook button
And I name my textbook "Economics"
And I name the first chapter "Chapter 1"
And I click the Upload Asset link for the first chapter
And I upload the textbook "textbook.pdf"
And I wait for "2" seconds
And I save the textbook
Then I should see a textbook named "Economics" with a chapter path containing "/c4x/MITx/999/asset/textbook.pdf"
And I reload the page
Then I should see a textbook named "Economics" with a chapter path containing "/c4x/MITx/999/asset/textbook.pdf"
#pylint: disable=C0111
#pylint: disable=W0621
from lettuce import world, step
from django.conf import settings
import requests
import string
import random
import os
TEST_ROOT = settings.COMMON_TEST_DATA_ROOT
HTTP_PREFIX = "http://localhost:8001"
@step(u'I go to the textbooks page')
def go_to_uploads(_step):
world.click_course_content()
menu_css = 'li.nav-course-courseware-textbooks'
world.css_find(menu_css).click()
@step(u'I should see a message telling me to create a new textbook')
def assert_create_new_textbook_msg(_step):
css = ".wrapper-content .no-textbook-content"
assert world.is_css_present(css)
no_tb = world.css_find(css)
assert "You haven't added any textbooks" in no_tb.text
@step(u'I upload the textbook "([^"]*)"$')
def upload_file(_step, file_name):
file_css = '.upload-dialog input[type=file]'
upload = world.css_find(file_css)
# uploading the file itself
path = os.path.join(TEST_ROOT, 'uploads', file_name)
upload._element.send_keys(os.path.abspath(path))
button_css = ".upload-dialog .action-upload"
world.css_click(button_css)
@step(u'I click (on )?the New Textbook button')
def click_new_textbook(_step, on):
button_css = ".nav-actions .new-button"
button = world.css_find(button_css)
button.click()
@step(u'I name my textbook "([^"]*)"')
def name_textbook(_step, name):
input_css = ".textbook input[name=textbook-name]"
world.css_fill(input_css, name)
@step(u'I name the first chapter "([^"]*)"')
def name_chapter(_step, name):
input_css = ".textbook input.chapter-name"
world.css_fill(input_css, name)
@step(u'I click the Upload Asset link for the first chapter')
def click_upload_asset(_step):
button_css = ".chapter .action-upload"
world.css_click(button_css)
@step(u'I save the textbook')
def save_textbook(_step):
submit_css = "form.edit-textbook button[type=submit]"
world.css_click(submit_css)
@step(u'I should see a textbook named "([^"]*)" with a chapter path containing "([^"]*)"')
def check_textbook(step, textbook_name, chapter_name):
title = world.css_find(".textbook h3.textbook-title")
chapter = world.css_find(".textbook .wrap-textbook p")
assert title.text == textbook_name, "{} != {}".format(title.text, textbook_name)
assert chapter.text == chapter_name, "{} != {}".format(chapter.text, chapter_name)
...@@ -511,7 +511,7 @@ def textbook_index(request, org, course, name): ...@@ -511,7 +511,7 @@ def textbook_index(request, org, course, name):
def create_textbook(request, org, course, name): def create_textbook(request, org, course, name):
location = get_location_and_verify_access(request, org, course, name) location = get_location_and_verify_access(request, org, course, name)
store = get_modulestore(location) store = get_modulestore(location)
course_module = store.get_item(location, depth=3) course_module = store.get_item(location, depth=0)
try: try:
textbook = validate_textbook_json(request.body) textbook = validate_textbook_json(request.body)
...@@ -520,7 +520,13 @@ def create_textbook(request, org, course, name): ...@@ -520,7 +520,13 @@ def create_textbook(request, org, course, name):
if not textbook.get("id"): if not textbook.get("id"):
tids = set(t["id"] for t in course_module.pdf_textbooks if "id" in t) tids = set(t["id"] for t in course_module.pdf_textbooks if "id" in t)
textbook["id"] = assign_textbook_id(textbook, tids) textbook["id"] = assign_textbook_id(textbook, tids)
course_module.pdf_textbooks.append(textbook) existing = course_module.pdf_textbooks
existing.append(textbook)
course_module.pdf_textbooks = existing
if not any(tab['type'] == 'pdf_textbooks' for tab in course_module.tabs):
tabs = course_module.tabs
tabs.append({"type": "pdf_textbooks"})
course_module.tabs = tabs
store.update_metadata(course_module.location, own_metadata(course_module)) store.update_metadata(course_module.location, own_metadata(course_module))
resp = JsonResponse(textbook, status=201) resp = JsonResponse(textbook, status=201)
resp["Location"] = reverse("textbook_by_id", kwargs={ resp["Location"] = reverse("textbook_by_id", kwargs={
......
...@@ -227,12 +227,16 @@ CMS.Views.EditChapter = Backbone.View.extend({ ...@@ -227,12 +227,16 @@ CMS.Views.EditChapter = Backbone.View.extend({
}, },
changeName: function(e) { changeName: function(e) {
if(e && e.preventDefault) { e.preventDefault(); } if(e && e.preventDefault) { e.preventDefault(); }
this.model.set("name", this.$(".chapter-name").val()); this.model.set({
name: this.$(".chapter-name").val()
}, {silent: true});
return this; return this;
}, },
changeAssetPath: function(e) { changeAssetPath: function(e) {
if(e && e.preventDefault) { e.preventDefault(); } if(e && e.preventDefault) { e.preventDefault(); }
this.model.set("asset_path", this.$(".chapter-asset-path").val()); this.model.set({
asset_path: this.$(".chapter-asset-path").val()
}, {silent: true});
return this; return this;
}, },
removeChapter: function(e) { removeChapter: function(e) {
......
...@@ -69,24 +69,24 @@ def css_click(css_selector, index=0, max_attempts=5, success_condition=lambda: T ...@@ -69,24 +69,24 @@ def css_click(css_selector, index=0, max_attempts=5, success_condition=lambda: T
This function will return True if the click worked (taking into account both errors and the optional This function will return True if the click worked (taking into account both errors and the optional
success_condition). success_condition).
""" """
assert is_css_present(css_selector) assert is_css_present(css_selector), "{} is not present".format(css_selector)
attempt = 0 attempt = 0
result = False result = False
while attempt < max_attempts: for attempt in range(max_attempts):
try: try:
world.css_find(css_selector)[index].click() world.css_find(css_selector)[index].click()
if success_condition(): if success_condition():
result = True return
break
except WebDriverException: except WebDriverException:
# Occasionally, MathJax or other JavaScript can cover up # Occasionally, MathJax or other JavaScript can cover up
# an element temporarily. # an element temporarily.
# If this happens, wait a second, then try again # If this happens, wait a second, then try again
world.wait(1) world.wait(1)
attempt += 1
except: except:
attempt += 1 pass
return result else:
# try once more, letting execptions raise
world.css_find(css_selector)[index].click()
@world.absorb @world.absorb
...@@ -101,24 +101,24 @@ def css_check(css_selector, index=0, max_attempts=5, success_condition=lambda: T ...@@ -101,24 +101,24 @@ def css_check(css_selector, index=0, max_attempts=5, success_condition=lambda: T
This function will return True if the check worked (taking into account both errors and the optional This function will return True if the check worked (taking into account both errors and the optional
success_condition). success_condition).
""" """
assert is_css_present(css_selector) assert is_css_present(css_selector), "{} is not present".format(css_selector)
attempt = 0 attempt = 0
result = False result = False
while attempt < max_attempts: for attempt in range(max_attempts):
try: try:
world.css_find(css_selector)[index].check() world.css_find(css_selector)[index].check()
if success_condition(): if success_condition():
result = True return
break
except WebDriverException: except WebDriverException:
# Occasionally, MathJax or other JavaScript can cover up # Occasionally, MathJax or other JavaScript can cover up
# an element temporarily. # an element temporarily.
# If this happens, wait a second, then try again # If this happens, wait a second, then try again
world.wait(1) world.wait(1)
attempt += 1
except: except:
attempt += 1 pass
return result else:
# try once more, letting exceptions raise
world.css_find(css_selector)[index].check()
@world.absorb @world.absorb
...@@ -143,7 +143,7 @@ def id_click(elem_id): ...@@ -143,7 +143,7 @@ def id_click(elem_id):
@world.absorb @world.absorb
def css_fill(css_selector, text): def css_fill(css_selector, text):
assert is_css_present(css_selector) assert is_css_present(css_selector), "{} is not present".format(css_selector)
world.browser.find_by_css(css_selector).first.fill(text) world.browser.find_by_css(css_selector).first.fill(text)
...@@ -184,7 +184,7 @@ def css_html(css_selector, index=0, max_attempts=5): ...@@ -184,7 +184,7 @@ def css_html(css_selector, index=0, max_attempts=5):
@world.absorb @world.absorb
def css_visible(css_selector): def css_visible(css_selector):
assert is_css_present(css_selector) assert is_css_present(css_selector), "{} is not present".format(css_selector)
return world.browser.find_by_css(css_selector).visible return world.browser.find_by_css(css_selector).visible
...@@ -203,11 +203,15 @@ def dialogs_closed(): ...@@ -203,11 +203,15 @@ def dialogs_closed():
def save_the_html(path='/tmp'): def save_the_html(path='/tmp'):
url = world.browser.url url = world.browser.url
html = world.browser.html.encode('ascii', 'ignore') html = world.browser.html.encode('ascii', 'ignore')
filename = '%s.html' % quote_plus(url) filename = "{path}/{name}.html".format(path=path, name=quote_plus(url))
file = open('%s/%s' % (path, filename), 'w') with open(filename, "w") as f:
file.write(html) f.write(html)
file.close()
@world.absorb
def click_course_content():
course_content_css = 'li.nav-course-courseware'
if world.browser.is_element_present_by_css(course_content_css):
world.css_click(course_content_css)
@world.absorb @world.absorb
def click_course_settings(): def click_course_settings():
......
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