Wrote simple lettuce tests for pdf textbooks
This commit is contained in:
20
cms/djangoapps/contentstore/features/textbooks.feature
Normal file
20
cms/djangoapps/contentstore/features/textbooks.feature
Normal file
@@ -0,0 +1,20 @@
|
||||
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"
|
||||
70
cms/djangoapps/contentstore/features/textbooks.py
Normal file
70
cms/djangoapps/contentstore/features/textbooks.py
Normal file
@@ -0,0 +1,70 @@
|
||||
#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):
|
||||
def create_textbook(request, org, course, name):
|
||||
location = get_location_and_verify_access(request, org, course, name)
|
||||
store = get_modulestore(location)
|
||||
course_module = store.get_item(location, depth=3)
|
||||
course_module = store.get_item(location, depth=0)
|
||||
|
||||
try:
|
||||
textbook = validate_textbook_json(request.body)
|
||||
@@ -520,7 +520,13 @@ def create_textbook(request, org, course, name):
|
||||
if not textbook.get("id"):
|
||||
tids = set(t["id"] for t in course_module.pdf_textbooks if "id" in t)
|
||||
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))
|
||||
resp = JsonResponse(textbook, status=201)
|
||||
resp["Location"] = reverse("textbook_by_id", kwargs={
|
||||
|
||||
@@ -227,12 +227,16 @@ CMS.Views.EditChapter = Backbone.View.extend({
|
||||
},
|
||||
changeName: function(e) {
|
||||
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;
|
||||
},
|
||||
changeAssetPath: function(e) {
|
||||
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;
|
||||
},
|
||||
removeChapter: function(e) {
|
||||
|
||||
@@ -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
|
||||
success_condition).
|
||||
"""
|
||||
assert is_css_present(css_selector)
|
||||
assert is_css_present(css_selector), "{} is not present".format(css_selector)
|
||||
attempt = 0
|
||||
result = False
|
||||
while attempt < max_attempts:
|
||||
for attempt in range(max_attempts):
|
||||
try:
|
||||
world.css_find(css_selector)[index].click()
|
||||
if success_condition():
|
||||
result = True
|
||||
break
|
||||
return
|
||||
except WebDriverException:
|
||||
# Occasionally, MathJax or other JavaScript can cover up
|
||||
# an element temporarily.
|
||||
# If this happens, wait a second, then try again
|
||||
world.wait(1)
|
||||
attempt += 1
|
||||
except:
|
||||
attempt += 1
|
||||
return result
|
||||
pass
|
||||
else:
|
||||
# try once more, letting execptions raise
|
||||
world.css_find(css_selector)[index].click()
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -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
|
||||
success_condition).
|
||||
"""
|
||||
assert is_css_present(css_selector)
|
||||
assert is_css_present(css_selector), "{} is not present".format(css_selector)
|
||||
attempt = 0
|
||||
result = False
|
||||
while attempt < max_attempts:
|
||||
for attempt in range(max_attempts):
|
||||
try:
|
||||
world.css_find(css_selector)[index].check()
|
||||
if success_condition():
|
||||
result = True
|
||||
break
|
||||
return
|
||||
except WebDriverException:
|
||||
# Occasionally, MathJax or other JavaScript can cover up
|
||||
# an element temporarily.
|
||||
# If this happens, wait a second, then try again
|
||||
world.wait(1)
|
||||
attempt += 1
|
||||
except:
|
||||
attempt += 1
|
||||
return result
|
||||
pass
|
||||
else:
|
||||
# try once more, letting exceptions raise
|
||||
world.css_find(css_selector)[index].check()
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -143,7 +143,7 @@ def id_click(elem_id):
|
||||
|
||||
@world.absorb
|
||||
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)
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ def css_html(css_selector, index=0, max_attempts=5):
|
||||
|
||||
@world.absorb
|
||||
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
|
||||
|
||||
|
||||
@@ -203,11 +203,15 @@ def dialogs_closed():
|
||||
def save_the_html(path='/tmp'):
|
||||
url = world.browser.url
|
||||
html = world.browser.html.encode('ascii', 'ignore')
|
||||
filename = '%s.html' % quote_plus(url)
|
||||
file = open('%s/%s' % (path, filename), 'w')
|
||||
file.write(html)
|
||||
file.close()
|
||||
filename = "{path}/{name}.html".format(path=path, name=quote_plus(url))
|
||||
with open(filename, "w") as f:
|
||||
f.write(html)
|
||||
|
||||
@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
|
||||
def click_course_settings():
|
||||
|
||||
BIN
common/test/data/uploads/textbook.pdf
Normal file
BIN
common/test/data/uploads/textbook.pdf
Normal file
Binary file not shown.
Reference in New Issue
Block a user