problem-editor.py 9.24 KB
Newer Older
cahrens committed
1
# disable missing docstring
2
# pylint: disable=C0111
cahrens committed
3

4
import json
cahrens committed
5
from lettuce import world, step
6
from nose.tools import assert_equal, assert_true  # pylint: disable=E0611
Julian Arni committed
7
from common import type_in_codemirror, open_new_course
8
from advanced_settings import change_value
Julian Arni committed
9
from course_import import import_file, go_to_import
10

cahrens committed
11
DISPLAY_NAME = "Display Name"
12 13 14 15
MAXIMUM_ATTEMPTS = "Maximum Attempts"
PROBLEM_WEIGHT = "Problem Weight"
RANDOMIZATION = 'Randomization'
SHOW_ANSWER = "Show Answer"
Nick Parlante committed
16
TIMER_BETWEEN_ATTEMPTS = "Timer Between Attempts"
cahrens committed
17 18 19

@step('I have created a Blank Common Problem$')
def i_created_blank_common_problem(step):
20
    world.create_course_with_unit()
21 22 23 24 25
    step.given("I have created another Blank Common Problem")


@step('I have created another Blank Common Problem$')
def i_create_new_common_problem(step):
26
    world.create_component_instance(
27 28 29
        step=step,
        category='problem',
        component_type='Blank Common Problem'
30
    )
31

cahrens committed
32 33

@step('I edit and select Settings$')
34
def i_edit_and_select_settings(_step):
cahrens committed
35 36
    world.edit_component_and_select_settings()

37

38 39
@step('I see the advanced settings and their expected values$')
def i_see_advanced_settings_with_values(step):
cahrens committed
40 41
    world.verify_all_setting_entries(
        [
42
            [DISPLAY_NAME, "Blank Common Problem", True],
cahrens committed
43 44
            [MAXIMUM_ATTEMPTS, "", False],
            [PROBLEM_WEIGHT, "", False],
45
            [RANDOMIZATION, "Never", False],
46
            [SHOW_ANSWER, "Finished", False],
Nick Parlante committed
47
            [TIMER_BETWEEN_ATTEMPTS, "0", False]
cahrens committed
48 49
        ])

50

cahrens committed
51
@step('I can modify the display name')
52
def i_can_modify_the_display_name(_step):
53 54
    # Verifying that the display name can be a string containing a floating point value
    # (to confirm that we don't throw an error because it is of the wrong type).
55
    index = world.get_setting_entry_index(DISPLAY_NAME)
56
    world.set_field_value(index, '3.4')
cahrens committed
57 58
    verify_modified_display_name()

59

cahrens committed
60 61 62 63 64
@step('my display name change is persisted on save')
def my_display_name_change_is_persisted_on_save(step):
    world.save_component_and_reopen(step)
    verify_modified_display_name()

65

cahrens committed
66 67 68 69 70
@step('the problem display name is "(.*)"$')
def verify_problem_display_name(step, name):
    assert_equal(name.upper(), world.browser.find_by_css('.problem-header').text)


71
@step('I can specify special characters in the display name')
72
def i_can_modify_the_display_name_with_special_chars(_step):
73
    index = world.get_setting_entry_index(DISPLAY_NAME)
74
    world.set_field_value(index, "updated ' \" &")
75 76
    verify_modified_display_name_with_special_chars()

77

78 79 80 81 82
@step('my special characters and persisted on save')
def special_chars_persisted_on_save(step):
    world.save_component_and_reopen(step)
    verify_modified_display_name_with_special_chars()

83

cahrens committed
84
@step('I can revert the display name to unset')
85
def can_revert_display_name_to_unset(_step):
cahrens committed
86 87 88
    world.revert_setting_entry(DISPLAY_NAME)
    verify_unset_display_name()

89

cahrens committed
90 91 92 93 94
@step('my display name is unset on save')
def my_display_name_is_persisted_on_save(step):
    world.save_component_and_reopen(step)
    verify_unset_display_name()

95

cahrens committed
96
@step('I can select Per Student for Randomization')
97
def i_can_select_per_student_for_randomization(_step):
cahrens committed
98 99 100
    world.browser.select(RANDOMIZATION, "Per Student")
    verify_modified_randomization()

101

cahrens committed
102 103 104 105 106
@step('my change to randomization is persisted')
def my_change_to_randomization_is_persisted(step):
    world.save_component_and_reopen(step)
    verify_modified_randomization()

107

cahrens committed
108 109 110 111
@step('I can revert to the default value for randomization')
def i_can_revert_to_default_for_randomization(step):
    world.revert_setting_entry(RANDOMIZATION)
    world.save_component_and_reopen(step)
112
    world.verify_setting_entry(world.get_setting_entry(RANDOMIZATION), RANDOMIZATION, "Never", False)
113

cahrens committed
114

115
@step('I can set the weight to "(.*)"?')
116
def i_can_set_weight(_step, weight):
117
    set_weight(weight)
cahrens committed
118 119
    verify_modified_weight()

120

cahrens committed
121
@step('my change to weight is persisted')
122
def my_change_to_weight_is_persisted(step):
cahrens committed
123 124 125
    world.save_component_and_reopen(step)
    verify_modified_weight()

126

cahrens committed
127
@step('I can revert to the default value of unset for weight')
128
def i_can_revert_to_default_for_unset_weight(step):
cahrens committed
129 130
    world.revert_setting_entry(PROBLEM_WEIGHT)
    world.save_component_and_reopen(step)
131 132
    world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", False)

cahrens committed
133

134 135 136
@step('if I set the weight to "(.*)", it remains unset')
def set_the_weight_to_abc(step, bad_weight):
    set_weight(bad_weight)
cahrens committed
137
    # We show the clear button immediately on type, hence the "True" here.
