Merge pull request #186 from edx/christina/latex_and_click
Bug fix for LaTeX source not saving
This commit is contained in:
@@ -3,11 +3,7 @@
|
||||
|
||||
from lettuce import world, step
|
||||
from nose.tools import assert_false, assert_equal, assert_regexp_matches
|
||||
|
||||
"""
|
||||
http://selenium.googlecode.com/svn/trunk/docs/api/py/webdriver/selenium.webdriver.common.keys.html
|
||||
"""
|
||||
from selenium.webdriver.common.keys import Keys
|
||||
from common import type_in_codemirror
|
||||
|
||||
KEY_CSS = '.key input.policy-key'
|
||||
VALUE_CSS = 'textarea.json'
|
||||
@@ -37,13 +33,7 @@ def press_the_notification_button(step, name):
|
||||
|
||||
@step(u'I edit the value of a policy key$')
|
||||
def edit_the_value_of_a_policy_key(step):
|
||||
"""
|
||||
It is hard to figure out how to get into the CodeMirror
|
||||
area, so cheat and do it from the policy key field :)
|
||||
"""
|
||||
world.css_find(".CodeMirror")[get_index_of(DISPLAY_NAME_KEY)].click()
|
||||
g = world.css_find("div.CodeMirror.CodeMirror-focused > div > textarea")
|
||||
g._element.send_keys(Keys.ARROW_LEFT, ' ', 'X')
|
||||
type_in_codemirror(get_index_of(DISPLAY_NAME_KEY), 'X')
|
||||
|
||||
|
||||
@step(u'I edit the value of a policy key and save$')
|
||||
@@ -132,13 +122,5 @@ def change_display_name_value(step, new_value):
|
||||
|
||||
|
||||
def change_value(step, key, new_value):
|
||||
index = get_index_of(key)
|
||||
world.css_find(".CodeMirror")[index].click()
|
||||
g = world.css_find("div.CodeMirror.CodeMirror-focused > div > textarea")
|
||||
current_value = world.css_find(VALUE_CSS)[index].value
|
||||
g._element.send_keys(Keys.CONTROL + Keys.END)
|
||||
for count in range(len(current_value)):
|
||||
g._element.send_keys(Keys.END, Keys.BACK_SPACE)
|
||||
# Must delete "" before typing the JSON value
|
||||
g._element.send_keys(Keys.END, Keys.BACK_SPACE, Keys.BACK_SPACE, new_value)
|
||||
type_in_codemirror(get_index_of(key), new_value)
|
||||
press_the_notification_button(step, "Save")
|
||||
|
||||
@@ -169,3 +169,14 @@ def open_new_unit(step):
|
||||
step.given('I have added a new subsection')
|
||||
step.given('I expand the first section')
|
||||
world.css_click('a.new-unit-item')
|
||||
|
||||
|
||||
def type_in_codemirror(index, text):
|
||||
world.css_click(".CodeMirror", index=index)
|
||||
g = world.css_find("div.CodeMirror.CodeMirror-focused > div > textarea")
|
||||
if world.is_mac():
|
||||
g._element.send_keys(Keys.COMMAND + 'a')
|
||||
else:
|
||||
g._element.send_keys(Keys.CONTROL + 'a')
|
||||
g._element.send_keys(Keys.DELETE)
|
||||
g._element.send_keys(text)
|
||||
|
||||
@@ -3,65 +3,71 @@ Feature: Problem Editor
|
||||
|
||||
Scenario: User can view metadata
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I see five alphabetized settings and their expected values
|
||||
And Edit High Level Source is not visible
|
||||
|
||||
Scenario: User can modify String values
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can modify the display name
|
||||
And my display name change is persisted on save
|
||||
|
||||
Scenario: User can specify special characters in String values
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can specify special characters in the display name
|
||||
And my special characters and persisted on save
|
||||
|
||||
Scenario: User can revert display name to unset
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can revert the display name to unset
|
||||
And my display name is unset on save
|
||||
|
||||
Scenario: User can select values in a Select
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can select Per Student for Randomization
|
||||
And my change to randomization is persisted
|
||||
And I can revert to the default value for randomization
|
||||
|
||||
Scenario: User can modify float input values
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can set the weight to "3.5"
|
||||
And my change to weight is persisted
|
||||
And I can revert to the default value of unset for weight
|
||||
|
||||
Scenario: User cannot type letters in float number field
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then if I set the weight to "abc", it remains unset
|
||||
|
||||
Scenario: User cannot type decimal values integer number field
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then if I set the max attempts to "2.34", it displays initially as "234", and is persisted as "234"
|
||||
|
||||
Scenario: User cannot type out of range values in an integer number field
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then if I set the max attempts to "-3", it displays initially as "-3", and is persisted as "0"
|
||||
|
||||
Scenario: Settings changes are not saved on Cancel
|
||||
Given I have created a Blank Common Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then I can set the weight to "3.5"
|
||||
And I can modify the display name
|
||||
Then If I press Cancel my changes are not persisted
|
||||
|
||||
Scenario: Edit High Level source is available for LaTeX problem
|
||||
Given I have created a LaTeX Problem
|
||||
And I edit and select Settings
|
||||
When I edit and select Settings
|
||||
Then Edit High Level Source is visible
|
||||
|
||||
Scenario: High Level source is persisted for LaTeX problem (bug STUD-280)
|
||||
Given I have created a LaTeX Problem
|
||||
When I edit and compile the High Level Source
|
||||
Then my change to the High Level Source is persisted
|
||||
And when I view the High Level Source I see my changes
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from lettuce import world, step
|
||||
from nose.tools import assert_equal
|
||||
from common import type_in_codemirror
|
||||
|
||||
DISPLAY_NAME = "Display Name"
|
||||
MAXIMUM_ATTEMPTS = "Maximum Attempts"
|
||||
@@ -135,12 +136,12 @@ def set_the_max_attempts(step, max_attempts_set, max_attempts_displayed, max_att
|
||||
|
||||
@step('Edit High Level Source is not visible')
|
||||
def edit_high_level_source_not_visible(step):
|
||||
verify_high_level_source(step, False)
|
||||
verify_high_level_source_links(step, False)
|
||||
|
||||
|
||||
@step('Edit High Level Source is visible')
|
||||
def edit_high_level_source_visible(step):
|
||||
verify_high_level_source(step, True)
|
||||
def edit_high_level_source_links_visible(step):
|
||||
verify_high_level_source_links(step, True)
|
||||
|
||||
|
||||
@step('If I press Cancel my changes are not persisted')
|
||||
@@ -153,13 +154,33 @@ def cancel_does_not_save_changes(step):
|
||||
@step('I have created a LaTeX Problem')
|
||||
def create_latex_problem(step):
|
||||
world.click_new_component_button(step, '.large-problem-icon')
|
||||
# Go to advanced tab (waiting for the tab to be visible)
|
||||
world.css_find('#ui-id-2')
|
||||
# Go to advanced tab.
|
||||
world.css_click('#ui-id-2')
|
||||
world.click_component_from_menu("i4x://edx/templates/problem/Problem_Written_in_LaTeX", '.xmodule_CapaModule')
|
||||
|
||||
|
||||
def verify_high_level_source(step, visible):
|
||||
@step('I edit and compile the High Level Source')
|
||||
def edit_latex_source(step):
|
||||
open_high_level_source()
|
||||
type_in_codemirror(1, "hi")
|
||||
world.css_click('.hls-compile')
|
||||
|
||||
|
||||
@step('my change to the High Level Source is persisted')
|
||||
def high_level_source_persisted(step):
|
||||
def verify_text(driver):
|
||||
return world.css_find('.problem').text == 'hi'
|
||||
|
||||
world.wait_for(verify_text)
|
||||
|
||||
|
||||
@step('I view the High Level Source I see my changes')
|
||||
def high_level_source_in_editor(step):
|
||||
open_high_level_source()
|
||||
assert_equal('hi', world.css_find('.source-edit-box').value)
|
||||
|
||||
|
||||
def verify_high_level_source_links(step, visible):
|
||||
assert_equal(visible, world.is_css_present('.launch-latex-compiler'))
|
||||
world.cancel_component(step)
|
||||
assert_equal(visible, world.is_css_present('.upload-button'))
|
||||
@@ -187,3 +208,8 @@ def verify_unset_display_name():
|
||||
|
||||
def set_weight(weight):
|
||||
world.get_setting_entry(PROBLEM_WEIGHT).find_by_css('.setting-input')[0].fill(weight)
|
||||
|
||||
|
||||
def open_high_level_source():
|
||||
world.css_click('a.edit-button')
|
||||
world.css_click('.launch-latex-compiler > a')
|
||||
|
||||
@@ -44,8 +44,17 @@ class CMS.Views.ModuleEdit extends Backbone.View
|
||||
[@metadataEditor.getDisplayName()])
|
||||
@$el.find('.component-name').html(title)
|
||||
|
||||
customMetadata: ->
|
||||
# Hack to support metadata fields that aren't part of the metadata editor (ie, LaTeX high level source).
|
||||
# Walk through the set of elements which have the 'data-metadata_name' attribute and
|
||||
# build up an object to pass back to the server on the subsequent POST.
|
||||
# Note that these values will always be sent back on POST, even if they did not actually change.
|
||||
_metadata = {}
|
||||
_metadata[$(el).data("metadata-name")] = el.value for el in $('[data-metadata-name]', @$component_editor())
|
||||
return _metadata
|
||||
|
||||
changedMetadata: ->
|
||||
return @metadataEditor.getModifiedMetadataValues()
|
||||
return _.extend(@metadataEditor.getModifiedMetadataValues(), @customMetadata())
|
||||
|
||||
cloneTemplate: (parent, template) ->
|
||||
$.post("/clone_item", {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from lettuce import world
|
||||
import time
|
||||
import platform
|
||||
from urllib import quote_plus
|
||||
from selenium.common.exceptions import WebDriverException, StaleElementReferenceException
|
||||
from selenium.webdriver.support import expected_conditions as EC
|
||||
@@ -57,20 +58,28 @@ def css_find(css, wait_time=5):
|
||||
|
||||
|
||||
@world.absorb
|
||||
def css_click(css_selector):
|
||||
def css_click(css_selector, index=0, attempts=5):
|
||||
"""
|
||||
Perform a click on a CSS selector, retrying if it initially fails
|
||||
This function will return if the click worked (since it is try/excepting all errors)
|
||||
"""
|
||||
assert is_css_present(css_selector)
|
||||
try:
|
||||
world.browser.find_by_css(css_selector).click()
|
||||
|
||||
except WebDriverException:
|
||||
# Occassionally, MathJax or other JavaScript can cover up
|
||||
# an element temporarily.
|
||||
# If this happens, wait a second, then try again
|
||||
world.wait(1)
|
||||
world.browser.find_by_css(css_selector).click()
|
||||
attempt = 0
|
||||
result = False
|
||||
while attempt < attempts:
|
||||
try:
|
||||
world.css_find(css_selector)[index].click()
|
||||
result = True
|
||||
break
|
||||
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
|
||||
|
||||
|
||||
@world.absorb
|
||||
@@ -158,3 +167,8 @@ def click_tools():
|
||||
tools_css = 'li.nav-course-tools'
|
||||
if world.browser.is_element_present_by_css(tools_css):
|
||||
world.css_click(tools_css)
|
||||
|
||||
|
||||
@world.absorb
|
||||
def is_mac():
|
||||
return platform.mac_ver()[0] is not ''
|
||||
|
||||
Reference in New Issue
Block a user