Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
45195375
Commit
45195375
authored
Jul 09, 2014
by
jhelbert
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4285 from edx/jhelbert/enrollment-mode-change-events
Jhelbert/enrollment mode change events
parents
cd8f0e6c
e78a398f
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
159 additions
and
14 deletions
+159
-14
common/djangoapps/student/models.py
+5
-0
common/djangoapps/student/tests/tests.py
+29
-0
lms/djangoapps/courseware/features/change_enrollment.feature
+23
-0
lms/djangoapps/courseware/features/change_enrollment.py
+49
-0
lms/djangoapps/courseware/features/common.py
+6
-6
lms/djangoapps/courseware/features/events.py
+10
-3
lms/djangoapps/courseware/features/registration.py
+9
-0
lms/djangoapps/verify_student/tests/test_views.py
+28
-5
No files found.
common/djangoapps/student/models.py
View file @
45195375
...
...
@@ -328,6 +328,7 @@ class PendingEmailChange(models.Model):
EVENT_NAME_ENROLLMENT_ACTIVATED
=
'edx.course.enrollment.activated'
EVENT_NAME_ENROLLMENT_DEACTIVATED
=
'edx.course.enrollment.deactivated'
EVENT_NAME_ENROLLMENT_MODE_CHANGED
=
'edx.course.enrollment.mode_changed'
class
PasswordHistory
(
models
.
Model
):
...
...
@@ -716,6 +717,10 @@ class CourseEnrollment(models.Model):
u"offering:{}"
.
format
(
self
.
course_id
.
offering
),
u"mode:{}"
.
format
(
self
.
mode
)]
)
if
mode_changed
:
# the user's default mode is "honor" and disabled for a course
# mode change events will only be emitted when the user's mode changes from this
self
.
emit_event
(
EVENT_NAME_ENROLLMENT_MODE_CHANGED
)
def
emit_event
(
self
,
event_name
):
"""
...
...
common/djangoapps/student/tests/tests.py
View file @
45195375
...
...
@@ -310,6 +310,18 @@ class EnrollInCourseTest(TestCase):
self
.
assertFalse
(
self
.
mock_tracker
.
emit
.
called
)
# pylint: disable=maybe-no-member
self
.
mock_tracker
.
reset_mock
()
def
assert_enrollment_mode_change_event_was_emitted
(
self
,
user
,
course_key
,
mode
):
"""Ensures an enrollment mode change event was emitted"""
self
.
mock_tracker
.
emit
.
assert_called_once_with
(
# pylint: disable=maybe-no-member
'edx.course.enrollment.mode_changed'
,
{
'course_id'
:
course_key
.
to_deprecated_string
(),
'user_id'
:
user
.
pk
,
'mode'
:
mode
}
)
self
.
mock_tracker
.
reset_mock
()
def
assert_enrollment_event_was_emitted
(
self
,
user
,
course_key
):
"""Ensures an enrollment event was emitted since the last event related assertion"""
self
.
mock_tracker
.
emit
.
assert_called_once_with
(
# pylint: disable=maybe-no-member
...
...
@@ -447,6 +459,23 @@ class EnrollInCourseTest(TestCase):
self
.
assertTrue
(
CourseEnrollment
.
is_enrolled
(
user
,
course_id
))
self
.
assert_enrollment_event_was_emitted
(
user
,
course_id
)
def
test_change_enrollment_modes
(
self
):
user
=
User
.
objects
.
create
(
username
=
"justin"
,
email
=
"jh@fake.edx.org"
)
course_id
=
SlashSeparatedCourseKey
(
"edX"
,
"Test101"
,
"2013"
)
CourseEnrollment
.
enroll
(
user
,
course_id
)
self
.
assert_enrollment_event_was_emitted
(
user
,
course_id
)
CourseEnrollment
.
enroll
(
user
,
course_id
,
"audit"
)
self
.
assert_enrollment_mode_change_event_was_emitted
(
user
,
course_id
,
"audit"
)
# same enrollment mode does not emit an event
CourseEnrollment
.
enroll
(
user
,
course_id
,
"audit"
)
self
.
assert_no_events_were_emitted
()
CourseEnrollment
.
enroll
(
user
,
course_id
,
"honor"
)
self
.
assert_enrollment_mode_change_event_was_emitted
(
user
,
course_id
,
"honor"
)
@override_settings
(
MODULESTORE
=
TEST_DATA_MIXED_MODULESTORE
)
@unittest.skipUnless
(
settings
.
ROOT_URLCONF
==
'lms.urls'
,
'Test only valid in lms'
)
...
...
lms/djangoapps/courseware/features/change_enrollment.feature
0 → 100644
View file @
45195375
Feature
:
Change Enrollment Events
As a registered user
I want to change my enrollment mode
Scenario
:
I
can change my enrollment
Given
The course
"6.002x"
exists
And
the course
"6.002x"
has all enrollment modes
And
I am logged in
And
I visit the courses page
When
I register to audit the course
And
a
"edx.course.enrollment.activated"
server event is emitted
And
a
"edx.course.enrollment.mode_changed"
server events is emitted
And
I visit the dashboard
And
I click on Challenge Yourself
And
I choose an honor code upgrade
Then
I should be on the dashboard page
Then
2
"edx.course.enrollment.mode_changed"
server event is emitted
# don't emit another mode_changed event upon unenrollment
When
I unregister for the course numbered
"6.002x"
Then
2
"edx.course.enrollment.mode_changed"
server events is emitted
lms/djangoapps/courseware/features/change_enrollment.py
0 → 100644
View file @
45195375
""" Provides lettuce acceptance methods for course enrollment changes """
from
__future__
import
absolute_import
from
lettuce
import
world
,
step
from
opaque_keys.edx.locations
import
SlashSeparatedCourseKey
from
logging
import
getLogger
logger
=
getLogger
(
__name__
)
@step
(
u'the course "([^"]*)" has all enrollment modes$'
)
def
add_enrollment_modes_to_course
(
_step
,
course
):
""" Add honor, audit, and verified modes to the sample course """
world
.
CourseModeFactory
.
create
(
course_id
=
SlashSeparatedCourseKey
(
"edx"
,
course
,
'Test_Course'
),
mode_slug
=
"verified"
,
mode_display_name
=
"Verified Course"
,
min_price
=
3
)
world
.
CourseModeFactory
.
create
(
course_id
=
SlashSeparatedCourseKey
(
"edx"
,
course
,
'Test_Course'
),
mode_slug
=
"honor"
,
mode_display_name
=
"Honor Course"
,
)
world
.
CourseModeFactory
.
create
(
course_id
=
SlashSeparatedCourseKey
(
"edx"
,
course
,
'Test_Course'
),
mode_slug
=
"audit"
,
mode_display_name
=
"Audit Course"
,
)
@step
(
u'I click on Challenge Yourself$'
)
def
challenge_yourself
(
_step
):
""" Simulates clicking 'Challenge Yourself' button on course """
challenge_button
=
world
.
browser
.
find_by_css
(
'.wrapper-tip'
)
challenge_button
.
click
()
verified_button
=
world
.
browser
.
find_by_css
(
'#upgrade-to-verified'
)
verified_button
.
click
()
@step
(
u'I choose an honor code upgrade$'
)
def
honor_code_upgrade
(
_step
):
""" Simulates choosing the honor code mode on the upgrade page """
honor_code_link
=
world
.
browser
.
find_by_css
(
'.title-expand'
)
honor_code_link
.
click
()
honor_code_checkbox
=
world
.
browser
.
find_by_css
(
'#honor-code'
)
honor_code_checkbox
.
click
()
upgrade_button
=
world
.
browser
.
find_by_name
(
"certificate_mode"
)
upgrade_button
.
click
()
lms/djangoapps/courseware/features/common.py
View file @
45195375
...
...
@@ -15,7 +15,6 @@ from opaque_keys.edx.locations import SlashSeparatedCourseKey
from
xmodule.course_module
import
CourseDescriptor
from
courseware.courses
import
get_course_by_id
from
xmodule
import
seq_module
,
vertical_module
from
logging
import
getLogger
logger
=
getLogger
(
__name__
)
...
...
@@ -27,7 +26,7 @@ def configure_screenshots_for_all_steps(_step, action):
automatic saving of screenshots before and after each step in a
scenario.
"""
action
=
action
.
strip
()
action
=
action
.
strip
()
if
action
==
'enable'
:
world
.
auto_capture_screenshots
=
True
elif
action
==
'disable'
:
...
...
@@ -35,6 +34,7 @@ def configure_screenshots_for_all_steps(_step, action):
else
:
raise
ValueError
(
'Parameter `action` should be one of "enable" or "disable".'
)
@world.absorb
def
capture_screenshot_before_after
(
func
):
"""
...
...
@@ -43,12 +43,12 @@ def capture_screenshot_before_after(func):
for each step in a scenario, but rather want to debug a single function.
"""
def
inner
(
*
args
,
**
kwargs
):
prefix
=
round
(
time
.
time
()
*
1000
)
prefix
=
round
(
time
.
time
()
*
1000
)
world
.
capture_screenshot
(
"{}_{}_{}"
.
format
(
prefix
,
func
.
func_name
,
'before'
))
ret_val
=
func
(
*
args
,
**
kwargs
)
ret_val
=
func
(
*
args
,
**
kwargs
)
world
.
capture_screenshot
(
"{}_{}_{}"
.
format
(
prefix
,
func
.
func_name
,
'after'
))
...
...
@@ -94,11 +94,11 @@ def i_am_registered_for_the_course(step, course):
# Create the user
world
.
create_user
(
'robot'
,
'test'
)
u
=
User
.
objects
.
get
(
username
=
'robot'
)
u
ser
=
User
.
objects
.
get
(
username
=
'robot'
)
# If the user is not already enrolled, enroll the user.
# TODO: change to factory
CourseEnrollment
.
enroll
(
u
,
course_id
(
course
))
CourseEnrollment
.
enroll
(
u
ser
,
course_id
(
course
))
world
.
log_in
(
username
=
'robot'
,
password
=
'test'
)
...
...
lms/djangoapps/courseware/features/events.py
View file @
45195375
...
...
@@ -36,8 +36,8 @@ def reset_between_outline_scenarios(_scenario, order, outline, reasons_to_fail):
world
.
event_collection
.
drop
()
@step
(
'[aA]n? "(.*)" (server|browser) event is emitted
'
)
def
event_is_emitted
(
_step
,
event_type
,
event_source
):
@step
(
r'([aA]n?|\d+) "(.*)" (server|browser) events? is emitted$
'
)
def
n_events_are_emitted
(
_step
,
count
,
event_type
,
event_source
):
# Ensure all events are written out to mongo before querying.
world
.
mongo_client
.
fsync
()
...
...
@@ -54,8 +54,15 @@ def event_is_emitted(_step, event_type, event_source):
'$ne'
:
'python/splinter'
}
}
cursor
=
world
.
event_collection
.
find
(
criteria
)
assert_equals
(
cursor
.
count
(),
1
)
try
:
number_events
=
int
(
count
)
except
ValueError
:
number_events
=
1
assert_equals
(
cursor
.
count
(),
number_events
)
event
=
cursor
.
next
()
...
...
lms/djangoapps/courseware/features/registration.py
View file @
45195375
...
...
@@ -10,7 +10,16 @@ def i_register_for_the_course(_step, course):
url
=
django_url
(
'courses/
%
s/about'
%
world
.
scenario_dict
[
'COURSE'
]
.
id
.
to_deprecated_string
())
world
.
browser
.
visit
(
url
)
world
.
css_click
(
'section.intro a.register'
)
assert
world
.
is_css_present
(
'section.container.dashboard'
)
@step
(
'I register to audit the course$'
)
def
i_register_to_audit_the_course
(
_step
):
url
=
django_url
(
'courses/
%
s/about'
%
world
.
scenario_dict
[
'COURSE'
]
.
id
.
to_deprecated_string
())
world
.
browser
.
visit
(
url
)
world
.
css_click
(
'section.intro a.register'
)
audit_button
=
world
.
browser
.
find_by_name
(
"audit_mode"
)
audit_button
.
click
()
assert
world
.
is_css_present
(
'section.container.dashboard'
)
...
...
lms/djangoapps/verify_student/tests/test_views.py
View file @
45195375
...
...
@@ -35,7 +35,6 @@ from verify_student.models import SoftwareSecurePhotoVerification
from
reverification.tests.factories
import
MidcourseReverificationWindowFactory
def
mock_render_to_response
(
*
args
,
**
kwargs
):
return
render_to_response
(
*
args
,
**
kwargs
)
...
...
@@ -386,8 +385,17 @@ class TestMidCourseReverifyView(TestCase):
kwargs
=
{
"course_id"
:
self
.
course_key
.
to_deprecated_string
()})
response
=
self
.
client
.
get
(
url
)
# Check that user entering the reverify flow was logged
self
.
mock_tracker
.
emit
.
assert_called_once_with
(
# pylint: disable=maybe-no-member
self
.
mock_tracker
.
emit
.
assert_any_call
(
# pylint: disable=maybe-no-member
'edx.course.enrollment.mode_changed'
,
{
'user_id'
:
self
.
user
.
id
,
'course_id'
:
self
.
course_key
.
to_deprecated_string
(),
'mode'
:
"verified"
,
}
)
# Check that user entering the reverify flow was logged, and that it was the last call
self
.
mock_tracker
.
emit
.
assert_called_with
(
# pylint: disable=maybe-no-member
'edx.course.enrollment.reverify.started'
,
{
'user_id'
:
self
.
user
.
id
,
...
...
@@ -395,6 +403,9 @@ class TestMidCourseReverifyView(TestCase):
'mode'
:
"verified"
,
}
)
self
.
assertTrue
(
self
.
mock_tracker
.
emit
.
call_count
,
2
)
self
.
mock_tracker
.
emit
.
reset_mock
()
# pylint: disable=maybe-no-member
self
.
assertEquals
(
response
.
status_code
,
200
)
...
...
@@ -408,8 +419,17 @@ class TestMidCourseReverifyView(TestCase):
response
=
self
.
client
.
post
(
url
,
{
'face_image'
:
','
})
# Check that submission event was logged
self
.
mock_tracker
.
emit
.
assert_called_once_with
(
# pylint: disable=maybe-no-member
self
.
mock_tracker
.
emit
.
assert_any_call
(
# pylint: disable=maybe-no-member
'edx.course.enrollment.mode_changed'
,
{
'user_id'
:
self
.
user
.
id
,
'course_id'
:
self
.
course_key
.
to_deprecated_string
(),
'mode'
:
"verified"
,
}
)
# Check that submission event was logged, and that it was the last call
self
.
mock_tracker
.
emit
.
assert_called_with
(
# pylint: disable=maybe-no-member
'edx.course.enrollment.reverify.submitted'
,
{
'user_id'
:
self
.
user
.
id
,
...
...
@@ -417,6 +437,9 @@ class TestMidCourseReverifyView(TestCase):
'mode'
:
"verified"
,
}
)
self
.
assertTrue
(
self
.
mock_tracker
.
emit
.
call_count
,
2
)
self
.
mock_tracker
.
emit
.
reset_mock
()
# pylint: disable=maybe-no-member
self
.
assertEquals
(
response
.
status_code
,
302
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment