Skip to content
Merged
4 changes: 2 additions & 2 deletions common/djangoapps/util/milestones_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def remove_course_milestones(course_key, user, relationship):
milestones_api.remove_user_milestone({'id': user.id}, milestone)


def get_required_content(course, user):
def get_required_content(course_key, user):
"""
Queries milestones subsystem to see if the specified course is gated on one or more milestones,
and if those milestones can be fulfilled via completion of a particular course content module
Expand All @@ -217,7 +217,7 @@ def get_required_content(course, user):
# Get all of the outstanding milestones for this course, for this user
try:
milestone_paths = get_course_milestones_fulfillment_paths(
unicode(course.id),
unicode(course_key),
serialize_user(user)
)
except InvalidMilestoneRelationshipTypeException:
Expand Down
2 changes: 1 addition & 1 deletion common/test/acceptance/pages/lms/course_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class CourseOutlinePage(PageObject):
SECTION_SELECTOR = '.outline-item.section:nth-of-type({0})'
SECTION_TITLES_SELECTOR = '.section-name span'
SUBSECTION_SELECTOR = SECTION_SELECTOR + ' .subsection:nth-of-type({1}) .outline-item'
SUBSECTION_TITLES_SELECTOR = SECTION_SELECTOR + ' .subsection a span:first-child'
SUBSECTION_TITLES_SELECTOR = SECTION_SELECTOR + ' .subsection .subsection-title'
OUTLINE_RESUME_COURSE_SELECTOR = '.outline-item .resume-right'

def __init__(self, browser, parent_page):
Expand Down
1 change: 1 addition & 0 deletions common/test/acceptance/pages/lms/courseware.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def __init__(self, browser, course_id):
def is_browser_on_page(self):
return self.q(css='.course-content').present

# TODO: TNL-6546: Remove and find callers
@property
def chapter_count_in_navigation(self):
"""
Expand Down
113 changes: 44 additions & 69 deletions common/test/acceptance/tests/lms/test_lms.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
from common.test.acceptance.pages.lms import BASE_URL
from common.test.acceptance.pages.lms.account_settings import AccountSettingsPage
from common.test.acceptance.pages.lms.auto_auth import AutoAuthPage
from common.test.acceptance.pages.lms.bookmarks import BookmarksPage
from common.test.acceptance.pages.lms.create_mode import ModeCreationPage
from common.test.acceptance.pages.lms.course_home import CourseHomePage
from common.test.acceptance.pages.lms.course_info import CourseInfoPage
Expand Down Expand Up @@ -635,6 +634,7 @@ def test_children_a11y(self):
children_page.a11y_audit.check_for_accessibility_errors()


@attr(shard=1)
class HighLevelTabTest(UniqueCourseTest):
"""
Tests that verify each of the high-level tabs available within a course.
Expand Down Expand Up @@ -688,7 +688,6 @@ def setUp(self):
# Auto-auth register for the course
AutoAuthPage(self.browser, course_id=self.course_id).visit()

@attr(shard=1)
def test_course_info(self):
"""
Navigate to the course info page.
Expand All @@ -706,7 +705,6 @@ def test_course_info(self):
self.assertEqual(len(handout_links), 1)
self.assertIn('demoPDF.pdf', handout_links[0])

@attr(shard=1)
def test_progress(self):
"""
Navigate to the progress page.
Expand All @@ -724,7 +722,6 @@ def test_progress(self):
actual_scores = self.progress_page.scores(CHAPTER, SECTION)
self.assertEqual(actual_scores, EXPECTED_SCORES)

@attr(shard=1)
def test_static_tab(self):
"""
Navigate to a static tab (course content)
Expand All @@ -734,7 +731,6 @@ def test_static_tab(self):
self.tab_nav.go_to_tab('Test Static Tab')
self.assertTrue(self.tab_nav.is_on_tab('Test Static Tab'))

@attr(shard=1)
def test_static_tab_with_mathjax(self):
"""
Navigate to a static tab (course content)
Expand All @@ -747,7 +743,6 @@ def test_static_tab_with_mathjax(self):
# Verify that Mathjax has rendered
self.tab_nav.mathjax_has_rendered()

@attr(shard=1)
def test_wiki_tab_first_time(self):
"""
Navigate to the course wiki tab. When the wiki is accessed for
Expand All @@ -769,7 +764,6 @@ def test_wiki_tab_first_time(self):
self.assertEqual(expected_article_name, course_wiki.article_name)

# TODO: TNL-6546: This whole function will be able to go away, replaced by test_course_home below.
@attr(shard=1)
def test_courseware_nav(self):
"""
Navigate to a particular unit in the course.
Expand Down Expand Up @@ -805,13 +799,9 @@ def test_courseware_nav(self):
self.courseware_page.nav.go_to_section('Test Section 2', 'Test Subsection 3')
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

@attr(shard=1)
def test_course_home(self):
def test_course_home_tab(self):
"""
Navigate to the course home page using the tab.

