Commit 29aa9331 by Waheed Ahmed

Converted annotation lettuce test into bok-choy test.

TNL-353
parent c57f1c81
"""
Annotation Component Page.
"""
from bok_choy.page_object import PageObject
from selenium.webdriver import ActionChains
class AnnotationComponentPage(PageObject):
"""
View of annotation component page.
"""
url = None
active_problem = 0
def is_browser_on_page(self):
return self.q(css='.annotatable-title').present
@property
def component_name(self):
"""
Return the current problem name.
"""
return self.q(css='.annotatable-title').text[0]
def click_reply_annotation(self, problem):
"""
Mouse over on annotation selector and click on "Reply to Annotation".
"""
annotation_span_selector = '.annotatable-span[data-problem-id="{}"]'.format(problem)
self.mouse_hover(self.browser.find_element_by_css_selector(annotation_span_selector))
self.wait_for_element_visibility(annotation_span_selector, "Reply to Annotation link is visible")
annotation_reply_selector = '.annotatable-reply[data-problem-id="{}"]'.format(problem)
self.q(css=annotation_reply_selector).click()
self.active_problem = problem
def active_problem_selector(self, sub_selector):
"""
Return css selector for current active problem with sub_selector.
"""
return 'div[data-problem-id="{}"] {}'.format(
self.q(css='.vert-{}'.format(self.active_problem+1)).map(
lambda el: el.get_attribute('data-id')).results[0],
sub_selector,
)
def mouse_hover(self, element):
"""
Mouse over on given element.
"""
mouse_hover_action = ActionChains(self.browser).move_to_element(element)
mouse_hover_action.perform()
def check_scroll_to_problem(self):
"""
Return visibility of active problem's input selector.
"""
annotation_input_selector = self.active_problem_selector('.annotation-input')
return self.q(css=annotation_input_selector).visible
def answer_problem(self):
"""
Submit correct answer for active problem.
"""
self.q(css=self.active_problem_selector('.comment')).fill('Test Response')
self.q(css=self.active_problem_selector('.tag[data-id="{}"]'.format(self.active_problem))).click()
self.q(css=self.active_problem_selector('.check')).click()
def check_feedback(self):
"""
Return visibility of active problem's feedback.
"""
self.wait_for_element_visibility(
self.active_problem_selector('.tag-status.correct'), "Correct is visible"
)
return self.q(css=self.active_problem_selector('.tag-status.correct')).visible
def click_return_to_annotation(self):
"""
Click on active problem's "Return to Annotation" link.
"""
self.q(css=self.active_problem_selector('.annotation-return')).click()
def check_scroll_to_annotation(self):
"""
Return visibility of active annotation component header.
"""
annotation_header_selector = '.annotation-header'
return self.q(css=annotation_header_selector).visible
# -*- coding: utf-8 -*-
"""
E2E tests for the LMS.
"""
import time
from .helpers import UniqueCourseTest
from ..pages.studio.auto_auth import AutoAuthPage
from ..pages.lms.courseware import CoursewarePage
from ..pages.lms.annotation_component import AnnotationComponentPage
from ..fixtures.course import CourseFixture, XBlockFixtureDesc
from ..fixtures.xqueue import XQueueResponseFixture
from textwrap import dedent
def _correctness(choice, target):
if choice == target:
return "correct"
elif abs(choice - target) == 1:
return "partially-correct"
else:
return "incorrect"
class AnnotatableProblemTest(UniqueCourseTest):
"""
Tests for annotation components.
"""
USERNAME = "STAFF_TESTER"
EMAIL = "johndoe@example.com"
DATA_TEMPLATE = dedent("""\
<annotatable>
<instructions>Instruction text</instructions>
<p>{}</p>
</annotatable>
""")
ANNOTATION_TEMPLATE = dedent("""\
Before {0}.
<annotation title="region {0}" body="Comment {0}" highlight="yellow" problem="{0}">
Region Contents {0}
</annotation>
After {0}.
""")
PROBLEM_TEMPLATE = dedent("""\
<problem max_attempts="1" weight="">
<annotationresponse>
<annotationinput>
<title>Question {number}</title>
<text>Region Contents {number}</text>
<comment>What number is this region?</comment>
<comment_prompt>Type your response below:</comment_prompt>
<tag_prompt>What number is this region?</tag_prompt>
<options>
{options}
</options>
</annotationinput>
</annotationresponse>
<solution>
This problem is checking region {number}
</solution>
</problem>
""")
OPTION_TEMPLATE = """<option choice="{correctness}">{number}</option>"""
def setUp(self):
super(AnnotatableProblemTest, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
# Install a course with two annotations and two annotations problems.
course_fix = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
self.annotation_count = 2
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
XBlockFixtureDesc('vertical', 'Test Annotation Vertical').add_children(
XBlockFixtureDesc('annotatable', 'Test Annotation Module',
data=self.DATA_TEMPLATE.format("\n".join(
self.ANNOTATION_TEMPLATE.format(i) for i in xrange(self.annotation_count)
))),
XBlockFixtureDesc('problem', 'Test Annotation Problem 0',
data=self.PROBLEM_TEMPLATE.format(number=0, options="\n".join(
self.OPTION_TEMPLATE.format(
number=k,
correctness=_correctness(k, 0))
for k in xrange(self.annotation_count)
))),
XBlockFixtureDesc('problem', 'Test Annotation Problem 1',
data=self.PROBLEM_TEMPLATE.format(number=1, options="\n".join(
self.OPTION_TEMPLATE.format(
number=k,
correctness=_correctness(k, 1))
for k in xrange(self.annotation_count)
)))
)
)
)
).install()
# Auto-auth register for the course.
AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
course_id=self.course_id, staff=False).visit()
def _goto_annotation_component_page(self):
"""
Open annotation component page with assertion.
"""
self.courseware_page.visit()
annotation_component_page = AnnotationComponentPage(self.browser)
self.assertEqual(
annotation_component_page.component_name, 'TEST ANNOTATION MODULE'.format()
)
return annotation_component_page
def test_annotation_component(self):
"""
Test annotation components links to annotation problems.
"""
annotation_component_page = self._goto_annotation_component_page()
for i in xrange(self.annotation_count):
annotation_component_page.click_reply_annotation(i)
self.assertTrue(annotation_component_page.check_scroll_to_problem())
annotation_component_page.answer_problem()
self.assertTrue(annotation_component_page.check_feedback())
annotation_component_page.click_return_to_annotation()
self.assertTrue(annotation_component_page.check_scroll_to_annotation())
...@@ -7,22 +7,3 @@ Feature: LMS.Annotatable Component ...@@ -7,22 +7,3 @@ Feature: LMS.Annotatable Component
When I view the annotatable component When I view the annotatable component
Then the annotatable component has rendered Then the annotatable component has rendered
And the annotatable component has 2 highlighted passages And the annotatable component has 2 highlighted passages
# Disabling due to frequent intermittent failures. TNL-353
# This features's acceptance tests should be rewritten in bok-choy, rather than fixed here.
#
# Scenario: An Annotatable component links to annonation problems in the LMS
# Given that a course has an annotatable component with 2 annotations
# And the course has 2 annotatation problems
# When I view the annotatable component
# And I click "Reply to annotation" on passage <problem>
# Then I am scrolled to that annotation problem
# When I answer that annotation problem
# Then I receive feedback on that annotation problem
# When I click "Return to annotation" on that problem
# Then I am scrolled to the annotatable component
#
# Examples:
# | problem |
# | 0 |
# | 1 |
import textwrap import textwrap
from lettuce import world, steps from lettuce import world, steps
from nose.tools import assert_in, assert_equals, assert_true from nose.tools import assert_in, assert_equals
from common import i_am_registered_for_the_course, visit_scenario_item from common import i_am_registered_for_the_course, visit_scenario_item
...@@ -100,74 +100,6 @@ class AnnotatableSteps(object): ...@@ -100,74 +100,6 @@ class AnnotatableSteps(object):
assert_equals(len(world.css_find('.annotatable-span.highlight')), count) assert_equals(len(world.css_find('.annotatable-span.highlight')), count)
assert_equals(len(world.css_find('.annotatable-span.highlight-yellow')), count) assert_equals(len(world.css_find('.annotatable-span.highlight-yellow')), count)
def add_problems(self, step, count):
r"""the course has (?P<count>\d+) annotatation problems$"""
count = int(count)
for i in xrange(count):
world.scenario_dict.setdefault('PROBLEMS', []).append(
world.ItemFactory(
parent_location=world.scenario_dict['ANNOTATION_VERTICAL'].location,
category='problem',
display_name="Test Annotation Problem {}".format(i),
data=PROBLEM_TEMPLATE.format(
number=i,
options="\n".join(
OPTION_TEMPLATE.format(
number=k,
correctness=_correctness(k, i)
)
for k in xrange(count)
)
)
)
)
def click_reply(self, step, problem):
r"""I click "Reply to annotation" on passage (?P<problem>\d+)$"""
problem = int(problem)
annotation_span_selector = '.annotatable-span[data-problem-id="{}"]'.format(problem)
world.css_find(annotation_span_selector).first.mouse_over()
annotation_reply_selector = '.annotatable-reply[data-problem-id="{}"]'.format(problem)
assert_equals(len(world.css_find(annotation_reply_selector)), 1)
world.css_click(annotation_reply_selector)
self.active_problem = problem
def active_problem_selector(self, subselector):
return 'div[data-problem-id="{}"] {}'.format(
world.scenario_dict['PROBLEMS'][self.active_problem].location.to_deprecated_string(),
subselector,
)
def check_scroll_to_problem(self, step):
r"""I am scrolled to that annotation problem$"""
annotation_input_selector = self.active_problem_selector('.annotation-input')
assert_true(world.css_visible(annotation_input_selector))
def answer_problem(self, step):
r"""I answer that annotation problem$"""
world.css_fill(self.active_problem_selector('.comment'), 'Test Response')
world.css_click(self.active_problem_selector('.tag[data-id="{}"]'.format(self.active_problem)))
world.css_click(self.active_problem_selector('.check'))
def check_feedback(self, step):
r"""I receive feedback on that annotation problem$"""
world.wait_for_visible(self.active_problem_selector('.tag-status.correct'))
assert_equals(len(world.css_find(self.active_problem_selector('.tag-status.correct'))), 1)
assert_equals(len(world.css_find(self.active_problem_selector('.show'))), 1)
def click_return_to(self, step):
r"""I click "Return to annotation" on that problem$"""
world.css_click(self.active_problem_selector('.annotation-return'))
def check_scroll_to_annotatable(self, step):
r"""I am scrolled to the annotatable component$"""
assert_true(world.css_visible('.annotation-header'))
# This line is required by @steps in order to actually bind the step # This line is required by @steps in order to actually bind the step
# regexes # regexes
AnnotatableSteps() AnnotatableSteps()
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