Commit ef3492aa by Brian Talbot

studio - resolving local merge

parents c7f5b742 1ccf0d48
...@@ -7,18 +7,18 @@ Feature: Advanced (manual) course policy ...@@ -7,18 +7,18 @@ Feature: Advanced (manual) course policy
When I select the Advanced Settings When I select the Advanced Settings
Then I see only the display name Then I see only the display name
Scenario: A course author sees something sensible if there are no policy settings without existing UI controls Scenario: Test if there are no policy settings without existing UI controls
Given I have opened a new course in Studio Given I have opened a new course in Studio
When I select the Advanced Settings When I select the Advanced Settings
And I delete the display name And I delete the display name
Then There are no advanced policy settings Then there are no advanced policy settings
And I refresh and select the Advanced Settings And I reload the page
Then There are no advanced policy settings Then there are no advanced policy settings
Scenario: A course author can add new entries, and they appear alphabetically after save Scenario: Add new entries, and they appear alphabetically after save
Given I have opened a new course in Studio Given I have opened a new course in Studio
When I select the Advanced Settings When I select the Advanced Settings
And Create New Entries And I create New Entries
Then They are alphabetized Then they are alphabetized
And I refresh and select the Advanced Settings And I reload the page
Then They are alphabetized Then they are alphabetized
\ No newline at end of file \ No newline at end of file
...@@ -11,41 +11,43 @@ from selenium.webdriver.common.keys import Keys ...@@ -11,41 +11,43 @@ from selenium.webdriver.common.keys import Keys
############### ACTIONS #################### ############### ACTIONS ####################
@step('I select the Advanced Settings$') @step('I select the Advanced Settings$')
def i_select_advanced_settings(step): def i_select_advanced_settings(step):
link_css = 'a#settings-tab' expand_icon_css = 'li.nav-course-settings i.icon-expand'
css_click(link_css) if world.browser.is_element_present_by_css(expand_icon_css):
link_css = "[data-section='advanced']" css_click(expand_icon_css)
link_css = 'li.nav-course-settings-advanced a'
css_click(link_css) css_click(link_css)
@step('I refresh and select the Advanced Settings$')
def refresh_and_select_advanced_settings(step):
reload()
i_select_advanced_settings(step)
@step('I see only the display name$') @step('I see only the display name$')
def i_see_only_display_name(step): def i_see_only_display_name(step):
assert_policy_entries(["display_name"], ['"Robot Super Course"']) assert_policy_entries(["display_name"], ['"Robot Super Course"'])
@step('I delete the display name') @step('I delete the display name')
def i_delete_the_display_name(step): def i_delete_the_display_name(step):
delete_entry(0) delete_entry(0)
click_save() click_save()
@step("There are no advanced policy settings$")
@step('there are no advanced policy settings$')
def no_policy_settings(step): def no_policy_settings(step):
assert_policy_entries([], []) assert_policy_entries([], [])
@step("Create New Entries")
@step('create New Entries$')
def create_new_entries(step): def create_new_entries(step):
create_entry("z", "apple") create_entry("z", "apple")
create_entry("a", "zebra") create_entry("a", "zebra")
click_save() click_save()
@step("They are alphabetized")
@step('they are alphabetized$')
def they_are_alphabetized(step): def they_are_alphabetized(step):
assert_policy_entries(["a", "display_name", "z"], ['"zebra"', '"Robot Super Course"', '"apple"']) assert_policy_entries(["a", "display_name", "z"], ['"zebra"', '"Robot Super Course"', '"apple"'])
def create_entry(key, value): def create_entry(key, value):
css_click(".new-advanced-policy-item") css_click_at('a.new-advanced-policy-item')
newKey = css_find('#__new_advanced_key__ input').first newKey = css_find('#__new_advanced_key__ input').first
newKey.fill(key) newKey.fill(key)
# For some reason have to get the instance for each command (get error that it is no longer attached to the DOM) # For some reason have to get the instance for each command (get error that it is no longer attached to the DOM)
...@@ -54,6 +56,7 @@ def create_entry(key, value): ...@@ -54,6 +56,7 @@ def create_entry(key, value):
css_find('.CodeMirror textarea').last._element.send_keys(Keys.ARROW_LEFT) css_find('.CodeMirror textarea').last._element.send_keys(Keys.ARROW_LEFT)
css_find('.CodeMirror textarea').last.fill(value) css_find('.CodeMirror textarea').last.fill(value)
def delete_entry(index): def delete_entry(index):
""" index is 0-based """ index is 0-based
""" """
...@@ -63,17 +66,20 @@ def delete_entry(index): ...@@ -63,17 +66,20 @@ def delete_entry(index):
assert_true(len(delete_buttons) > index, "no delete button exists for entry " + str(index)) assert_true(len(delete_buttons) > index, "no delete button exists for entry " + str(index))
delete_buttons[index].click() delete_buttons[index].click()
def assert_policy_entries(expected_keys, expected_values): def assert_policy_entries(expected_keys, expected_values):
assert_entries('.key input', expected_keys) assert_entries('.key input', expected_keys)
assert_entries('.json', expected_values) assert_entries('.json', expected_values)
def assert_entries(css, expected_values): def assert_entries(css, expected_values):
webElements = css_find(css) webElements = css_find(css)
assert_equal(len(expected_values),len(webElements)) assert_equal(len(expected_values), len(webElements))
# Sometimes get stale reference if I hold on to the array of elements # Sometimes get stale reference if I hold on to the array of elements
for counter in range(len(expected_values)): for counter in range(len(expected_values)):
assert_equal(expected_values[counter], css_find(css)[counter].value) assert_equal(expected_values[counter], css_find(css)[counter].value)
def click_save(): def click_save():
css = ".save-button" css = ".save-button"
def is_shown(driver): def is_shown(driver):
...@@ -85,6 +91,7 @@ def click_save(): ...@@ -85,6 +91,7 @@ def click_save():
wait_for(is_shown) wait_for(is_shown)
css_click(css) css_click(css)
def fill_last_field(value): def fill_last_field(value):
newValue = css_find('#__new_advanced_key__ input').first newValue = css_find('#__new_advanced_key__ input').first
newValue.fill(value) newValue.fill(value)
\ No newline at end of file
...@@ -10,6 +10,7 @@ from logging import getLogger ...@@ -10,6 +10,7 @@ from logging import getLogger
logger = getLogger(__name__) logger = getLogger(__name__)
########### STEP HELPERS ############## ########### STEP HELPERS ##############
@step('I (?:visit|access|open) the Studio homepage$') @step('I (?:visit|access|open) the Studio homepage$')
def i_visit_the_studio_homepage(step): def i_visit_the_studio_homepage(step):
# To make this go to port 8001, put # To make this go to port 8001, put
...@@ -19,14 +20,17 @@ def i_visit_the_studio_homepage(step): ...@@ -19,14 +20,17 @@ def i_visit_the_studio_homepage(step):
signin_css = 'a.action-signin' signin_css = 'a.action-signin'
assert world.browser.is_element_present_by_css(signin_css, 10) assert world.browser.is_element_present_by_css(signin_css, 10)
@step('I am logged into Studio$') @step('I am logged into Studio$')
def i_am_logged_into_studio(step): def i_am_logged_into_studio(step):
log_into_studio() log_into_studio()
@step('I confirm the alert$') @step('I confirm the alert$')
def i_confirm_with_ok(step): def i_confirm_with_ok(step):
world.browser.get_alert().accept() world.browser.get_alert().accept()
@step(u'I press the "([^"]*)" delete icon$') @step(u'I press the "([^"]*)" delete icon$')
def i_press_the_category_delete_icon(step, category): def i_press_the_category_delete_icon(step, category):
if category == 'section': if category == 'section':
...@@ -37,6 +41,7 @@ def i_press_the_category_delete_icon(step, category): ...@@ -37,6 +41,7 @@ def i_press_the_category_delete_icon(step, category):
assert False, 'Invalid category: %s' % category assert False, 'Invalid category: %s' % category
css_click(css) css_click(css)
@step('I have opened a new course in Studio$') @step('I have opened a new course in Studio$')
def i_have_opened_a_new_course(step): def i_have_opened_a_new_course(step):
clear_courses() clear_courses()
...@@ -44,13 +49,14 @@ def i_have_opened_a_new_course(step): ...@@ -44,13 +49,14 @@ def i_have_opened_a_new_course(step):
create_a_course() create_a_course()
####### HELPER FUNCTIONS ############## ####### HELPER FUNCTIONS ##############
def create_studio_user( def create_studio_user(
uname='robot', uname='robot',
email='robot+studio@edx.org', email='robot+studio@edx.org',
password='test', password='test',
is_staff=False): is_staff=False):
studio_user = UserFactory.build( studio_user = UserFactory.build(
username=uname, username=uname,
email=email, email=email,
password=password, password=password,
is_staff=is_staff) is_staff=is_staff)
...@@ -63,6 +69,7 @@ def create_studio_user( ...@@ -63,6 +69,7 @@ def create_studio_user(
user_profile = UserProfileFactory(user=studio_user) user_profile = UserProfileFactory(user=studio_user)
def flush_xmodule_store(): def flush_xmodule_store():
# Flush and initialize the module store # Flush and initialize the module store
# It needs the templates because it creates new records # It needs the templates because it creates new records
...@@ -75,32 +82,53 @@ def flush_xmodule_store(): ...@@ -75,32 +82,53 @@ def flush_xmodule_store():
xmodule.modulestore.django.modulestore().collection.drop() xmodule.modulestore.django.modulestore().collection.drop()
xmodule.templates.update_templates() xmodule.templates.update_templates()
def assert_css_with_text(css, text): def assert_css_with_text(css, text):
assert_true(world.browser.is_element_present_by_css(css, 5)) assert_true(world.browser.is_element_present_by_css(css, 5))
assert_equal(world.browser.find_by_css(css).text, text) assert_equal(world.browser.find_by_css(css).text, text)
def css_click(css): def css_click(css):
assert_true(world.browser.is_element_present_by_css(css, 5)) assert_true(world.browser.is_element_present_by_css(css, 5))
world.browser.find_by_css(css).first.click() world.browser.find_by_css(css).first.click()
def css_click_at(css, x=10, y=10):
'''
A method to click at x,y coordinates of the element
rather than in the center of the element
'''
assert_true(world.browser.is_element_present_by_css(css, 5))
e = world.browser.find_by_css(css).first
e.action_chains.move_to_element_with_offset(e._element, x, y)
e.action_chains.click()
e.action_chains.perform()
def css_fill(css, value): def css_fill(css, value):
world.browser.find_by_css(css).first.fill(value) world.browser.find_by_css(css).first.fill(value)
def css_find(css): def css_find(css):
return world.browser.find_by_css(css) return world.browser.find_by_css(css)
def wait_for(func): def wait_for(func):
WebDriverWait(world.browser.driver, 10).until(func) WebDriverWait(world.browser.driver, 10).until(func)
def id_find(id): def id_find(id):
return world.browser.find_by_id(id) return world.browser.find_by_id(id)
def reload(): def reload():
return world.browser.reload() return world.browser.reload()
def clear_courses(): def clear_courses():
flush_xmodule_store() flush_xmodule_store()
def fill_in_course_info( def fill_in_course_info(
name='Robot Super Course', name='Robot Super Course',
org='MITx', org='MITx',
...@@ -109,6 +137,7 @@ def fill_in_course_info( ...@@ -109,6 +137,7 @@ def fill_in_course_info(
css_fill('.new-course-org', org) css_fill('.new-course-org', org)
css_fill('.new-course-number', num) css_fill('.new-course-number', num)
def log_into_studio( def log_into_studio(
uname='robot', uname='robot',
email='robot+studio@edx.org', email='robot+studio@edx.org',
...@@ -130,6 +159,7 @@ def log_into_studio( ...@@ -130,6 +159,7 @@ def log_into_studio(
assert_true(world.browser.is_element_present_by_css('.new-course-button', 5)) assert_true(world.browser.is_element_present_by_css('.new-course-button', 5))
def create_a_course(): def create_a_course():
css_click('a.new-course-button') css_click('a.new-course-button')
fill_in_course_info() fill_in_course_info()
...@@ -137,6 +167,7 @@ def create_a_course(): ...@@ -137,6 +167,7 @@ def create_a_course():
course_title_css = 'span.course-title' course_title_css = 'span.course-title'
assert_true(world.browser.is_element_present_by_css(course_title_css, 5)) assert_true(world.browser.is_element_present_by_css(course_title_css, 5))
def add_section(name='My Section'): def add_section(name='My Section'):
link_css = 'a.new-courseware-section-button' link_css = 'a.new-courseware-section-button'
css_click(link_css) css_click(link_css)
......
...@@ -21,6 +21,11 @@ def wait(step, seconds): ...@@ -21,6 +21,11 @@ def wait(step, seconds):
time.sleep(float(seconds)) time.sleep(float(seconds))
@step('I reload the page$')
def reload_the_page(step):
world.browser.reload()
@step('I (?:visit|access|open) the homepage$') @step('I (?:visit|access|open) the homepage$')
def i_visit_the_homepage(step): def i_visit_the_homepage(step):
world.browser.visit(django_url('/')) world.browser.visit(django_url('/'))
......
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