Includes smoke test of course outline, courseware page, and breadcrumbs.

"""
# TODO: TNL-6546: Use tab navigation and remove course_home_page.visit().
#self.course_info_page.visit()
Expand All @@ -825,56 +815,6 @@ def test_course_home(self):
# Check that the tab lands on the course home page.
self.assertTrue(self.course_home_page.is_browser_on_page())

# Check that the course navigation appears correctly
EXPECTED_SECTIONS = {
'Test Section': ['Test Subsection'],
'Test Section 2': ['Test Subsection 2', 'Test Subsection 3']
}

actual_sections = self.course_home_page.outline.sections
for section, subsections in EXPECTED_SECTIONS.iteritems():
self.assertIn(section, actual_sections)
self.assertEqual(actual_sections[section], EXPECTED_SECTIONS[section])

# Navigate to a particular section
self.course_home_page.outline.go_to_section('Test Section', 'Test Subsection')

# Check the sequence items on the courseware page
EXPECTED_ITEMS = ['Test Problem 1', 'Test Problem 2', 'Test HTML']

actual_items = self.courseware_page.nav.sequence_items
self.assertEqual(len(actual_items), len(EXPECTED_ITEMS))
for expected in EXPECTED_ITEMS:
self.assertIn(expected, actual_items)

# Use outline breadcrumb to get back to course home page.
self.courseware_page.nav.go_to_outline()

# Navigate to a particular section other than the default landing section.
self.course_home_page.outline.go_to_section('Test Section 2', 'Test Subsection 3')
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

# Verify that we can navigate to the bookmarks page
self.course_home_page.visit()
self.course_home_page.click_bookmarks_button()
bookmarks_page = BookmarksPage(self.browser, self.course_id)
self.assertTrue(bookmarks_page.is_browser_on_page())

# Test "Resume Course" button from header
self.course_home_page.visit()
self.course_home_page.resume_course_from_header()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

# Test "Resume Course" button from within outline
self.course_home_page.visit()
self.course_home_page.outline.resume_course_from_outline()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

@attr('a11y')
def test_course_home_a11y(self):
self.course_home_page.visit()
self.course_home_page.a11y_audit.check_for_accessibility_errors()


@attr(shard=1)
class PDFTextBooksTabTest(UniqueCourseTest):
Expand Down Expand Up @@ -1233,7 +1173,7 @@ def setUp(self):
self.course_info['run'], self.course_info['display_name']
).install()

self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_home_page = CourseHomePage(self.browser, self.course_id)
self.settings_page = SettingsPage(
self.browser,
self.course_info['org'],
Expand All @@ -1245,19 +1185,54 @@ def setUp(self):
AutoAuthPage(self.browser, course_id=self.course_id).visit()

def test_entrance_exam_section(self):
"""
Scenario: Any course that is enabled for an entrance exam, should have
entrance exam section in the course outline.
Given that I visit the course outline
And entrance exams are not yet enabled
Then I should not see an "Entrance Exam" section
When I log in as staff
And enable entrance exams
And I visit the course outline again as student
Then there should be an "Entrance Exam" chapter.'
"""
# visit the course outline and make sure there is no "Entrance Exam" section.
self.course_home_page.visit()
self.assertFalse('Entrance Exam' in self.course_home_page.outline.sections.keys())

# Logout and login as a staff.
LogoutPage(self.browser).visit()
AutoAuthPage(self.browser, course_id=self.course_id, staff=True).visit()

# visit course settings page and set/enabled entrance exam for that course.
self.settings_page.visit()
self.settings_page.entrance_exam_field.click()
self.settings_page.save_changes()

# Logout and login as a student.
LogoutPage(self.browser).visit()
AutoAuthPage(self.browser, course_id=self.course_id, staff=False).visit()

# visit the course outline and make sure there is an "Entrance Exam" section.
self.course_home_page.visit()
self.assertTrue('Entrance Exam' in self.course_home_page.outline.sections.keys())

# TODO: TNL-6546: Remove test
def test_entrance_exam_section_2(self):
"""
Scenario: Any course that is enabled for an entrance exam, should have entrance exam chapter at course
page.
Given that I am on the course page
When I view the course that has an entrance exam
Then there should be an "Entrance Exam" chapter.'
"""
courseware_page = CoursewarePage(self.browser, self.course_id)
entrance_exam_link_selector = '.accordion .course-navigation .chapter .group-heading'
# visit course page and make sure there is not entrance exam chapter.
self.courseware_page.visit()
self.courseware_page.wait_for_page()
courseware_page.visit()
courseware_page.wait_for_page()
self.assertFalse(element_has_text(
page=self.courseware_page,
page=courseware_page,
css_selector=entrance_exam_link_selector,
text='Entrance Exam'
))
Expand All @@ -1276,10 +1251,10 @@ def test_entrance_exam_section(self):
AutoAuthPage(self.browser, course_id=self.course_id, staff=False).visit()

# visit course info page and make sure there is an "Entrance Exam" section.
self.courseware_page.visit()
self.courseware_page.wait_for_page()
courseware_page.visit()
courseware_page.wait_for_page()
self.assertTrue(element_has_text(
page=self.courseware_page,
page=courseware_page,
css_selector=entrance_exam_link_selector,
text='Entrance Exam'
))
Expand Down
139 changes: 139 additions & 0 deletions common/test/acceptance/tests/lms/test_lms_course_home.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
# -*- coding: utf-8 -*-
"""
End-to-end tests for the LMS that utilize the course home page and course outline.
"""
from contextlib import contextmanager
from nose.plugins.attrib import attr

from ..helpers import auto_auth, load_data_str, UniqueCourseTest
from ...fixtures.course import CourseFixture, XBlockFixtureDesc
from ...pages.lms.bookmarks import BookmarksPage
from ...pages.lms.course_home import CourseHomePage
from ...pages.lms.courseware import CoursewarePage


class CourseHomeBaseTest(UniqueCourseTest):
"""
Provides base setup for course home tests.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"

