Files
edx-platform/lms/djangoapps/courseware/features/problems.py
Ben Patterson e54ce29587 Fix flaky lettuce test. TE-572.
This should be ported to bok-choy, but until then we should fix the flakiness in
this test. It needs to wait for the page to change after the user clicks 'reset'.
2015-06-09 09:37:36 -04:00

187 lines
6.7 KiB
Python

'''
Steps for problem.feature lettuce tests
'''
# pylint: disable=missing-docstring
# pylint: disable=redefined-outer-name
from lettuce import world, step
from common import i_am_registered_for_the_course, visit_scenario_item
from problems_setup import PROBLEM_DICT, answer_problem, problem_has_answer, add_problem_to_course
def _view_problem(step, problem_type, problem_settings=None):
i_am_registered_for_the_course(step, 'model_course')
# Ensure that the course has this problem type
add_problem_to_course(world.scenario_dict['COURSE'].number, problem_type, problem_settings)
# Go to the one section in the factory-created course
# which should be loaded with the correct problem
visit_scenario_item('SECTION')
@step(u'I am viewing a "([^"]*)" problem with "([^"]*)" attempt')
def view_problem_with_attempts(step, problem_type, attempts):
_view_problem(step, problem_type, {'max_attempts': attempts})
@step(u'I am viewing a randomization "([^"]*)" "([^"]*)" problem with "([^"]*)" attempts with reset')
def view_problem_attempts_reset(step, randomization, problem_type, attempts, ):
_view_problem(step, problem_type, {'max_attempts': attempts,
'rerandomize': randomization,
'show_reset_button': True})
@step(u'I am viewing a "([^"]*)" that shows the answer "([^"]*)"')
def view_problem_with_show_answer(step, problem_type, answer):
_view_problem(step, problem_type, {'showanswer': answer})
@step(u'I am viewing a "([^"]*)" problem')
def view_problem(step, problem_type):
_view_problem(step, problem_type)
@step(u'I am viewing a randomization "([^"]*)" "([^"]*)" problem with reset button on')
def view_random_reset_problem(step, randomization, problem_type):
_view_problem(step, problem_type, {'rerandomize': randomization, 'show_reset_button': True})
@step(u'External graders respond "([^"]*)"')
def set_external_grader_response(step, correctness):
assert(correctness in ['correct', 'incorrect'])
response_dict = {
'correct': True if correctness == 'correct' else False,
'score': 1 if correctness == 'correct' else 0,
'msg': 'Your problem was graded {0}'.format(correctness)
}
# Set the fake xqueue server to always respond
# correct/incorrect when asked to grade a problem
world.xqueue.config['default'] = response_dict
@step(u'I answer a "([^"]*)" problem "([^"]*)ly"')
def answer_problem_step(step, problem_type, correctness):
""" Mark a given problem type correct or incorrect, then submit it.
*problem_type* is a string representing the type of problem (e.g. 'drop down')
*correctness* is in ['correct', 'incorrect']
"""
# Change the answer on the page
input_problem_answer(step, problem_type, correctness)
# Submit the problem
check_problem(step)
@step(u'I input an answer on a "([^"]*)" problem "([^"]*)ly"')
def input_problem_answer(_, problem_type, correctness):
"""
Have the browser input an answer (either correct or incorrect)
"""
assert(correctness in ['correct', 'incorrect'])
assert(problem_type in PROBLEM_DICT)
answer_problem(world.scenario_dict['COURSE'].number, problem_type, correctness)
@step(u'I check a problem')
def check_problem(step):
# first scroll down so the loading mathjax button does not
# cover up the Check button
world.browser.execute_script("window.scrollTo(0,1024)")
world.css_click("button.check")
# Wait for the problem to finish re-rendering
world.wait_for_ajax_complete()
@step(u'The "([^"]*)" problem displays a "([^"]*)" answer')
def assert_problem_has_answer(step, problem_type, answer_class):
'''
Assert that the problem is displaying a particular answer.
These correspond to the same correct/incorrect
answers we set in answer_problem()
We can also check that a problem has been left blank
by setting answer_class='blank'
'''
assert answer_class in ['correct', 'incorrect', 'blank']
assert problem_type in PROBLEM_DICT
problem_has_answer(world.scenario_dict['COURSE'].number, problem_type, answer_class)
@step(u'I reset the problem')
def reset_problem(_step):
world.css_click('button.reset')
# Wait for the problem to finish re-rendering
world.wait_for_ajax_complete()
@step(u'I press the button with the label "([^"]*)"$')
def press_the_button_with_label(_step, buttonname):
button_css = 'button span.show-label'
elem = world.css_find(button_css).first
world.css_has_text(button_css, elem)
world.css_click(button_css)
@step(u'The "([^"]*)" button does( not)? appear')
def action_button_present(_step, buttonname, doesnt_appear):
button_css = 'div.action button[data-value*="%s"]' % buttonname
if bool(doesnt_appear):
assert world.is_css_not_present(button_css)
else:
assert world.is_css_present(button_css)
@step(u'the Show/Hide button label is "([^"]*)"$')
def show_hide_label_is(_step, label_name):
# The label text is changed by static/xmodule_js/src/capa/display.js
# so give it some time to change on the page.
label_css = 'button.show span.show-label'
world.wait_for(lambda _: world.css_has_text(label_css, label_name))
@step(u'I should see a score of "([^"]*)"$')
def see_score(_step, score):
# The problem progress is changed by
# cms/static/xmodule_js/src/capa/display.js
# so give it some time to render on the page.
score_css = 'div.problem-progress'
expected_text = '({})'.format(score)
world.wait_for(lambda _: world.css_has_text(score_css, expected_text))
@step(u'[Mm]y "([^"]*)" answer is( NOT)? marked "([^"]*)"')
def assert_answer_mark(_step, problem_type, isnt_marked, correctness):
"""
Assert that the expected answer mark is visible
for a given problem type.
*problem_type* is a string identifying the type of problem (e.g. 'drop down')
*correctness* is in ['correct', 'incorrect', 'unanswered']
"""
# Determine which selector(s) to look for based on correctness
assert(correctness in ['correct', 'incorrect', 'unanswered'])
assert(problem_type in PROBLEM_DICT)
# At least one of the correct selectors should be present
for sel in PROBLEM_DICT[problem_type][correctness]:
if bool(isnt_marked):
world.wait_for(lambda _: world.is_css_not_present(sel)) # pylint: disable=cell-var-from-loop
has_expected = world.is_css_not_present(sel)
else:
world.css_find(sel) # css_find includes a wait_for pattern
has_expected = world.is_css_present(sel)
# As soon as we find the selector, break out of the loop
if has_expected:
break
# Expect that we found the expected selector
assert(has_expected)