Commit 8ab2e3c3 by Jay Zoldak

Merge pull request #1179 from edx/zoldak/enable-component-acceptance-tests

Re-enable the component acceptance tests
parents 38642d28 50dc93dc
......@@ -168,6 +168,18 @@ def log_into_studio(
assert_in(uname, world.css_text('h2.title', timeout=10))
def add_course_author(user, course):
"""
Add the user to the instructor group of the course
so they will have the permissions to see it in studio
"""
for role in ("staff", "instructor"):
groupname = get_course_groupname_for_role(course.location, role)
group, __ = Group.objects.get_or_create(name=groupname)
user.groups.add(group)
user.save()
def create_a_course():
course = world.CourseFactory.create(org='MITx', course='999', display_name='Robot Super Course')
world.scenario_dict['COURSE'] = course
......@@ -176,13 +188,7 @@ def create_a_course():
if not user:
user = get_user_by_email('robot+studio@edx.org')
# Add the user to the instructor group of the course
# so they will have the permissions to see it in studio
for role in ("staff", "instructor"):
groupname = get_course_groupname_for_role(course.location, role)
group, __ = Group.objects.get_or_create(name=groupname)
user.groups.add(group)
user.save()
add_course_author(user, course)
# Navigate to the studio dashboard
world.visit('/')
......
......@@ -2,85 +2,87 @@
Feature: CMS.Component Adding
As a course author, I want to be able to add a wide variety of components
#Scenario: I can add components
# Given I have opened a new course in studio
# And I am editing a new unit
# When I add the following components:
# | Component |
# | Discussion |
# | Blank HTML |
# | LaTex |
# | Blank Problem|
# | Dropdown |
# | Multi Choice |
# | Numerical |
# | Text Input |
# | Advanced |
# | Circuit |
# | Custom Python|
# | Image Mapped |
# | Math Input |
# | Problem LaTex|
# | Adaptive Hint|
# | Video |
# Then I see the following components:
# | Component |
# | Discussion |
# | Blank HTML |
# | LaTex |
# | Blank Problem|
# | Dropdown |
# | Multi Choice |
# | Numerical |
# | Text Input |
# | Advanced |
# | Circuit |
# | Custom Python|
# | Image Mapped |
# | Math Input |
# | Problem LaTex|
# | Adaptive Hint|
# | Video |
Scenario: I can add single step components
Given I am in Studio editing a new unit
When I add this type of single step component:
| Component |
| Discussion |
| Video |
Then I see this type of single step component:
| Component |
| Discussion |
| Video |
#Scenario: I can delete Components
# Given I have opened a new course in studio
# And I am editing a new unit
# And I add the following components:
# | Component |
# | Discussion |
# | Blank HTML |
# | LaTex |
# | Blank Problem|
# | Dropdown |
# | Multi Choice |
# | Numerical |
# | Text Input |
# | Advanced |
# | Circuit |
# | Custom Python|
# | Image Mapped |
# | Math Input |
# | Problem LaTex|
# | Adaptive Hint|
# | Video |
# When I will confirm all alerts
# And I delete all components
# Then I see no components
Scenario: I can add HTML components
Given I am in Studio editing a new unit
When I add this type of HTML component:
| Component |
| Text |
| Announcement |
| E-text Written in LaTeX |
Then I see HTML components in this order:
| Component |
| Text |
| Announcement |
| E-text Written in LaTeX |
Scenario: I can add Common Problem components
Given I am in Studio editing a new unit
When I add this type of Problem component:
| Component |
| Blank Common Problem |
| Dropdown |
| Multiple Choice |
| Numerical Input |
| Text Input |
Then I see Problem components in this order:
| Component |
| Blank Common Problem |
| Dropdown |
| Multiple Choice |
| Numerical Input |
| Text Input |
Scenario: I can add Advanced Problem components
Given I am in Studio editing a new unit
When I add this type of Advanced Problem component:
| Component |
| Blank Advanced Problem |
| Circuit Schematic Builder |
| Custom Python-Evaluated Input |
| Drag and Drop |
| Image Mapped Input |
| Math Expression Input |
| Problem Written in LaTeX |
| Problem with Adaptive Hint |
Then I see Problem components in this order:
| Component |
| Blank Advanced Problem |
| Circuit Schematic Builder |
| Custom Python-Evaluated Input |
| Drag and Drop |
| Image Mapped Input |
| Math Expression Input |
| Problem Written in LaTeX |
| Problem with Adaptive Hint |
Scenario: I see a prompt on delete
Given I have opened a new course in studio
And I am editing a new unit
And I add the following components:
| Component |
| Discussion |
And I delete a component
Then I am shown a prompt
Given I am in Studio editing a new unit
And I add a "Discussion" "single step" component
And I delete a component
Then I am shown a prompt
Scenario: I can delete Components
Given I am in Studio editing a new unit
And I add a "Discussion" "single step" component
And I add a "Text" "HTML" component
And I add a "Blank Common Problem" "Problem" component
And I add a "Blank Advanced Problem" "Advanced Problem" component
And I delete all components
Then I see no components
Scenario: I see a notification on save
Given I have opened a new course in studio
And I am editing a new unit
And I add the following components:
| Component |
| Discussion |
Scenario: I see a notification on save
Given I am in Studio editing a new unit
And I add a "Discussion" "single step" component
And I edit and save a component
Then I am shown a notification
......@@ -2,38 +2,135 @@
#pylint: disable=W0621
from lettuce import world, step
from nose.tools import assert_true # pylint: disable=E0611
from nose.tools import assert_true, assert_in, assert_equal # pylint: disable=E0611
from common import create_studio_user, add_course_author, log_into_studio
DATA_LOCATION = 'i4x://edx/templates'
@step(u'I am editing a new unit')
@step(u'I am in Studio editing a new unit$')
def add_unit(step):
css_selectors = ['a.new-courseware-section-button', 'input.new-section-name-save', 'a.new-subsection-item',
'input.new-subsection-name-save', 'div.section-item a.expand-collapse-icon', 'a.new-unit-item']
world.clear_courses()
course = world.CourseFactory.create()
section = world.ItemFactory.create(parent_location=course.location)
world.ItemFactory.create(
parent_location=section.location,
category='sequential',
display_name='Subsection One',)
user = create_studio_user(is_staff=False)
add_course_author(user, course)
log_into_studio()
css_selectors = ['a.course-link', 'div.section-item a.expand-collapse-icon', 'a.new-unit-item']
for selector in css_selectors:
world.css_click(selector)
@step(u'I add the following components:')
def add_components(step):
for component in [step_hash['Component'] for step_hash in step.hashes]:
assert component in COMPONENT_DICTIONARY
for css in COMPONENT_DICTIONARY[component]['steps']:
world.css_click(css)
@step(u'I see the following components')
def check_components(step):
for component in [step_hash['Component'] for step_hash in step.hashes]:
assert component in COMPONENT_DICTIONARY
assert_true(COMPONENT_DICTIONARY[component]['found_func'](), "{} couldn't be found".format(component))
@step(u'I delete all components')
@step(u'I add this type of single step component:$')
def add_a_single_step_component(step):
for step_hash in step.hashes:
component = step_hash['Component']
assert_in(component, ['Discussion', 'Video'])
css_selector = 'a[data-type="{}"]'.format(component.lower())
world.css_click(css_selector)
@step(u'I see this type of single step component:$')
def see_a_single_step_component(step):
for step_hash in step.hashes:
component = step_hash['Component']
assert_in(component, ['Discussion', 'Video'])
component_css = 'section.xmodule_{}Module'.format(component)
assert_true(world.is_css_present(component_css),
"{} couldn't be found".format(component))
@step(u'I add this type of( Advanced)? (HTML|Problem) component:$')
def add_a_multi_step_component(step, is_advanced, category):
def click_advanced():
css = 'ul.problem-type-tabs a[href="#tab2"]'
world.css_click(css)
my_css = 'ul.problem-type-tabs li.ui-state-active a[href="#tab2"]'
assert(world.css_find(my_css))
def find_matching_link():
"""
Find the link with the specified text. There should be one and only one.
"""
# The tab shows links for the given category
links = world.css_find('div.new-component-{} a'.format(category))
# Find the link whose text matches what you're looking for
matched_links = [link for link in links if link.text == step_hash['Component']]
# There should be one and only one
assert_equal(len(matched_links), 1)
return matched_links[0]
def click_link():
link.click()
category = category.lower()
for step_hash in step.hashes:
css_selector = 'a[data-type="{}"]'.format(category)
world.css_click(css_selector)
world.wait_for_invisible(css_selector)
if is_advanced:
# Sometimes this click does not work if you go too fast.
world.retry_on_exception(click_advanced, max_attempts=5, ignored_exceptions=AssertionError)
# Retry this in case the list is empty because you tried too fast.
link = world.retry_on_exception(func=find_matching_link, ignored_exceptions=AssertionError)
# Wait for the link to be clickable. If you go too fast it is not.
world.retry_on_exception(click_link)
@step(u'I see (HTML|Problem) components in this order:')
def see_a_multi_step_component(step, category):
components = world.css_find('li.component section.xmodule_display')
for idx, step_hash in enumerate(step.hashes):
if category == 'HTML':
html_matcher = {
'Text':
'\n \n',
'Announcement':
'<p> Words of encouragement! This is a short note that most students will read. </p>',
'E-text Written in LaTeX':
'<h2>Example: E-text page</h2>',
}
assert_in(html_matcher[step_hash['Component']], components[idx].html)
else:
assert_in(step_hash['Component'].upper(), components[idx].text)
@step(u'I add a "([^"]*)" "([^"]*)" component$')
def add_component_catetory(step, component, category):
assert category in ('single step', 'HTML', 'Problem', 'Advanced Problem')
given_string = 'I add this type of {} component:'.format(category)
step.given('{}\n{}\n{}'.format(given_string, '|Component|', '|{}|'.format(component)))
@step(u'I delete all components$')
def delete_all_components(step):
for _ in range(len(COMPONENT_DICTIONARY)):
world.css_click('a.delete-button')
delete_btn_css = 'a.delete-button'
prompt_css = 'div#prompt-warning'
btn_css = '{} a.button.action-primary'.format(prompt_css)
saving_mini_css = 'div#page-notification .wrapper-notification-mini'
count = len(world.css_find('ol.components li.component'))
for _ in range(int(count)):
world.css_click(delete_btn_css)
assert_true(world.is_css_present('{}.is-shown'.format(prompt_css)),
msg='Waiting for the confirmation prompt to be shown')
# Pressing the button via css was not working reliably for the last component
# when run in Chrome.
if world.browser.driver_name is 'Chrome':
world.browser.execute_script("$('{}').click()".format(btn_css))
else:
world.css_click(btn_css)
# Wait for the saving notification to pop up then disappear
if world.is_css_present('{}.is-shown'.format(saving_mini_css)):
world.css_find('{}.is-hiding'.format(saving_mini_css))
@step(u'I see no components')
......@@ -50,88 +147,3 @@ def delete_one_component(step):
def edit_and_save_component(step):
world.css_click('.edit-button')
world.css_click('.save-button')
def step_selector_list(data_type, path, index=1):
selector_list = ['a[data-type="{}"]'.format(data_type)]
if index != 1:
selector_list.append('a[id="ui-id-{}"]'.format(index))
if path is not None:
selector_list.append('a[data-location="{}/{}/{}"]'.format(DATA_LOCATION, data_type, path))
return selector_list
def found_text_func(text):
return lambda: world.browser.is_text_present(text)
def found_css_func(css):
return lambda: world.is_css_present(css, wait_time=2)
COMPONENT_DICTIONARY = {
'Discussion': {
'steps': step_selector_list('discussion', None),
'found_func': found_css_func('section.xmodule_DiscussionModule')
},
'Blank HTML': {
'steps': step_selector_list('html', 'Blank_HTML_Page'),
#this one is a blank html so a more refined search is being done
'found_func': lambda: '\n \n' in [x.html for x in world.css_find('section.xmodule_HtmlModule')]
},
'LaTex': {
'steps': step_selector_list('html', 'E-text_Written_in_LaTeX'),
'found_func': found_text_func('EXAMPLE: E-TEXT PAGE')
},
'Blank Problem': {
'steps': step_selector_list('problem', 'Blank_Common_Problem'),
'found_func': found_text_func('BLANK COMMON PROBLEM')
},
'Dropdown': {
'steps': step_selector_list('problem', 'Dropdown'),
'found_func': found_text_func('DROPDOWN')
},
'Multi Choice': {
'steps': step_selector_list('problem', 'Multiple_Choice'),
'found_func': found_text_func('MULTIPLE CHOICE')
},
'Numerical': {
'steps': step_selector_list('problem', 'Numerical_Input'),
'found_func': found_text_func('NUMERICAL INPUT')
},
'Text Input': {
'steps': step_selector_list('problem', 'Text_Input'),
'found_func': found_text_func('TEXT INPUT')
},
'Advanced': {
'steps': step_selector_list('problem', 'Blank_Advanced_Problem', index=2),
'found_func': found_text_func('BLANK ADVANCED PROBLEM')
},
'Circuit': {
'steps': step_selector_list('problem', 'Circuit_Schematic_Builder', index=2),
'found_func': found_text_func('CIRCUIT SCHEMATIC BUILDER')
},
'Custom Python': {
'steps': step_selector_list('problem', 'Custom_Python-Evaluated_Input', index=2),
'found_func': found_text_func('CUSTOM PYTHON-EVALUATED INPUT')
},
'Image Mapped': {
'steps': step_selector_list('problem', 'Image_Mapped_Input', index=2),
'found_func': found_text_func('IMAGE MAPPED INPUT')
},
'Math Input': {
'steps': step_selector_list('problem', 'Math_Expression_Input', index=2),
'found_func': found_text_func('MATH EXPRESSION INPUT')
},
'Problem LaTex': {
'steps': step_selector_list('problem', 'Problem_Written_in_LaTeX', index=2),
'found_func': found_text_func('PROBLEM WRITTEN IN LATEX')
},
'Adaptive Hint': {
'steps': step_selector_list('problem', 'Problem_with_Adaptive_Hint', index=2),
'found_func': found_text_func('PROBLEM WITH ADAPTIVE HINT')
},
'Video': {
'steps': step_selector_list('video', None),
'found_func': found_css_func('section.xmodule_VideoModule')
}
}
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