Remove notes tests.
This feature is not sufficiently important to warrant expensive UI tests.
This commit is contained in:
@@ -1,1504 +0,0 @@
|
||||
"""
|
||||
Test LMS Notes
|
||||
"""
|
||||
|
||||
|
||||
import random
|
||||
from datetime import datetime
|
||||
from unittest import skip
|
||||
from uuid import uuid4
|
||||
|
||||
from six.moves import range
|
||||
|
||||
from common.test.acceptance.fixtures.course import CourseFixture, XBlockFixtureDesc
|
||||
from common.test.acceptance.fixtures.edxnotes import EdxNotesFixture, Note, Range
|
||||
from common.test.acceptance.pages.common.auto_auth import AutoAuthPage
|
||||
from common.test.acceptance.pages.lms.course_home import CourseHomePage
|
||||
from common.test.acceptance.pages.lms.courseware import CoursewarePage
|
||||
from common.test.acceptance.pages.lms.edxnotes import EdxNotesPage, EdxNotesPageNoContent, EdxNotesUnitPage
|
||||
from common.test.acceptance.tests.helpers import EventsTestMixin, UniqueCourseTest
|
||||
from openedx.core.lib.tests import attr
|
||||
|
||||
|
||||
class EdxNotesTestMixin(UniqueCourseTest):
|
||||
"""
|
||||
Creates a course with initial data and contains useful helper methods.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Initialize pages and install a course fixture.
|
||||
"""
|
||||
super(EdxNotesTestMixin, self).setUp()
|
||||
self.courseware_page = CoursewarePage(self.browser, self.course_id)
|
||||
self.course_home_page = CourseHomePage(self.browser, self.course_id)
|
||||
self.note_unit_page = EdxNotesUnitPage(self.browser, self.course_id)
|
||||
self.notes_page = EdxNotesPage(self.browser, self.course_id)
|
||||
|
||||
self.username = str(uuid4().hex)[:5]
|
||||
self.email = "{}@email.com".format(self.username)
|
||||
|
||||
self.selector = "annotate-id"
|
||||
self.edxnotes_fixture = EdxNotesFixture()
|
||||
self.course_fixture = CourseFixture(
|
||||
self.course_info["org"], self.course_info["number"],
|
||||
self.course_info["run"], self.course_info["display_name"]
|
||||
)
|
||||
|
||||
self.course_fixture.add_advanced_settings({
|
||||
u"edxnotes": {u"value": True}
|
||||
})
|
||||
|
||||
self.course_fixture.add_children(
|
||||
XBlockFixtureDesc("chapter", "Test Section 1").add_children(
|
||||
XBlockFixtureDesc("sequential", "Test Subsection 1").add_children(
|
||||
XBlockFixtureDesc("vertical", "Test Unit 1").add_children(
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 1",
|
||||
data=u"""
|
||||
<p><span class="{}">Annotate this!</span></p>
|
||||
<p>Annotate this</p>
|
||||
""".format(self.selector)
|
||||
),
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 2",
|
||||
data=u"""<p><span class="{}">Annotate this!</span></p>""".format(self.selector)
|
||||
),
|
||||
),
|
||||
XBlockFixtureDesc("vertical", "Test Unit 2").add_children(
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 3",
|
||||
data=u"""<p><span class="{}">Annotate this!</span></p>""".format(self.selector)
|
||||
),
|
||||
),
|
||||
),
|
||||
XBlockFixtureDesc("sequential", "Test Subsection 2").add_children(
|
||||
XBlockFixtureDesc("vertical", "Test Unit 3").add_children(
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 4",
|
||||
data=u"""
|
||||
<p><span class="{}">Annotate this!</span></p>
|
||||
""".format(self.selector)
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
XBlockFixtureDesc("chapter", "Test Section 2").add_children(
|
||||
XBlockFixtureDesc("sequential", "Test Subsection 3").add_children(
|
||||
XBlockFixtureDesc("vertical", "Test Unit 4").add_children(
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 5",
|
||||
data=u"""
|
||||
<p><span class="{}">Annotate this!</span></p>
|
||||
""".format(self.selector)
|
||||
),
|
||||
XBlockFixtureDesc(
|
||||
"html",
|
||||
"Test HTML 6",
|
||||
data=u"""<p><span class="{}">Annotate this!</span></p>""".format(self.selector)
|
||||
),
|
||||
),
|
||||
),
|
||||
)).install()
|
||||
|
||||
self.addCleanup(self.edxnotes_fixture.cleanup)
|
||||
|
||||
AutoAuthPage(self.browser, username=self.username, email=self.email, course_id=self.course_id).visit()
|
||||
|
||||
def _add_notes(self):
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="html")
|
||||
notes_list = []
|
||||
for index, xblock in enumerate(xblocks):
|
||||
notes_list.append(
|
||||
Note(
|
||||
user=self.username,
|
||||
usage_id=xblock.locator,
|
||||
course_id=self.course_fixture._course_key,
|
||||
ranges=[Range(startOffset=index, endOffset=index + 5)]
|
||||
)
|
||||
)
|
||||
|
||||
self.edxnotes_fixture.create_notes(notes_list)
|
||||
self.edxnotes_fixture.install()
|
||||
|
||||
|
||||
@attr(shard=18)
|
||||
class EdxNotesDefaultInteractionsTest(EdxNotesTestMixin):
|
||||
"""
|
||||
Tests for creation, editing, deleting annotations inside annotatable components in LMS.
|
||||
"""
|
||||
def create_notes(self, components, offset=0):
|
||||
self.assertGreater(len(components), 0)
|
||||
index = offset
|
||||
for component in components:
|
||||
for note in component.create_note(".{}".format(self.selector)):
|
||||
note.text = u"TEST TEXT {}".format(index)
|
||||
index += 1
|
||||
|
||||
def edit_notes(self, components, offset=0):
|
||||
self.assertGreater(len(components), 0)
|
||||
index = offset
|
||||
for component in components:
|
||||
self.assertGreater(len(component.notes), 0)
|
||||
for note in component.edit_note():
|
||||
note.text = u"TEST TEXT {}".format(index)
|
||||
index += 1
|
||||
|
||||
def edit_tags_in_notes(self, components, tags):
|
||||
self.assertGreater(len(components), 0)
|
||||
index = 0
|
||||
for component in components:
|
||||
self.assertGreater(len(component.notes), 0)
|
||||
for note in component.edit_note():
|
||||
note.tags = tags[index]
|
||||
index += 1
|
||||
self.assertEqual(index, len(tags), "Number of supplied tags did not match components")
|
||||
|
||||
def remove_notes(self, components):
|
||||
self.assertGreater(len(components), 0)
|
||||
for component in components:
|
||||
self.assertGreater(len(component.notes), 0)
|
||||
component.remove_note()
|
||||
|
||||
def assert_notes_are_removed(self, components):
|
||||
for component in components:
|
||||
self.assertEqual(0, len(component.notes))
|
||||
|
||||
def assert_text_in_notes(self, notes):
|
||||
actual = [note.text for note in notes]
|
||||
expected = [u"TEST TEXT {}".format(i) for i in range(len(notes))]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def assert_tags_in_notes(self, notes, expected_tags):
|
||||
actual = [note.tags for note in notes]
|
||||
expected = [expected_tags[i] for i in range(len(notes))]
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
def test_can_create_notes(self):
|
||||
"""
|
||||
Scenario: User can create notes.
|
||||
Given I have a course with 3 annotatable components
|
||||
And I open the unit with 2 annotatable components
|
||||
When I add 2 notes for the first component and 1 note for the second
|
||||
Then I see that notes were correctly created
|
||||
When I change sequential position to "2"
|
||||
And I add note for the annotatable component on the page
|
||||
Then I see that note was correctly created
|
||||
When I refresh the page
|
||||
Then I see that note was correctly stored
|
||||
When I change sequential position to "1"
|
||||
Then I see that notes were correctly stored on the page
|
||||
"""
|
||||
self.note_unit_page.visit()
|
||||
|
||||
components = self.note_unit_page.components
|
||||
self.create_notes(components)
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
self.courseware_page.go_to_sequential_position(2)
|
||||
components = self.note_unit_page.components
|
||||
self.create_notes(components)
|
||||
|
||||
components = self.note_unit_page.refresh()
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
self.courseware_page.go_to_sequential_position(1)
|
||||
components = self.note_unit_page.components
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
def test_can_edit_notes(self):
|
||||
"""
|
||||
Scenario: User can edit notes.
|
||||
Given I have a course with 3 components with notes
|
||||
And I open the unit with 2 annotatable components
|
||||
When I change text in the notes
|
||||
Then I see that notes were correctly changed
|
||||
When I change sequential position to "2"
|
||||
And I change the note on the page
|
||||
Then I see that note was correctly changed
|
||||
When I refresh the page
|
||||
Then I see that edited note was correctly stored
|
||||
When I change sequential position to "1"
|
||||
Then I see that edited notes were correctly stored on the page
|
||||
"""
|
||||
self._add_notes()
|
||||
self.note_unit_page.visit()
|
||||
|
||||
components = self.note_unit_page.components
|
||||
self.edit_notes(components)
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
self.courseware_page.go_to_sequential_position(2)
|
||||
components = self.note_unit_page.components
|
||||
self.edit_notes(components)
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
components = self.note_unit_page.refresh()
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
self.courseware_page.go_to_sequential_position(1)
|
||||
components = self.note_unit_page.components
|
||||
self.assert_text_in_notes(self.note_unit_page.notes)
|
||||
|
||||
def test_can_create_note_with_tags(self):
|
||||
"""
|
||||
Scenario: a user of notes can define one with tags
|
||||
Given I have a course with 3 annotatable components
|
||||
And I open the unit with 2 annotatable components
|
||||
When I add a note with tags for the first component
|
||||
And I refresh the page
|
||||
Then I see that note was correctly stored with its tags
|
||||
"""
|
||||
self.note_unit_page.visit()
|
||||
|
||||
components = self.note_unit_page.components
|
||||
for note in components[0].create_note(".{}".format(self.selector)):
|
||||
note.tags = ["fruit", "tasty"]
|
||||
|
||||
self.note_unit_page.refresh()
|
||||
self.assertEqual(["fruit", "tasty"], self.note_unit_page.notes[0].tags)
|
||||
|
||||
def test_can_change_tags(self):
|
||||
"""
|
||||
Scenario: a user of notes can edit tags on notes
|
||||
Given I have a course with 3 components with notes
|
||||
When I open the unit with 2 annotatable components
|
||||
And I edit tags on the notes for the 2 annotatable components
|
||||
Then I see that the tags were correctly changed
|
||||
And I again edit tags on the notes for the 2 annotatable components
|
||||
And I refresh the page
|
||||
Then I see that the tags were correctly changed
|
||||
"""
|
||||
self._add_notes()
|
||||
self.note_unit_page.visit()
|
||||
|
||||
components = self.note_unit_page.components
|
||||
self.edit_tags_in_notes(components, [["hard"], ["apple", "pear"]])
|
||||
self.assert_tags_in_notes(self.note_unit_page.notes, [["hard"], ["apple", "pear"]])
|
||||
|
||||
self.edit_tags_in_notes(components, [[], ["avocado"]])
|
||||
self.assert_tags_in_notes(self.note_unit_page.notes, [[], ["avocado"]])
|
||||
|
||||
self.note_unit_page.refresh()
|
||||
self.assert_tags_in_notes(self.note_unit_page.notes, [[], ["avocado"]])
|
||||
|
||||
def test_sr_labels(self):
|
||||
"""
|
||||
Scenario: screen reader labels exist for text and tags fields
|
||||
Given I have a course with 3 components with notes
|
||||
When I open the unit with 2 annotatable components
|
||||
And I open the editor for each note
|
||||
Then the text and tags fields both have screen reader labels
|
||||
"""
|
||||
self._add_notes()
|
||||
self.note_unit_page.visit()
|
||||
|
||||
# First note is in the first annotatable component, will have field indexes 0 and 1.
|
||||
for note in self.note_unit_page.components[0].edit_note():
|
||||
self.assertTrue(note.has_sr_label(0, 0, "Note"))
|
||||
self.assertTrue(note.has_sr_label(1, 1, "Tags (space-separated)"))
|
||||
|
||||
# Second note is in the second annotatable component, will have field indexes 2 and 3.
|
||||
for note in self.note_unit_page.components[1].edit_note():
|
||||
self.assertTrue(note.has_sr_label(0, 2, "Note"))
|
||||
self.assertTrue(note.has_sr_label(1, 3, "Tags (space-separated)"))
|
||||
|
||||
|
||||
@attr(shard=4)
|
||||
class EdxNotesPageTest(EventsTestMixin, EdxNotesTestMixin):
|
||||
"""
|
||||
Tests for Notes page.
|
||||
"""
|
||||
def _add_notes(self, notes_list):
|
||||
self.edxnotes_fixture.create_notes(notes_list)
|
||||
self.edxnotes_fixture.install()
|
||||
|
||||
def _add_default_notes(self, tags=None, extra_notes=0):
|
||||
"""
|
||||
Creates 5 test notes by default & number of extra_notes will be created if specified.
|
||||
If tags are not specified, will populate the notes with some test tag data.
|
||||
If tags are specified, they will be used for each of the 3 notes that have tags.
|
||||
"""
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="html")
|
||||
# pylint: disable=attribute-defined-outside-init
|
||||
self.raw_note_list = [
|
||||
Note(
|
||||
usage_id=xblocks[4].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="First note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2011, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[2].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="",
|
||||
quote=u"Annotate this",
|
||||
updated=datetime(2012, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
tags=["Review", "cool"] if tags is None else tags
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[0].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="Third note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2013, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
ranges=[Range(startOffset=0, endOffset=18)],
|
||||
tags=["Cool", "TODO"] if tags is None else tags
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[3].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="Fourth note",
|
||||
quote="",
|
||||
updated=datetime(2014, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
tags=["review"] if tags is None else tags
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[1].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="Fifth note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2015, 1, 1, 1, 1, 1, 1).isoformat()
|
||||
),
|
||||
]
|
||||
if extra_notes > 0:
|
||||
for __ in range(extra_notes):
|
||||
self.raw_note_list.append(
|
||||
Note(
|
||||
usage_id=xblocks[random.choice([0, 1, 2, 3, 4, 5])].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key, # pylint: disable=protected-access
|
||||
text="Fourth note",
|
||||
quote="",
|
||||
updated=datetime(2014, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
tags=["review"] if tags is None else tags
|
||||
)
|
||||
)
|
||||
self._add_notes(self.raw_note_list)
|
||||
|
||||
def assertNoteContent(self, item, text=None, quote=None, unit_name=None, time_updated=None, tags=None):
|
||||
""" Verifies the expected properties of the note. """
|
||||
self.assertEqual(text, item.text)
|
||||
if item.quote is not None:
|
||||
self.assertIn(quote, item.quote)
|
||||
else:
|
||||
self.assertIsNone(quote)
|
||||
self.assertEqual(unit_name, item.unit_name)
|
||||
self.assertEqual(time_updated, item.time_updated)
|
||||
self.assertEqual(tags, item.tags)
|
||||
|
||||
def assertChapterContent(self, item, title=None, subtitles=None):
|
||||
"""
|
||||
Verifies the expected title and subsection titles (subtitles) for the given chapter.
|
||||
"""
|
||||
self.assertEqual(item.title, title)
|
||||
self.assertEqual(item.subtitles, subtitles)
|
||||
|
||||
def assertGroupContent(self, item, title=None, notes=None):
|
||||
"""
|
||||
Verifies the expected title and child notes for the given group.
|
||||
"""
|
||||
self.assertEqual(item.title, title)
|
||||
self.assertEqual(item.notes, notes)
|
||||
|
||||
def assert_viewed_event(self, view=None):
|
||||
"""
|
||||
Verifies that the correct view event was captured for the Notes page.
|
||||
"""
|
||||
# There will always be an initial event for "Recent Activity" because that is the default view.
|
||||
# If view is something besides "Recent Activity", expect 2 events, with the second one being
|
||||
# the view name passed in.
|
||||
if view == 'Recent Activity':
|
||||
view = None
|
||||
actual_events = self.wait_for_events(
|
||||
event_filter={'event_type': 'edx.course.student_notes.notes_page_viewed'},
|
||||
number_of_matches=1 if view is None else 2
|
||||
)
|
||||
expected_events = [{'event': {'view': 'Recent Activity'}}]
|
||||
if view:
|
||||
expected_events.append({'event': {'view': view}})
|
||||
self.assert_events_match(expected_events, actual_events)
|
||||
|
||||
def assert_unit_link_event(self, usage_id, view):
|
||||
"""
|
||||
Verifies that the correct used_unit_link event was captured for the Notes page.
|
||||
"""
|
||||
actual_events = self.wait_for_events(
|
||||
event_filter={'event_type': 'edx.course.student_notes.used_unit_link'},
|
||||
number_of_matches=1
|
||||
)
|
||||
expected_events = [
|
||||
{'event': {'component_usage_id': usage_id, 'view': view}}
|
||||
]
|
||||
self.assert_events_match(expected_events, actual_events)
|
||||
|
||||
def assert_search_event(self, search_string, number_of_results):
|
||||
"""
|
||||
Verifies that the correct searched event was captured for the Notes page.
|
||||
"""
|
||||
actual_events = self.wait_for_events(
|
||||
event_filter={'event_type': 'edx.course.student_notes.searched'},
|
||||
number_of_matches=1
|
||||
)
|
||||
expected_events = [
|
||||
{'event': {'search_string': search_string, 'number_of_results': number_of_results}}
|
||||
]
|
||||
self.assert_events_match(expected_events, actual_events)
|
||||
|
||||
def _verify_pagination_info(
|
||||
self,
|
||||
notes_count_on_current_page,
|
||||
header_text,
|
||||
previous_button_enabled,
|
||||
next_button_enabled,
|
||||
current_page_number,
|
||||
total_pages
|
||||
):
|
||||
"""
|
||||
Verify pagination info
|
||||
"""
|
||||
self.assertEqual(self.notes_page.count(), notes_count_on_current_page)
|
||||
self.assertEqual(self.notes_page.get_pagination_header_text(), header_text)
|
||||
|
||||
if total_pages > 1:
|
||||
self.assertEqual(self.notes_page.footer_visible, True)
|
||||
self.assertEqual(self.notes_page.is_previous_page_button_enabled(), previous_button_enabled)
|
||||
self.assertEqual(self.notes_page.is_next_page_button_enabled(), next_button_enabled)
|
||||
self.assertEqual(self.notes_page.get_current_page_number(), current_page_number)
|
||||
self.assertEqual(self.notes_page.get_total_pages, total_pages)
|
||||
else:
|
||||
self.assertEqual(self.notes_page.footer_visible, False)
|
||||
|
||||
def search_and_verify(self):
|
||||
"""
|
||||
Add, search and verify notes.
|
||||
"""
|
||||
self._add_default_notes(extra_notes=22)
|
||||
self.notes_page.visit()
|
||||
# Run the search
|
||||
self.notes_page.search("note")
|
||||
# No error message appears
|
||||
self.assertFalse(self.notes_page.is_error_visible)
|
||||
self.assertIn(u"Search Results", self.notes_page.tabs)
|
||||
|
||||
self.assertEqual(self.notes_page.get_total_pages, 2)
|
||||
|
||||
def test_no_content(self):
|
||||
"""
|
||||
Scenario: User can see `No content` message.
|
||||
Given I have a course without notes
|
||||
When I open Notes page
|
||||
Then I see only "You do not have any notes within the course." message
|
||||
"""
|
||||
notes_page_empty = EdxNotesPageNoContent(self.browser, self.course_id)
|
||||
notes_page_empty.visit()
|
||||
self.assertIn(
|
||||
"You have not made any notes in this course yet. Other students in this course are using notes to:",
|
||||
notes_page_empty.no_content_text)
|
||||
|
||||
def test_notes_works_correctly_with_xss(self):
|
||||
"""
|
||||
Scenario: Note text & tags should be HTML and JS escaped
|
||||
Given I am enrolled in a course with notes enabled
|
||||
When I visit the Notes page, with a Notes text and tag containing HTML characters like < and >
|
||||
Then the text and tags appear as expected due to having been properly escaped
|
||||
"""
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="html")
|
||||
self._add_notes([
|
||||
Note(
|
||||
usage_id=xblocks[0].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key, # pylint: disable=protected-access
|
||||
text='<script>alert("XSS")</script>',
|
||||
quote="quote",
|
||||
updated=datetime(2014, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
tags=['<script>alert("XSS")</script>']
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[1].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key, # pylint: disable=protected-access
|
||||
text='<b>bold</b>',
|
||||
quote="quote",
|
||||
updated=datetime(2014, 2, 1, 1, 1, 1, 1).isoformat(),
|
||||
tags=['<i>bold</i>']
|
||||
)
|
||||
])
|
||||
self.notes_page.visit()
|
||||
|
||||
notes = self.notes_page.notes
|
||||
self.assertEqual(len(notes), 2)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[0],
|
||||
quote=u"quote",
|
||||
text='<b>bold</b>',
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Feb 01, 2014 at 01:01 UTC",
|
||||
tags=['<i>bold</i>']
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[1],
|
||||
quote=u"quote",
|
||||
text='<script>alert("XSS")</script>',
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2014 at 01:01 UTC",
|
||||
tags=['<script>alert("XSS")</script>']
|
||||
)
|
||||
|
||||
def test_recent_activity_view(self):
|
||||
"""
|
||||
Scenario: User can view all notes by recent activity.
|
||||
Given I have a course with 5 notes
|
||||
When I open Notes page
|
||||
Then I see 5 notes sorted by the updated date
|
||||
And I see correct content in the notes
|
||||
And an event has fired indicating that the Recent Activity view was selected
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit()
|
||||
notes = self.notes_page.notes
|
||||
self.assertEqual(len(notes), 5)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[0],
|
||||
quote=u"Annotate this",
|
||||
text=u"Fifth note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2015 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[1],
|
||||
text=u"Fourth note",
|
||||
unit_name="Test Unit 3",
|
||||
time_updated="Jan 01, 2014 at 01:01 UTC",
|
||||
tags=["review"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[2],
|
||||
quote="Annotate this",
|
||||
text=u"Third note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2013 at 01:01 UTC",
|
||||
tags=["Cool", "TODO"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[3],
|
||||
quote=u"Annotate this",
|
||||
unit_name="Test Unit 2",
|
||||
time_updated="Jan 01, 2012 at 01:01 UTC",
|
||||
tags=["Review", "cool"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[4],
|
||||
quote=u"Annotate this",
|
||||
text=u"First note",
|
||||
unit_name="Test Unit 4",
|
||||
time_updated="Jan 01, 2011 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assert_viewed_event()
|
||||
|
||||
def test_course_structure_view(self):
|
||||
"""
|
||||
Scenario: User can view all notes by location in Course.
|
||||
Given I have a course with 5 notes
|
||||
When I open Notes page
|
||||
And I switch to "Location in Course" view
|
||||
Then I see 2 groups, 3 sections and 5 notes
|
||||
And I see correct content in the notes and groups
|
||||
And an event has fired indicating that the Location in Course view was selected
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit().switch_to_tab("structure")
|
||||
|
||||
notes = self.notes_page.notes
|
||||
groups = self.notes_page.chapter_groups
|
||||
sections = self.notes_page.subsection_groups
|
||||
self.assertEqual(len(notes), 5)
|
||||
self.assertEqual(len(groups), 2)
|
||||
self.assertEqual(len(sections), 3)
|
||||
|
||||
self.assertChapterContent(
|
||||
groups[0],
|
||||
title=u"Test Section 1",
|
||||
subtitles=[u"Test Subsection 1", u"Test Subsection 2"]
|
||||
)
|
||||
|
||||
self.assertGroupContent(
|
||||
sections[0],
|
||||
title=u"Test Subsection 1",
|
||||
notes=[u"Fifth note", u"Third note", None]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[0],
|
||||
quote=u"Annotate this",
|
||||
text=u"Fifth note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2015 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[1],
|
||||
quote=u"Annotate this",
|
||||
text=u"Third note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2013 at 01:01 UTC",
|
||||
tags=["Cool", "TODO"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[2],
|
||||
quote=u"Annotate this",
|
||||
unit_name="Test Unit 2",
|
||||
time_updated="Jan 01, 2012 at 01:01 UTC",
|
||||
tags=["Review", "cool"]
|
||||
)
|
||||
|
||||
self.assertGroupContent(
|
||||
sections[1],
|
||||
title=u"Test Subsection 2",
|
||||
notes=[u"Fourth note"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[3],
|
||||
text=u"Fourth note",
|
||||
unit_name="Test Unit 3",
|
||||
time_updated="Jan 01, 2014 at 01:01 UTC",
|
||||
tags=["review"]
|
||||
)
|
||||
|
||||
self.assertChapterContent(
|
||||
groups[1],
|
||||
title=u"Test Section 2",
|
||||
subtitles=[u"Test Subsection 3"],
|
||||
)
|
||||
|
||||
self.assertGroupContent(
|
||||
sections[2],
|
||||
title=u"Test Subsection 3",
|
||||
notes=[u"First note"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[4],
|
||||
quote=u"Annotate this",
|
||||
text=u"First note",
|
||||
unit_name="Test Unit 4",
|
||||
time_updated="Jan 01, 2011 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assert_viewed_event('Location in Course')
|
||||
|
||||
def test_tags_view(self):
|
||||
"""
|
||||
Scenario: User can view all notes by associated tags.
|
||||
Given I have a course with 5 notes and I am viewing the Notes page
|
||||
When I switch to the "Tags" view
|
||||
Then I see 4 tag groups
|
||||
And I see correct content in the notes and groups
|
||||
And an event has fired indicating that the Tags view was selected
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit().switch_to_tab("tags")
|
||||
|
||||
notes = self.notes_page.notes
|
||||
groups = self.notes_page.tag_groups
|
||||
self.assertEqual(len(notes), 7)
|
||||
self.assertEqual(len(groups), 4)
|
||||
|
||||
# Tag group "cool"
|
||||
self.assertGroupContent(
|
||||
groups[0],
|
||||
title=u"cool (2)",
|
||||
notes=[u"Third note", None]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[0],
|
||||
quote=u"Annotate this",
|
||||
text=u"Third note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2013 at 01:01 UTC",
|
||||
tags=["Cool", "TODO"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[1],
|
||||
quote=u"Annotate this",
|
||||
unit_name="Test Unit 2",
|
||||
time_updated="Jan 01, 2012 at 01:01 UTC",
|
||||
tags=["Review", "cool"]
|
||||
)
|
||||
|
||||
# Tag group "review"
|
||||
self.assertGroupContent(
|
||||
groups[1],
|
||||
title=u"review (2)",
|
||||
notes=[u"Fourth note", None]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[2],
|
||||
text=u"Fourth note",
|
||||
unit_name="Test Unit 3",
|
||||
time_updated="Jan 01, 2014 at 01:01 UTC",
|
||||
tags=["review"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[3],
|
||||
quote=u"Annotate this",
|
||||
unit_name="Test Unit 2",
|
||||
time_updated="Jan 01, 2012 at 01:01 UTC",
|
||||
tags=["Review", "cool"]
|
||||
)
|
||||
|
||||
# Tag group "todo"
|
||||
self.assertGroupContent(
|
||||
groups[2],
|
||||
title=u"todo (1)",
|
||||
notes=["Third note"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[4],
|
||||
quote=u"Annotate this",
|
||||
text=u"Third note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2013 at 01:01 UTC",
|
||||
tags=["Cool", "TODO"]
|
||||
)
|
||||
|
||||
# Notes with no tags
|
||||
self.assertGroupContent(
|
||||
groups[3],
|
||||
title=u"[no tags] (2)",
|
||||
notes=["Fifth note", "First note"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[5],
|
||||
quote=u"Annotate this",
|
||||
text=u"Fifth note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2015 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[6],
|
||||
quote=u"Annotate this",
|
||||
text=u"First note",
|
||||
unit_name="Test Unit 4",
|
||||
time_updated="Jan 01, 2011 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assert_viewed_event('Tags')
|
||||
|
||||
def test_easy_access_from_notes_page(self):
|
||||
"""
|
||||
Scenario: Ensure that the link to the Unit works correctly.
|
||||
Given I have a course with 5 notes
|
||||
When I open Notes page
|
||||
And I click on the first unit link
|
||||
Then I see correct text on the unit page and a unit link event was fired
|
||||
When go back to the Notes page
|
||||
And I switch to "Location in Course" view
|
||||
And I click on the second unit link
|
||||
Then I see correct text on the unit page and a unit link event was fired
|
||||
When go back to the Notes page
|
||||
And I switch to "Tags" view
|
||||
And I click on the first unit link
|
||||
Then I see correct text on the unit page and a unit link event was fired
|
||||
When go back to the Notes page
|
||||
And I run the search with "Fifth" query
|
||||
And I click on the first unit link
|
||||
Then I see correct text on the unit page and a unit link event was fired
|
||||
"""
|
||||
def assert_page(note, usage_id, view):
|
||||
""" Verify that clicking on the unit link works properly. """
|
||||
quote = note.quote
|
||||
note.go_to_unit()
|
||||
self.courseware_page.wait_for_page()
|
||||
self.assertIn(quote, self.courseware_page.xblock_component_html_content())
|
||||
self.assert_unit_link_event(usage_id, view)
|
||||
self.reset_event_tracking()
|
||||
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit()
|
||||
note = self.notes_page.notes[0]
|
||||
assert_page(note, self.raw_note_list[4]['usage_id'], "Recent Activity")
|
||||
|
||||
self.notes_page.visit()
|
||||
self.notes_page.switch_to_tab("structure")
|
||||
note = self.notes_page.notes[1]
|
||||
assert_page(note, self.raw_note_list[2]['usage_id'], "Location in Course")
|
||||
|
||||
self.notes_page.visit()
|
||||
self.notes_page.switch_to_tab("tags")
|
||||
note = self.notes_page.notes[0]
|
||||
assert_page(note, self.raw_note_list[2]['usage_id'], "Tags")
|
||||
|
||||
self.notes_page.visit()
|
||||
self.notes_page.search("Fifth")
|
||||
self.notes_page.wait_for_ajax()
|
||||
note = self.notes_page.notes[0]
|
||||
assert_page(note, self.raw_note_list[4]['usage_id'], "Search Results")
|
||||
|
||||
def test_search_behaves_correctly(self):
|
||||
"""
|
||||
Scenario: Searching behaves correctly.
|
||||
Given I have a course with 5 notes
|
||||
When I open Notes page
|
||||
When I run the search with " " query
|
||||
Then I see the following error message "Please enter a term in the search field."
|
||||
And I do not see "Search Results" tab
|
||||
When I run the search with "note" query
|
||||
Then I see that error message disappears
|
||||
And I see that "Search Results" tab appears with 4 notes found
|
||||
And an event has fired indicating that the Search Results view was selected
|
||||
And an event has fired recording the search that was performed
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit()
|
||||
# Run the search with whitespaces only
|
||||
self.notes_page.search(" ")
|
||||
# Displays error message
|
||||
self.assertTrue(self.notes_page.is_error_visible)
|
||||
self.assertEqual(self.notes_page.error_text, u"Please enter a term in the search field.")
|
||||
# Search results tab does not appear
|
||||
self.assertNotIn(u"Search Results", self.notes_page.tabs)
|
||||
# Run the search with correct query
|
||||
self.notes_page.search("note")
|
||||
# Error message disappears
|
||||
self.assertFalse(self.notes_page.is_error_visible)
|
||||
self.assertIn(u"Search Results", self.notes_page.tabs)
|
||||
notes = self.notes_page.notes
|
||||
self.assertEqual(len(notes), 4)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[0],
|
||||
quote=u"Annotate this",
|
||||
text=u"Fifth note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2015 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[1],
|
||||
text=u"Fourth note",
|
||||
unit_name="Test Unit 3",
|
||||
time_updated="Jan 01, 2014 at 01:01 UTC",
|
||||
tags=["review"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[2],
|
||||
quote="Annotate this",
|
||||
text=u"Third note",
|
||||
unit_name="Test Unit 1",
|
||||
time_updated="Jan 01, 2013 at 01:01 UTC",
|
||||
tags=["Cool", "TODO"]
|
||||
)
|
||||
|
||||
self.assertNoteContent(
|
||||
notes[3],
|
||||
quote=u"Annotate this",
|
||||
text=u"First note",
|
||||
unit_name="Test Unit 4",
|
||||
time_updated="Jan 01, 2011 at 01:01 UTC"
|
||||
)
|
||||
|
||||
self.assert_viewed_event('Search Results')
|
||||
self.assert_search_event('note', 4)
|
||||
|
||||
@skip("scroll to tag functionality is disabled")
|
||||
def test_scroll_to_tag_recent_activity(self):
|
||||
"""
|
||||
Scenario: Can scroll to a tag group from the Recent Activity view (default view)
|
||||
Given I have a course with 5 notes and I open the Notes page
|
||||
When I click on a tag associated with a note
|
||||
Then the Tags view tab gets focus and I scroll to the section of notes associated with that tag
|
||||
"""
|
||||
self._add_default_notes(["apple", "banana", "kiwi", "pear", "pumpkin", "squash", "zucchini"])
|
||||
self.notes_page.visit()
|
||||
self._scroll_to_tag_and_verify("pear", 3)
|
||||
|
||||
@skip("scroll to tag functionality is disabled")
|
||||
def test_scroll_to_tag_course_structure(self):
|
||||
"""
|
||||
Scenario: Can scroll to a tag group from the Course Structure view
|
||||
Given I have a course with 5 notes and I open the Notes page and select the Course Structure view
|
||||
When I click on a tag associated with a note
|
||||
Then the Tags view tab gets focus and I scroll to the section of notes associated with that tag
|
||||
"""
|
||||
self._add_default_notes(["apple", "banana", "kiwi", "pear", "pumpkin", "squash", "zucchini"])
|
||||
self.notes_page.visit().switch_to_tab("structure")
|
||||
self._scroll_to_tag_and_verify("squash", 5)
|
||||
|
||||
@skip("scroll to tag functionality is disabled")
|
||||
def test_scroll_to_tag_search(self):
|
||||
"""
|
||||
Scenario: Can scroll to a tag group from the Search Results view
|
||||
Given I have a course with 5 notes and I open the Notes page and perform a search
|
||||
Then the Search view tab opens and gets focus
|
||||
And when I click on a tag associated with a note
|
||||
Then the Tags view tab gets focus and I scroll to the section of notes associated with that tag
|
||||
"""
|
||||
self._add_default_notes(["apple", "banana", "kiwi", "pear", "pumpkin", "squash", "zucchini"])
|
||||
self.notes_page.visit().search("note")
|
||||
self._scroll_to_tag_and_verify("pumpkin", 4)
|
||||
|
||||
@skip("scroll to tag functionality is disabled")
|
||||
def test_scroll_to_tag_from_tag_view(self):
|
||||
"""
|
||||
Scenario: Can scroll to a tag group from the Tags view
|
||||
Given I have a course with 5 notes and I open the Notes page and select the Tag view
|
||||
When I click on a tag associated with a note
|
||||
Then I scroll to the section of notes associated with that tag
|
||||
"""
|
||||
self._add_default_notes(["apple", "banana", "kiwi", "pear", "pumpkin", "squash", "zucchini"])
|
||||
self.notes_page.visit().switch_to_tab("tags")
|
||||
self._scroll_to_tag_and_verify("kiwi", 2)
|
||||
|
||||
def _scroll_to_tag_and_verify(self, tag_name, group_index):
|
||||
""" Helper method for all scroll to tag tests """
|
||||
self.notes_page.notes[1].go_to_tag(tag_name)
|
||||
|
||||
# Because all the notes (with tags) have the same tags, they will end up ordered alphabetically.
|
||||
pear_group = self.notes_page.tag_groups[group_index]
|
||||
self.assertEqual(tag_name + " (3)", pear_group.title)
|
||||
self.assertTrue(pear_group.scrolled_to_top(group_index))
|
||||
|
||||
def test_tabs_behaves_correctly(self):
|
||||
"""
|
||||
Scenario: Tabs behaves correctly.
|
||||
Given I have a course with 5 notes
|
||||
When I open Notes page
|
||||
Then I see only "Recent Activity", "Location in Course", and "Tags" tabs
|
||||
When I run the search with "note" query
|
||||
And I see that "Search Results" tab appears with 4 notes found
|
||||
Then I switch to "Recent Activity" tab
|
||||
And I see all 5 notes
|
||||
Then I switch to "Location in Course" tab
|
||||
And I see all 2 groups and 5 notes
|
||||
When I switch back to "Search Results" tab
|
||||
Then I can still see 4 notes found
|
||||
When I close "Search Results" tab
|
||||
Then I see that "Recent Activity" tab becomes active
|
||||
And "Search Results" tab disappears
|
||||
And I see all 5 notes
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit()
|
||||
|
||||
# We're on Recent Activity tab.
|
||||
self.assertEqual(len(self.notes_page.tabs), 3)
|
||||
self.assertEqual([u"Recent Activity", u"Location in Course", u"Tags"], self.notes_page.tabs)
|
||||
self.notes_page.search("note")
|
||||
# We're on Search Results tab
|
||||
self.assertEqual(len(self.notes_page.tabs), 4)
|
||||
self.assertIn(u"Search Results", self.notes_page.tabs)
|
||||
self.assertEqual(len(self.notes_page.notes), 4)
|
||||
# We can switch on Recent Activity tab and back.
|
||||
self.notes_page.switch_to_tab("recent")
|
||||
self.assertEqual(len(self.notes_page.notes), 5)
|
||||
self.notes_page.switch_to_tab("structure")
|
||||
self.assertEqual(len(self.notes_page.chapter_groups), 2)
|
||||
self.assertEqual(len(self.notes_page.notes), 5)
|
||||
self.notes_page.switch_to_tab("search")
|
||||
self.assertEqual(len(self.notes_page.notes), 4)
|
||||
# Can close search results page
|
||||
self.notes_page.close_tab()
|
||||
self.assertEqual(len(self.notes_page.tabs), 3)
|
||||
self.assertNotIn(u"Search Results", self.notes_page.tabs)
|
||||
self.assertEqual(len(self.notes_page.notes), 5)
|
||||
|
||||
def test_open_note_when_accessed_from_notes_page(self):
|
||||
"""
|
||||
Scenario: Ensure that the link to the Unit opens a note only once.
|
||||
Given I have a course with 2 sequentials that contain respectively one note and two notes
|
||||
When I open Notes page
|
||||
And I click on the first unit link
|
||||
Then I see the note opened on the unit page
|
||||
When I switch to the second sequential
|
||||
I do not see any note opened
|
||||
When I switch back to first sequential
|
||||
I do not see any note opened
|
||||
"""
|
||||
xblocks = self.course_fixture.get_nested_xblocks(category="html")
|
||||
self._add_notes([
|
||||
Note(
|
||||
usage_id=xblocks[1].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="Third note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2012, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
ranges=[Range(startOffset=0, endOffset=14)],
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[2].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="Second note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2013, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
ranges=[Range(startOffset=0, endOffset=14)],
|
||||
),
|
||||
Note(
|
||||
usage_id=xblocks[0].locator,
|
||||
user=self.username,
|
||||
course_id=self.course_fixture._course_key,
|
||||
text="First note",
|
||||
quote="Annotate this",
|
||||
updated=datetime(2014, 1, 1, 1, 1, 1, 1).isoformat(),
|
||||
ranges=[Range(startOffset=0, endOffset=14)],
|
||||
),
|
||||
])
|
||||
self.notes_page.visit()
|
||||
item = self.notes_page.notes[0]
|
||||
item.go_to_unit()
|
||||
self.courseware_page.wait_for_page()
|
||||
note = self.note_unit_page.notes[0]
|
||||
self.assertTrue(note.is_visible)
|
||||
note = self.note_unit_page.notes[1]
|
||||
self.assertFalse(note.is_visible)
|
||||
self.courseware_page.go_to_sequential_position(2)
|
||||
note = self.note_unit_page.notes[0]
|
||||
self.assertFalse(note.is_visible)
|
||||
self.courseware_page.go_to_sequential_position(1)
|
||||
self.courseware_page.wait_for_ajax()
|
||||
note = self.note_unit_page.notes[0]
|
||||
self.assertFalse(note.is_visible)
|
||||
|
||||
def test_page_size_limit(self):
|
||||
"""
|
||||
Scenario: Verify that we can't get notes more than default page size.
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 11 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list contains 10 items
|
||||
And I should see paging header and footer with correct data
|
||||
And I should see disabled previous button
|
||||
And I should also see enabled next button
|
||||
"""
|
||||
self._add_default_notes(extra_notes=21)
|
||||
self.notes_page.visit()
|
||||
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_pagination_with_single_page(self):
|
||||
"""
|
||||
Scenario: Notes list pagination works as expected for single page
|
||||
Given that I am a registered user
|
||||
And I have a course with 5 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list contains 5 items
|
||||
And I should see paging header and footer with correct data
|
||||
And I should see disabled previous and next buttons
|
||||
"""
|
||||
self._add_default_notes()
|
||||
self.notes_page.visit()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=5,
|
||||
header_text='Showing 1-5 out of 5 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=False,
|
||||
current_page_number=1,
|
||||
total_pages=1
|
||||
)
|
||||
|
||||
def test_next_and_previous_page_button(self):
|
||||
"""
|
||||
Scenario: Next & Previous buttons are working as expected for notes list pagination
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 26 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list contains 25 items
|
||||
And I should see paging header and footer with correct data
|
||||
And I should see disabled previous button
|
||||
And I should see enabled next button
|
||||
|
||||
When I click on next page button in footer
|
||||
Then I should be navigated to second page
|
||||
And I should see a list with 1 item
|
||||
And I should see paging header and footer with correct info
|
||||
And I should see enabled previous button
|
||||
And I should also see disabled next button
|
||||
|
||||
When I click on previous page button in footer
|
||||
Then I should be navigated to first page
|
||||
And I should see a list with 25 items
|
||||
And I should see paging header and footer with correct info
|
||||
And I should see disabled previous button
|
||||
And I should also see enabled next button
|
||||
"""
|
||||
self._add_default_notes(extra_notes=21)
|
||||
self.notes_page.visit()
|
||||
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
self.notes_page.press_next_page_button()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
self.notes_page.press_previous_page_button()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_pagination_with_valid_and_invalid_page_number(self):
|
||||
"""
|
||||
Scenario: Notes list pagination works as expected for valid & invalid page number
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 26 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list contains 25 items
|
||||
And I should see paging header and footer with correct data
|
||||
And I should see total page value is 2
|
||||
When I enter 2 in the page number input
|
||||
Then I should be navigated to page 2
|
||||
|
||||
When I enter 3 in the page number input
|
||||
Then I should not be navigated away from page 2
|
||||
"""
|
||||
self._add_default_notes(extra_notes=21)
|
||||
self.notes_page.visit()
|
||||
|
||||
self.assertEqual(self.notes_page.get_total_pages, 2)
|
||||
|
||||
# test pagination with valid page number
|
||||
self.notes_page.go_to_page(2)
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
# test pagination with invalid page number
|
||||
self.notes_page.go_to_page(3)
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_search_behaves_correctly_with_pagination(self):
|
||||
"""
|
||||
Scenario: Searching behaves correctly with pagination.
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 27 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list with 25 items
|
||||
And I should see paging header and footer with correct data
|
||||
And previous button is disabled
|
||||
And next button is enabled
|
||||
When I run the search with "note" query
|
||||
Then I see no error message
|
||||
And I see that "Search Results" tab appears with 26 notes found
|
||||
And an event has fired indicating that the Search Results view was selected
|
||||
And an event has fired recording the search that was performed
|
||||
"""
|
||||
self.search_and_verify()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
self.assert_viewed_event('Search Results')
|
||||
self.assert_search_event('note', 26)
|
||||
|
||||
def test_search_with_next_and_prev_page_button(self):
|
||||
"""
|
||||
Scenario: Next & Previous buttons are working as expected for search
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 27 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list with 25 items
|
||||
And I should see paging header and footer with correct data
|
||||
And previous button is disabled
|
||||
And next button is enabled
|
||||
|
||||
When I run the search with "note" query
|
||||
Then I see that "Search Results" tab appears with 26 notes found
|
||||
And an event has fired indicating that the Search Results view was selected
|
||||
And an event has fired recording the search that was performed
|
||||
|
||||
When I click on next page button in footer
|
||||
Then I should be navigated to second page
|
||||
And I should see a list with 1 item
|
||||
And I should see paging header and footer with correct info
|
||||
And I should see enabled previous button
|
||||
And I should also see disabled next button
|
||||
|
||||
When I click on previous page button in footer
|
||||
Then I should be navigated to first page
|
||||
And I should see a list with 25 items
|
||||
And I should see paging header and footer with correct info
|
||||
And I should see disabled previous button
|
||||
And I should also see enabled next button
|
||||
"""
|
||||
self.search_and_verify()
|
||||
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
self.assert_viewed_event('Search Results')
|
||||
self.assert_search_event('note', 26)
|
||||
|
||||
self.notes_page.press_next_page_button()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
self.notes_page.press_previous_page_button()
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=25,
|
||||
header_text='Showing 1-25 out of 26 total',
|
||||
previous_button_enabled=False,
|
||||
next_button_enabled=True,
|
||||
current_page_number=1,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
def test_search_with_valid_and_invalid_page_number(self):
|
||||
"""
|
||||
Scenario: Notes list pagination works as expected for valid & invalid page number
|
||||
|
||||
Given that I am a registered user
|
||||
And I have a course with 27 notes
|
||||
When I open Notes page
|
||||
Then I can see notes list contains 25 items
|
||||
And I should see paging header and footer with correct data
|
||||
And I should see total page value is 2
|
||||
|
||||
When I run the search with "note" query
|
||||
Then I see that "Search Results" tab appears with 26 notes found
|
||||
And an event has fired indicating that the Search Results view was selected
|
||||
And an event has fired recording the search that was performed
|
||||
|
||||
When I enter 2 in the page number input
|
||||
Then I should be navigated to page 2
|
||||
|
||||
When I enter 3 in the page number input
|
||||
Then I should not be navigated away from page 2
|
||||
"""
|
||||
self.search_and_verify()
|
||||
|
||||
# test pagination with valid page number
|
||||
self.notes_page.go_to_page(2)
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
# test pagination with invalid page number
|
||||
self.notes_page.go_to_page(3)
|
||||
self._verify_pagination_info(
|
||||
notes_count_on_current_page=1,
|
||||
header_text='Showing 26-26 out of 26 total',
|
||||
previous_button_enabled=True,
|
||||
next_button_enabled=False,
|
||||
current_page_number=2,
|
||||
total_pages=2
|
||||
)
|
||||
|
||||
|
||||
@attr(shard=4)
|
||||
class EdxNotesToggleSingleNoteTest(EdxNotesTestMixin):
|
||||
"""
|
||||
Tests for toggling single annotation.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(EdxNotesToggleSingleNoteTest, self).setUp()
|
||||
self._add_notes()
|
||||
self.note_unit_page.visit()
|
||||
|
||||
def test_can_toggle_by_clicking_on_highlighted_text(self):
|
||||
"""
|
||||
Scenario: User can toggle a single note by clicking on highlighted text.
|
||||
Given I have a course with components with notes
|
||||
When I click on highlighted text
|
||||
And I move mouse out of the note
|
||||
Then I see that the note is still shown
|
||||
When I click outside the note
|
||||
Then I see the the note is closed
|
||||
"""
|
||||
note = self.note_unit_page.notes[0]
|
||||
|
||||
note.click_on_highlight()
|
||||
self.note_unit_page.move_mouse_to("body")
|
||||
self.assertTrue(note.is_visible)
|
||||
self.note_unit_page.click("body")
|
||||
self.assertFalse(note.is_visible)
|
||||
|
||||
def test_can_toggle_by_clicking_on_the_note(self):
|
||||
"""
|
||||
Scenario: User can toggle a single note by clicking on the note.
|
||||
Given I have a course with components with notes
|
||||
When I click on the note
|
||||
And I move mouse out of the note
|
||||
Then I see that the note is still shown
|
||||
When I click outside the note
|
||||
Then I see the the note is closed
|
||||
"""
|
||||
note = self.note_unit_page.notes[0]
|
||||
|
||||
note.show().click_on_viewer()
|
||||
self.note_unit_page.move_mouse_to("body")
|
||||
self.assertTrue(note.is_visible)
|
||||
self.note_unit_page.click("body")
|
||||
self.assertFalse(note.is_visible)
|
||||
|
||||
def test_interaction_between_notes(self):
|
||||
"""
|
||||
Scenario: Interactions between notes works well.
|
||||
Given I have a course with components with notes
|
||||
When I click on highlighted text in the first component
|
||||
And I move mouse out of the note
|
||||
Then I see that the note is still shown
|
||||
When I click on highlighted text in the second component
|
||||
Then I see that the new note is shown
|
||||
"""
|
||||
note_1 = self.note_unit_page.notes[0]
|
||||
note_2 = self.note_unit_page.notes[1]
|
||||
|
||||
note_1.click_on_highlight()
|
||||
self.note_unit_page.move_mouse_to("body")
|
||||
self.assertTrue(note_1.is_visible)
|
||||
|
||||
note_2.click_on_highlight()
|
||||
self.assertFalse(note_1.is_visible)
|
||||
self.assertTrue(note_2.is_visible)
|
||||
|
||||
|
||||
@attr(shard=4)
|
||||
class EdxNotesToggleNotesTest(EdxNotesTestMixin):
|
||||
"""
|
||||
Tests for toggling visibility of all notes.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(EdxNotesToggleNotesTest, self).setUp()
|
||||
self._add_notes()
|
||||
self.note_unit_page.visit()
|
||||
|
||||
def test_can_disable_all_notes(self):
|
||||
"""
|
||||
Scenario: User can disable all notes.
|
||||
Given I have a course with components with notes
|
||||
And I open the unit with annotatable components
|
||||
When I click on "Show notes" checkbox
|
||||
Then I do not see any notes on the sequential position
|
||||
When I change sequential position to "2"
|
||||
Then I still do not see any notes on the sequential position
|
||||
When I go to "Test Subsection 2" subsection
|
||||
Then I do not see any notes on the subsection
|
||||
"""
|
||||
# Disable all notes
|
||||
self.note_unit_page.toggle_visibility()
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) == 0, u"Notes are hidden")
|
||||
self.courseware_page.go_to_sequential_position(2)
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) == 0, u"Notes are hidden")
|
||||
self.course_home_page.visit()
|
||||
self.course_home_page.outline.go_to_section(u"Test Section 1", u"Test Subsection 2")
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) == 0, u"Notes are hidden")
|
||||
|
||||
def test_can_reenable_all_notes(self):
|
||||
"""
|
||||
Scenario: User can toggle notes visibility.
|
||||
Given I have a course with components with notes
|
||||
And I open the unit with annotatable components
|
||||
When I click on "Show notes" checkbox
|
||||
Then I do not see any notes on the sequential position
|
||||
When I click on "Show notes" checkbox again
|
||||
Then I see that all notes appear
|
||||
When I change sequential position to "2"
|
||||
Then I still can see all notes on the sequential position
|
||||
When I go to "Test Subsection 2" subsection
|
||||
Then I can see all notes on the subsection
|
||||
"""
|
||||
# Disable notes
|
||||
self.note_unit_page.toggle_visibility()
|
||||
self.assertEqual(len(self.note_unit_page.notes), 0)
|
||||
# Enable notes to make sure that I can enable notes without refreshing
|
||||
# the page.
|
||||
self.note_unit_page.toggle_visibility()
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) > 0, u"Notes are visible")
|
||||
self.courseware_page.go_to_sequential_position(2)
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) > 0, u"Notes are visible")
|
||||
self.course_home_page.visit()
|
||||
self.course_home_page.outline.go_to_section(u"Test Section 1", u"Test Subsection 2")
|
||||
self.note_unit_page.wait_for(lambda: len(self.note_unit_page.notes) > 0, u"Notes are visible")
|
||||
Reference in New Issue
Block a user