Files
edx-platform/common/test/acceptance/tests/lms/test_lms_courseware.py
Feanil Patel 046feb0cf0 Merge pull request #22649 from edx/feanil/fix_pep8
Fix all E303 pep8 errors.
2019-12-30 13:32:26 -05:00

943 lines
38 KiB
Python

# -*- coding: utf-8 -*-
"""
End-to-end tests for the LMS.
"""
import json
from datetime import datetime, timedelta
import ddt
import six
from six.moves import range
from openedx.core.lib.tests import attr
from ...fixtures.course import CourseFixture, XBlockFixtureDesc
from ...pages.common.auto_auth import AutoAuthPage
from ...pages.common.logout import LogoutPage
from ...pages.lms.course_home import CourseHomePage
from ...pages.lms.courseware import CoursewarePage, CoursewareSequentialTabPage
from ...pages.lms.create_mode import ModeCreationPage
from ...pages.lms.dashboard import DashboardPage
from ...pages.lms.pay_and_verify import FakePaymentPage, FakeSoftwareSecureVerificationPage, PaymentAndVerificationFlow
from ...pages.lms.problem import ProblemPage
from ...pages.lms.progress import ProgressPage
from ...pages.lms.track_selection import TrackSelectionPage
from ...pages.studio.overview import CourseOutlinePage as StudioCourseOutlinePage
from ..helpers import EventsTestMixin, UniqueCourseTest, auto_auth, create_multiple_choice_problem
@attr(shard=9)
class CoursewareTest(UniqueCourseTest):
"""
Test courseware.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
def setUp(self):
super(CoursewareTest, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_home_page = CourseHomePage(self.browser, self.course_id)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course with sections/problems, tabs, updates, and handouts
self.course_fix = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
self.course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1')
)
),
XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 2').add_children(
XBlockFixtureDesc('problem', 'Test Problem 2')
)
)
).install()
# Auto-auth register for the course.
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
def _goto_problem_page(self):
"""
Open problem page with assertion.
"""
self.courseware_page.visit()
self.problem_page = ProblemPage(self.browser) # pylint: disable=attribute-defined-outside-init
self.assertEqual(self.problem_page.problem_name, 'Test Problem 1')
def test_courseware(self):
"""
Test courseware if recent visited subsection become unpublished.
"""
# Visit problem page as a student.
self._goto_problem_page()
# Logout and login as a staff user.
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
# Visit course outline page in studio.
self.studio_course_outline.visit()
# Set release date for subsection in future.
self.studio_course_outline.change_problem_release_date()
# Logout and login as a student.
LogoutPage(self.browser).visit()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
# Visit courseware as a student.
self.courseware_page.visit()
# Problem name should be "Test Problem 2".
self.assertEqual(self.problem_page.problem_name, 'Test Problem 2')
def test_course_tree_breadcrumb(self):
"""
Scenario: Correct course tree breadcrumb is shown.
Given that I am a registered user
And I visit my courseware page
Then I should see correct course tree breadcrumb
"""
xblocks = self.course_fix.get_nested_xblocks(category="problem")
for index in range(1, len(xblocks) + 1):
test_section_title = u'Test Section {}'.format(index)
test_subsection_title = u'Test Subsection {}'.format(index)
test_unit_title = u'Test Problem {}'.format(index)
self.course_home_page.visit()
self.course_home_page.outline.go_to_section(test_section_title, test_subsection_title)
course_nav = self.courseware_page.nav
self.assertEqual(course_nav.breadcrumb_section_title, test_section_title)
self.assertEqual(course_nav.breadcrumb_subsection_title, test_subsection_title)
self.assertEqual(course_nav.breadcrumb_unit_title, test_unit_title)
@attr(shard=9)
@ddt.ddt
class ProctoredExamTest(UniqueCourseTest):
"""
Tests for proctored exams.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
def setUp(self):
super(ProctoredExamTest, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course with sections/problems, tabs, updates, and handouts
course_fix = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
course_fix.add_advanced_settings({
"enable_proctored_exams": {"value": "true"}
})
course_fix.add_advanced_settings({
"show_review_rules": {"value": "true"}
})
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1')
)
)
).install()
self.track_selection_page = TrackSelectionPage(self.browser, self.course_id)
self.payment_and_verification_flow = PaymentAndVerificationFlow(self.browser, self.course_id)
self.immediate_verification_page = PaymentAndVerificationFlow(
self.browser, self.course_id, entry_point='verify-now'
)
self.upgrade_page = PaymentAndVerificationFlow(self.browser, self.course_id, entry_point='upgrade')
self.fake_payment_page = FakePaymentPage(self.browser, self.course_id)
self.dashboard_page = DashboardPage(self.browser)
self.problem_page = ProblemPage(self.browser)
# Add a verified mode to the course
ModeCreationPage(
self.browser, self.course_id, mode_slug=u'verified', mode_display_name=u'Verified Certificate',
min_price=10, suggested_prices='10,20'
).visit()
# Auto-auth register for the course.
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
def _login_as_a_verified_user(self):
"""
login as a verififed user
"""
auto_auth(
self.browser,
self.USERNAME,
self.EMAIL,
False,
self.course_id,
should_manually_verify=True
)
# the track selection page cannot be visited. see the other tests to see if any prereq is there.
# Navigate to the track selection page
self.track_selection_page.visit()
# Enter the payment and verification flow by choosing to enroll as verified
self.track_selection_page.enroll('verified')
# Proceed to the fake payment page
self.payment_and_verification_flow.proceed_to_payment()
# Submit payment
self.fake_payment_page.submit_payment()
def test_can_create_proctored_exam_in_studio(self):
"""
Given that I am a staff member
When I visit the course outline page in studio.
And open the subsection edit dialog
Then I can view all settings related to Proctored and timed exams
"""
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
self.studio_course_outline.open_subsection_settings_dialog()
self.assertTrue(self.studio_course_outline.proctoring_items_are_displayed())
def test_proctored_exam_flow(self):
"""
Given that I am a staff member on the exam settings section
select advanced settings tab
When I Make the exam proctored.
And I login as a verified student.
And I verify the user's ID.
And visit the courseware as a verified student.
Then I can see an option to take the exam as a proctored exam.
"""
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
self.studio_course_outline.open_subsection_settings_dialog()
self.studio_course_outline.select_advanced_tab()
self.studio_course_outline.make_exam_proctored()
LogoutPage(self.browser).visit()
self._login_as_a_verified_user()
self.courseware_page.visit()
self.assertTrue(self.courseware_page.can_start_proctored_exam)
def _setup_and_take_timed_exam(self, hide_after_due=False):
"""
Helper to perform the common action "set up a timed exam as staff,
then take it as student"
"""
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
self.studio_course_outline.open_subsection_settings_dialog()
self.studio_course_outline.select_advanced_tab()
self.studio_course_outline.make_exam_timed(hide_after_due=hide_after_due)
LogoutPage(self.browser).visit()
self._login_as_a_verified_user()
self.courseware_page.visit()
self.courseware_page.start_timed_exam()
self.assertTrue(self.courseware_page.is_timer_bar_present)
self.courseware_page.stop_timed_exam()
self.courseware_page.wait_for_page()
self.assertTrue(self.courseware_page.has_submitted_exam_message())
LogoutPage(self.browser).visit()
@ddt.data(True, False)
def test_timed_exam_flow(self, hide_after_due):
"""
Given that I am a staff member on the exam settings section
select advanced settings tab
When I Make the exam timed.
And I login as a verified student.
And visit the courseware as a verified student.
And I start the timed exam
Then I am taken to the exam with a timer bar showing
When I finish the exam
Then I see the exam submitted dialog in place of the exam
When I log back into studio as a staff member
And change the problem's due date to be in the past
And log back in as the original verified student
Then I see the exam or message in accordance with the hide_after_due setting
"""
self._setup_and_take_timed_exam(hide_after_due)
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
last_week = (datetime.today() - timedelta(days=7)).strftime("%m/%d/%Y")
self.studio_course_outline.change_problem_due_date(last_week)
LogoutPage(self.browser).visit()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
self.courseware_page.visit()
self.assertEqual(self.courseware_page.has_submitted_exam_message(), hide_after_due)
def test_field_visiblity_with_all_exam_types(self):
"""
Given that I am a staff member
And I have visited the course outline page in studio.
And the subsection edit dialog is open
select advanced settings tab
For each of None, Timed, Proctored, and Practice exam types
The time allotted and review rules fields have proper visibility
None: False, False
Timed: True, False
Proctored: True, True
Practice: True, False
"""
LogoutPage(self.browser).visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
self.studio_course_outline.open_subsection_settings_dialog()
self.studio_course_outline.select_advanced_tab()
self.studio_course_outline.select_none_exam()
self.assertFalse(self.studio_course_outline.time_allotted_field_visible())
self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible())
self.studio_course_outline.select_timed_exam()
self.assertTrue(self.studio_course_outline.time_allotted_field_visible())
self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible())
self.studio_course_outline.select_proctored_exam()
self.assertTrue(self.studio_course_outline.time_allotted_field_visible())
self.studio_course_outline.select_practice_exam()
self.assertTrue(self.studio_course_outline.time_allotted_field_visible())
self.assertFalse(self.studio_course_outline.exam_review_rules_field_visible())
class CoursewareMultipleVerticalsTestBase(UniqueCourseTest, EventsTestMixin):
"""
Base class with setup for testing courseware with multiple verticals
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
def setUp(self):
super(CoursewareMultipleVerticalsTestBase, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.course_home_page = CourseHomePage(self.browser, self.course_id)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course with sections/problems, tabs, updates, and handouts
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('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'),
XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>"),
XBlockFixtureDesc('problem', 'Test Problem 2', data="<problem>problem 2 dummy body</problem>"),
XBlockFixtureDesc('html', 'html 2', data="<html>html 2 dummy body</html>"),
),
XBlockFixtureDesc('sequential', 'Test Subsection 1,2').add_children(
XBlockFixtureDesc('problem', 'Test Problem 3', data='<problem>problem 3 dummy body</problem>'),
),
XBlockFixtureDesc(
'sequential', 'Test HIDDEN Subsection', metadata={'visible_to_staff_only': True}
).add_children(
XBlockFixtureDesc('problem', 'Test HIDDEN Problem', data='<problem>hidden problem</problem>'),
),
),
XBlockFixtureDesc('chapter', 'Test Section 2').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 2,1').add_children(
XBlockFixtureDesc('problem', 'Test Problem 4', data='<problem>problem 4 dummy body</problem>'),
),
),
XBlockFixtureDesc('chapter', 'Test HIDDEN Section', metadata={'visible_to_staff_only': True}).add_children(
XBlockFixtureDesc('sequential', 'Test HIDDEN Subsection'),
),
).install()
# Auto-auth register for the course.
AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
course_id=self.course_id, staff=False).visit()
@attr(shard=9)
class CoursewareMultipleVerticalsTest(CoursewareMultipleVerticalsTestBase):
"""
Test courseware with multiple verticals
"""
def test_navigation_buttons(self):
self.courseware_page.visit()
# start in first section
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 0, next_enabled=True, prev_enabled=False)
# next takes us to next tab in sequential
self.courseware_page.click_next_button_on_top()
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 1, next_enabled=True, prev_enabled=True)
# go to last sequential position
self.courseware_page.go_to_sequential_position(4)
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 3, next_enabled=True, prev_enabled=True)
# next takes us to next sequential
self.courseware_page.click_next_button_on_bottom()
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,2', 0, next_enabled=True, prev_enabled=True)
# next takes us to next chapter
self.courseware_page.click_next_button_on_top()
self.assert_navigation_state('Test Section 2', 'Test Subsection 2,1', 0, next_enabled=False, prev_enabled=True)
# previous takes us to previous chapter
self.courseware_page.click_previous_button_on_top()
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,2', 0, next_enabled=True, prev_enabled=True)
# previous takes us to last tab in previous sequential
self.courseware_page.click_previous_button_on_bottom()
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 3, next_enabled=True, prev_enabled=True)
# previous takes us to previous tab in sequential
self.courseware_page.click_previous_button_on_bottom()
self.assert_navigation_state('Test Section 1', 'Test Subsection 1,1', 2, next_enabled=True, prev_enabled=True)
# test UI events emitted by navigation
filter_sequence_ui_event = lambda event: event.get('name', '').startswith('edx.ui.lms.sequence.')
sequence_ui_events = self.wait_for_events(event_filter=filter_sequence_ui_event, timeout=2)
legacy_events = [ev for ev in sequence_ui_events if ev['event_type'] in {'seq_next', 'seq_prev', 'seq_goto'}]
nonlegacy_events = [ev for ev in sequence_ui_events if ev not in legacy_events]
self.assertTrue(all('old' in json.loads(ev['event']) for ev in legacy_events))
self.assertTrue(all('new' in json.loads(ev['event']) for ev in legacy_events))
self.assertFalse(any('old' in json.loads(ev['event']) for ev in nonlegacy_events))
self.assertFalse(any('new' in json.loads(ev['event']) for ev in nonlegacy_events))
self.assert_events_match(
[
{
'event_type': 'seq_next',
'event': {
'old': 1,
'new': 2,
'current_tab': 1,
'tab_count': 4,
'widget_placement': 'top',
}
},
{
'event_type': 'seq_goto',
'event': {
'old': 2,
'new': 4,
'current_tab': 2,
'target_tab': 4,
'tab_count': 4,
'widget_placement': 'top',
}
},
{
'event_type': 'edx.ui.lms.sequence.next_selected',
'event': {
'current_tab': 4,
'tab_count': 4,
'widget_placement': 'bottom',
}
},
{
'event_type': 'edx.ui.lms.sequence.next_selected',
'event': {
'current_tab': 1,
'tab_count': 1,
'widget_placement': 'top',
}
},
{
'event_type': 'edx.ui.lms.sequence.previous_selected',
'event': {
'current_tab': 1,
'tab_count': 1,
'widget_placement': 'top',
}
},
{
'event_type': 'edx.ui.lms.sequence.previous_selected',
'event': {
'current_tab': 1,
'tab_count': 1,
'widget_placement': 'bottom',
}
},
{
'event_type': 'seq_prev',
'event': {
'old': 4,
'new': 3,
'current_tab': 4,
'tab_count': 4,
'widget_placement': 'bottom',
}
},
],
sequence_ui_events
)
def assert_navigation_state(
self, section_title, subsection_title, subsection_position, next_enabled, prev_enabled
):
"""
Verifies that the navigation state is as expected.
"""
self.assertTrue(self.courseware_page.nav.is_on_section(section_title, subsection_title))
self.assertEqual(self.courseware_page.sequential_position, subsection_position)
self.assertEqual(self.courseware_page.is_next_button_enabled, next_enabled)
self.assertEqual(self.courseware_page.is_previous_button_enabled, prev_enabled)
def test_tab_position(self):
# test that using the position in the url direct to correct tab in courseware
self.course_home_page.visit()
self.course_home_page.outline.go_to_section('Test Section 1', 'Test Subsection 1,1')
subsection_url = self.browser.current_url
url_part_list = subsection_url.split('/')
course_id = url_part_list[-5]
chapter_id = url_part_list[-3]
subsection_id = url_part_list[-2]
problem1_page = CoursewareSequentialTabPage(
self.browser,
course_id=course_id,
chapter=chapter_id,
subsection=subsection_id,
position=1
).visit()
self.assertIn('problem 1 dummy body', problem1_page.get_selected_tab_content())
html1_page = CoursewareSequentialTabPage(
self.browser,
course_id=course_id,
chapter=chapter_id,
subsection=subsection_id,
position=2
).visit()
self.assertIn('html 1 dummy body', html1_page.get_selected_tab_content())
problem2_page = CoursewareSequentialTabPage(
self.browser,
course_id=course_id,
chapter=chapter_id,
subsection=subsection_id,
position=3
).visit()
self.assertIn('problem 2 dummy body', problem2_page.get_selected_tab_content())
html2_page = CoursewareSequentialTabPage(
self.browser,
course_id=course_id,
chapter=chapter_id,
subsection=subsection_id,
position=4
).visit()
self.assertIn('html 2 dummy body', html2_page.get_selected_tab_content())
@attr(shard=9)
class ProblemStateOnNavigationTest(UniqueCourseTest):
"""
Test courseware with problems in multiple verticals.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
problem1_name = 'MULTIPLE CHOICE TEST PROBLEM 1'
problem2_name = 'MULTIPLE CHOICE TEST PROBLEM 2'
def setUp(self):
super(ProblemStateOnNavigationTest, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
# Install a course with section, tabs and multiple choice 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('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
create_multiple_choice_problem(self.problem1_name),
create_multiple_choice_problem(self.problem2_name),
),
),
).install()
# Auto-auth register for the course.
AutoAuthPage(
self.browser, username=self.USERNAME, email=self.EMAIL,
course_id=self.course_id, staff=False
).visit()
self.courseware_page.visit()
self.problem_page = ProblemPage(self.browser)
def go_to_tab_and_assert_problem(self, position, problem_name):
"""
Go to sequential tab and assert that we are on problem whose name is given as a parameter.
Args:
position: Position of the sequential tab
problem_name: Name of the problem
"""
self.courseware_page.go_to_sequential_position(position)
self.problem_page.wait_for_element_presence(
self.problem_page.CSS_PROBLEM_HEADER,
'wait for problem header'
)
self.assertEqual(self.problem_page.problem_name, problem_name)
def test_perform_problem_submit_and_navigate(self):
"""
Scenario:
I go to sequential position 1
Facing problem1, I select 'choice_1'
Then I click submit button
Then I go to sequential position 2
Then I came back to sequential position 1 again
Facing problem1, I observe the problem1 content is not
outdated before and after sequence navigation
"""
# Go to sequential position 1 and assert that we are on problem 1.
self.go_to_tab_and_assert_problem(1, self.problem1_name)
# Update problem 1's content state by clicking check button.
self.problem_page.click_choice('choice_choice_1')
self.problem_page.click_submit()
self.problem_page.wait_for_expected_status('label.choicegroup_incorrect', 'incorrect')
# Save problem 1's content state as we're about to switch units in the sequence.
problem1_content_before_switch = self.problem_page.problem_content
before_meta = self.problem_page.problem_meta
# Go to sequential position 2 and assert that we are on problem 2.
self.go_to_tab_and_assert_problem(2, self.problem2_name)
# Come back to our original unit in the sequence and assert that the content hasn't changed.
self.go_to_tab_and_assert_problem(1, self.problem1_name)
problem1_content_after_coming_back = self.problem_page.problem_content
after_meta = self.problem_page.problem_meta
self.assertEqual(problem1_content_before_switch, problem1_content_after_coming_back)
self.assertEqual(before_meta, after_meta)
def test_perform_problem_save_and_navigate(self):
"""
Scenario:
I go to sequential position 1
Facing problem1, I select 'choice_1'
Then I click save button
Then I go to sequential position 2
Then I came back to sequential position 1 again
Facing problem1, I observe the problem1 content is not
outdated before and after sequence navigation
"""
# Go to sequential position 1 and assert that we are on problem 1.
self.go_to_tab_and_assert_problem(1, self.problem1_name)
# Update problem 1's content state by clicking save button.
self.problem_page.click_choice('choice_choice_1')
self.problem_page.click_save()
self.problem_page.wait_for_save_notification()
# Save problem 1's content state as we're about to switch units in the sequence.
problem1_content_before_switch = self.problem_page.problem_input_content
before_meta = self.problem_page.problem_meta
# Go to sequential position 2 and assert that we are on problem 2.
self.go_to_tab_and_assert_problem(2, self.problem2_name)
self.problem_page.wait_for_expected_status('span.unanswered', 'unanswered')
# Come back to our original unit in the sequence and assert that the content hasn't changed.
self.go_to_tab_and_assert_problem(1, self.problem1_name)
problem1_content_after_coming_back = self.problem_page.problem_input_content
after_meta = self.problem_page.problem_meta
self.assertIn(problem1_content_after_coming_back, problem1_content_before_switch)
self.assertEqual(before_meta, after_meta)
@attr(shard=9)
class SubsectionHiddenAfterDueDateTest(UniqueCourseTest):
"""
Tests the "hide after due date" setting for
subsections.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
def setUp(self):
super(SubsectionHiddenAfterDueDateTest, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.logout_page = LogoutPage(self.browser)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course with sections/problems, tabs, updates, and handouts
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('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
create_multiple_choice_problem('Test Problem 1')
)
)
).install()
self.progress_page = ProgressPage(self.browser, self.course_id)
self._setup_subsection()
# Auto-auth register for the course.
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
def _setup_subsection(self):
"""
Helper to set up a problem subsection as staff, then take
it as a student.
"""
self.logout_page.visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
self.studio_course_outline.open_subsection_settings_dialog()
self.studio_course_outline.select_visibility_tab()
self.studio_course_outline.make_subsection_hidden_after_due_date()
self.logout_page.visit()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
self.courseware_page.visit()
self.logout_page.visit()
def test_subsecton_hidden_after_due_date(self):
"""
Given that I am a staff member on the subsection settings section
And I select the advanced settings tab
When I Make the subsection hidden after its due date.
And I login as a student.
And visit the subsection in the courseware as a verified student.
Then I am able to see the subsection
And when I visit the progress page
Then I should be able to see my grade on the progress page
When I log in as staff
And I make the subsection due in the past so that the current date is past its due date
And I log in as a student
And I visit the subsection in the courseware
Then the subsection should be hidden with a message that its due date has passed
And when I visit the progress page
Then I should be able to see my grade on the progress page
"""
self.logout_page.visit()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
self.courseware_page.visit()
self.assertFalse(self.courseware_page.content_hidden_past_due_date())
self.progress_page.visit()
self.assertEqual(self.progress_page.scores('Test Section 1', 'Test Subsection 1'), [(0, 1)])
self.logout_page.visit()
auto_auth(self.browser, "STAFF_TESTER", "staff101@example.com", True, self.course_id)
self.studio_course_outline.visit()
last_week = (datetime.today() - timedelta(days=7)).strftime("%m/%d/%Y")
self.studio_course_outline.change_problem_due_date(last_week)
self.logout_page.visit()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
self.courseware_page.visit()
self.assertTrue(self.courseware_page.content_hidden_past_due_date())
self.progress_page.visit()
self.assertEqual(self.progress_page.scores('Test Section 1', 'Test Subsection 1'), [(0, 1)])
@attr(shard=9)
class CompletionTestCase(UniqueCourseTest, EventsTestMixin):
"""
Test the completion on view functionality.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
COMPLETION_BY_VIEWING_DELAY_MS = '1000'
def setUp(self):
super(CompletionTestCase, self).setUp()
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course with sections/problems, tabs, updates, and handouts
course_fix = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
self.html_1_block = XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>")
self.problem_1_block = XBlockFixtureDesc(
'problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'
)
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1,1').add_children(
XBlockFixtureDesc('vertical', 'Test Unit 1,1,1').add_children(
XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>"),
XBlockFixtureDesc(
'html', 'html 2',
data=("<html>html 2 dummy body</html>" * 100) + "<span id='html2-end'>End</span>",
),
XBlockFixtureDesc('problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'),
),
XBlockFixtureDesc('vertical', 'Test Unit 1,1,2').add_children(
XBlockFixtureDesc('html', 'html 1', data="<html>html 1 dummy body</html>"),
XBlockFixtureDesc('problem', 'Test Problem 1', data='<problem>problem 1 dummy body</problem>'),
),
XBlockFixtureDesc('vertical', 'Test Unit 1,1,2').add_children(
self.html_1_block,
self.problem_1_block,
),
),
),
).install()
# Auto-auth register for the course.
AutoAuthPage(self.browser, username=self.USERNAME, email=self.EMAIL,
course_id=self.course_id, staff=False).visit()
@attr(shard=9)
class WordCloudTests(UniqueCourseTest):
"""
Tests the Word Cloud.
"""
USERNAME = "STUDENT_TESTER"
EMAIL = "student101@example.com"
def setUp(self):
super(WordCloudTests, self).setUp()
self.courseware_page = CoursewarePage(self.browser, self.course_id)
self.studio_course_outline = StudioCourseOutlinePage(
self.browser,
self.course_info['org'],
self.course_info['number'],
self.course_info['run']
)
# Install a course
course_fix = CourseFixture(
self.course_info['org'], self.course_info['number'],
self.course_info['run'], self.course_info['display_name']
)
# Set word cloud value against advanced modules in advanced settings
course_fix.add_advanced_settings({
"advanced_modules": {"value": ["word_cloud"]},
})
course_fix.add_children(
XBlockFixtureDesc('chapter', 'Test Section 1').add_children(
XBlockFixtureDesc('sequential', 'Test Subsection 1').add_children(
XBlockFixtureDesc('vertical', 'Test Unit').add_children(
XBlockFixtureDesc(
'word_cloud', 'advanced WORDCLOUD'
)
)
)
)
).install()
auto_auth(self.browser, self.USERNAME, self.EMAIL, False, self.course_id)
self.courseware_page.visit()
def test_word_cloud_is_rendered_with_empty_result(self):
"""
Scenario: Word Cloud component in LMS is rendered with empty result
Given the course has a Word Cloud component
Then I view the word cloud and it has rendered
When I press the Save button
Then I see the empty result
"""
self.assertTrue(self.courseware_page.is_word_cloud_rendered)
self.courseware_page.save_word_cloud()
self.assertEqual(self.courseware_page.word_cloud_answer_list, '')
def test_word_cloud_is_rendered_with_result(self):
"""
Scenario: Word Cloud component in LMS is rendered with result
Given the course has a Word Cloud component
Then I view the word cloud and it has rendered
When I fill inputs
And I press the Save button
Then I see the result with words count
"""
expected_data = ['test_wordcloud1', 'test_wordcloud2', 'test_wordcloud3', 'test_wordcloud4', 'test_wordcloud5']
self.assertTrue(self.courseware_page.is_word_cloud_rendered)
self.courseware_page.input_word_cloud('test_wordcloud')
self.courseware_page.save_word_cloud()
six.assertCountEqual(self, expected_data, self.courseware_page.word_cloud_answer_list)