138
    world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", True)
cahrens committed
139 140
    world.save_component_and_reopen(step)
    # But no change was actually ever sent to the model, so on reopen, explicitly_set is False
141
    world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "", False)
142

cahrens committed
143

144 145
@step('if I set the max attempts to "(.*)", it will persist as a valid integer$')
def set_the_max_attempts(step, max_attempts_set):
polesye committed
146
    # on firefox with selenium, the behavior is different.
147
    # eg 2.34 displays as 2.34 and is persisted as 2
148
    index = world.get_setting_entry_index(MAXIMUM_ATTEMPTS)
149
    world.set_field_value(index, max_attempts_set)
cahrens committed
150
    world.save_component_and_reopen(step)
151 152 153
    value = world.css_value('input.setting-input', index=index)
    assert value != "", "max attempts is blank"
    assert int(value) >= 0
154

cahrens committed
155 156 157

@step('Edit High Level Source is not visible')
def edit_high_level_source_not_visible(step):
158
    verify_high_level_source_links(step, False)
cahrens committed
159

160

cahrens committed
161
@step('Edit High Level Source is visible')
162 163
def edit_high_level_source_links_visible(step):
    verify_high_level_source_links(step, True)
cahrens committed
164

165

cahrens committed
166 167 168 169
@step('If I press Cancel my changes are not persisted')
def cancel_does_not_save_changes(step):
    world.cancel_component(step)
    step.given("I edit and select Settings")
170
    step.given("I see the advanced settings and their expected values")
cahrens committed
171

172

173 174 175 176
@step('I have enabled latex compiler')
def enable_latex_compiler(step):
    url = world.browser.url
    step.given("I select the Advanced Settings")
177
    change_value(step, 'use_latex_compiler', 'true')
178 179 180 181
    world.visit(url)
    world.wait_for_xmodule()


cahrens committed
182 183
@step('I have created a LaTeX Problem')
def create_latex_problem(step):
184
    world.create_course_with_unit()
185
    step.given('I have enabled latex compiler')
186 187 188 189 190 191
    world.create_component_instance(
        step=step,
        category='problem',
        component_type='Problem Written in LaTeX',
        is_advanced=True
    )
cahrens committed
192

193

194
@step('I edit and compile the High Level Source')
195
def edit_latex_source(_step):
196
    open_high_level_source()
197 198 199 200 201
    type_in_codemirror(1, "hi")
    world.css_click('.hls-compile')


@step('my change to the High Level Source is persisted')
202
def high_level_source_persisted(_step):
203
    def verify_text(driver):
Will Daly committed
204 205
        css_sel = '.problem div>span'
        return world.css_text(css_sel) == 'hi'
206

207
    world.wait_for(verify_text, timeout=10)
208 209 210


@step('I view the High Level Source I see my changes')
211
def high_level_source_in_editor(_step):
212
    open_high_level_source()
213
    assert_equal('hi', world.css_value('.source-edit-box'))
214

Julian Arni committed
215

216 217
@step(u'I have an empty course')
def i_have_empty_course(step):
Julian Arni committed
218
    open_new_course()
219

Julian Arni committed
220

221 222
@step(u'I go to the import page')
def i_go_to_import(_step):
Julian Arni committed
223
    go_to_import()
224 225 226 227


@step(u'I import the file "([^"]*)"$')
def i_import_the_file(_step, filename):
Julian Arni committed
228
    import_file(filename)
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243


@step(u'I go to the vertical "([^"]*)"$')
def i_go_to_vertical(_step, vertical):
    world.css_click("span:contains('{0}')".format(vertical))


@step(u'I go to the unit "([^"]*)"$')
def i_go_to_unit(_step, unit):
    loc = "window.location = $(\"span:contains('{0}')\").closest('a').attr('href')".format(unit)
    world.browser.execute_script(loc)


@step(u'I see a message that says "([^"]*)"$')
def i_can_see_message(_step, msg):
Julian Arni committed
244
    msg = json.dumps(msg)     # escape quotes
Julian Arni committed
245
    world.css_has_text("h2.title", msg)
246 247 248 249


@step(u'I can edit the problem$')
def i_can_edit_problem(_step):
Julian Arni committed
250
    world.edit_component()
251

252 253

def verify_high_level_source_links(step, visible):
254
    if visible:
255 256
        assert_true(world.is_css_present('.launch-latex-compiler'),
                    msg="Expected to find the latex button but it is not present.")
257
    else:
258 259 260
        assert_true(world.is_css_not_present('.launch-latex-compiler'),
                    msg="Expected not to find the latex button but it is present.")

cahrens committed
261 262
    world.cancel_component(step)

263

cahrens committed
264
def verify_modified_weight():
265 266
    world.verify_setting_entry(world.get_setting_entry(PROBLEM_WEIGHT), PROBLEM_WEIGHT, "3.5", True)

cahrens committed
267 268

def verify_modified_randomization():
269 270
    world.verify_setting_entry(world.get_setting_entry(RANDOMIZATION), RANDOMIZATION, "Per Student", True)

cahrens committed
271 272

def verify_modified_display_name():
273
    world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, '3.4', True)
cahrens committed
274

275

276 277 278
def verify_modified_display_name_with_special_chars():
    world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, "updated ' \" &", True)

279

cahrens committed
280
def verify_unset_display_name():
281
    world.verify_setting_entry(world.get_setting_entry(DISPLAY_NAME), DISPLAY_NAME, 'Blank Advanced Problem', False)
282 283 284


def set_weight(weight):
285
    index = world.get_setting_entry_index(PROBLEM_WEIGHT)
286
    world.set_field_value(index, weight)
287 288 289


def open_high_level_source():
290
    world.edit_component()
291
    world.css_click('.launch-latex-compiler > a')