def setUp(self):
"""
Initialize pages and install a course fixture.
"""
super(CourseHomeBaseTest, self).setUp()

self.course_home_page = CourseHomePage(self.browser, self.course_id)
self.courseware_page = CoursewarePage(self.browser, self.course_id)

# Install a course with sections and problems
course_fix = CourseFixture(
self.course_info['org'],
self.course_info['number'],
self.course_info['run'],
self.course_info['display_name']
)

course_fix.add_children(
XBlockFixtureDesc('static_tab', 'Test Static Tab', data=r"static tab data with mathjax \(E=mc^2\)"),
XBlockFixtureDesc('chapter', 'Test Section').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1', data=load_data_str('multiple_choice.xml')),
XBlockFixtureDesc('problem', 'Test Problem 2', data=load_data_str('formula_problem.xml')),
XBlockFixtureDesc('html', 'Test HTML'),
)
),
XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 2'),
XBlockFixtureDesc('sequential', 'Test Subsection 3').add_children(
XBlockFixtureDesc('problem', 'Test Problem A', data=load_data_str('multiple_choice.xml'))
),
)
).install()

# Auto-auth register for the course.
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)


class CourseHomeTest(CourseHomeBaseTest):
"""
Tests the course home page with course outline.
"""

def test_course_home(self):
"""
Smoke test of course outline, breadcrumbs to and from cours outline, and bookmarks.
"""
self.course_home_page.visit()

# TODO: TNL-6546: Remove unified_course_view.
self.course_home_page.unified_course_view = True
self.courseware_page.nav.unified_course_view = True

# Check that the tab lands on the course home page.
self.assertTrue(self.course_home_page.is_browser_on_page())

# Check that the course navigation appears correctly
EXPECTED_SECTIONS = {
'Test Section': ['Test Subsection'],
'Test Section 2': ['Test Subsection 2', 'Test Subsection 3']
}

actual_sections = self.course_home_page.outline.sections
for section, subsections in EXPECTED_SECTIONS.iteritems():
self.assertIn(section, actual_sections)
self.assertEqual(actual_sections[section], EXPECTED_SECTIONS[section])

# Navigate to a particular section
self.course_home_page.outline.go_to_section('Test Section', 'Test Subsection')

# Check the sequence items on the courseware page
EXPECTED_ITEMS = ['Test Problem 1', 'Test Problem 2', 'Test HTML']

actual_items = self.courseware_page.nav.sequence_items
self.assertEqual(len(actual_items), len(EXPECTED_ITEMS))
for expected in EXPECTED_ITEMS:
self.assertIn(expected, actual_items)

# Use outline breadcrumb to get back to course home page.
self.courseware_page.nav.go_to_outline()

# Navigate to a particular section other than the default landing section.
self.course_home_page.outline.go_to_section('Test Section 2', 'Test Subsection 3')
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

# Verify that we can navigate to the bookmarks page
self.course_home_page.visit()
self.course_home_page.click_bookmarks_button()
bookmarks_page = BookmarksPage(self.browser, self.course_id)
self.assertTrue(bookmarks_page.is_browser_on_page())

# Test "Resume Course" button from header
self.course_home_page.visit()
self.course_home_page.resume_course_from_header()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))

# Test "Resume Course" button from within outline
self.course_home_page.visit()
self.course_home_page.outline.resume_course_from_outline()
self.assertTrue(self.courseware_page.nav.is_on_section('Test Section 2', 'Test Subsection 3'))


@attr('a11y')
class CourseHomeA11yTest(CourseHomeBaseTest):
"""
Tests the accessibility of the course home page with course outline.
"""

def setUp(self):
super(CourseHomeA11yTest, self).setUp()

def test_course_home_a11y(self):
"""
Test the accessibility of the course home page with course outline.
"""
course_home_page = CourseHomePage(self.browser, self.course_id)
course_home_page.visit()
course_home_page.a11y_audit.check_for_accessibility_errors()
Loading