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
066d5ab6
Commit
066d5ab6
authored
Jul 29, 2015
by
Carlos de la Guardia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Changes to a CCX course should emit a course_published event
parent
8da4fcbb
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
154 additions
and
0 deletions
+154
-0
lms/djangoapps/ccx/tasks.py
+45
-0
lms/djangoapps/ccx/tests/test_tasks.py
+109
-0
No files found.
lms/djangoapps/ccx/tasks.py
0 → 100644
View file @
066d5ab6
"""
Asynchronous tasks for the CCX app.
"""
from
django.dispatch
import
receiver
import
logging
from
opaque_keys
import
InvalidKeyError
from
opaque_keys.edx.locator
import
CourseLocator
from
ccx_keys.locator
import
CCXLocator
from
xmodule.modulestore.django
import
SignalHandler
from
lms
import
CELERY_APP
from
.models
import
CustomCourseForEdX
log
=
logging
.
getLogger
(
"edx.ccx"
)
@receiver
(
SignalHandler
.
course_published
)
def
course_published_handler
(
sender
,
course_key
,
**
kwargs
):
# pylint: disable=unused-argument
"""
Consume signals that indicate course published. If course already a CCX, do nothing.
"""
if
not
isinstance
(
course_key
,
CCXLocator
):
send_ccx_course_published
.
delay
(
unicode
(
course_key
))
@CELERY_APP.task
def
send_ccx_course_published
(
course_key
):
"""
Find all CCX derived from this course, and send course published event for them.
"""
course_key
=
CourseLocator
.
from_string
(
course_key
)
for
ccx
in
CustomCourseForEdX
.
objects
.
filter
(
course_id
=
course_key
):
try
:
ccx_key
=
CCXLocator
.
from_course_locator
(
course_key
,
ccx
.
id
)
except
InvalidKeyError
:
log
.
info
(
'Attempt to publish course with deprecated id. Course:
%
s. CCX:
%
s'
,
course_key
,
ccx
.
id
)
continue
responses
=
SignalHandler
.
course_published
.
send
(
sender
=
ccx
,
course_key
=
ccx_key
)
for
rec
,
response
in
responses
:
log
.
info
(
'Signal fired when course is published. Receiver:
%
s. Response:
%
s'
,
rec
,
response
)
lms/djangoapps/ccx/tests/test_tasks.py
0 → 100644
View file @
066d5ab6
"""
Tests for celery tasks defined in tasks module
"""
from
mock_django
import
mock_signal_receiver
from
ccx.tests.factories
import
(
# pylint: disable=import-error
CcxFactory
,
)
from
student.roles
import
CourseCcxCoachRole
# pylint: disable=import-error
from
student.tests.factories
import
(
# pylint: disable=import-error
AdminFactory
,
)
from
xmodule.modulestore.django
import
SignalHandler
from
xmodule.modulestore.tests.factories
import
CourseFactory
from
xmodule.modulestore.tests.django_utils
import
(
ModuleStoreTestCase
,
TEST_DATA_SPLIT_MODULESTORE
)
from
openedx.core.djangoapps.content.course_structures.models
import
CourseStructure
from
openedx.core.djangoapps.content.course_overviews.models
import
CourseOverview
from
ccx_keys.locator
import
CCXLocator
from
..tasks
import
send_ccx_course_published
class
TestSendCCXCoursePublished
(
ModuleStoreTestCase
):
"""unit tests for the send ccx course published task
"""
MODULESTORE
=
TEST_DATA_SPLIT_MODULESTORE
def
setUp
(
self
):
"""
Set up tests
"""
super
(
TestSendCCXCoursePublished
,
self
)
.
setUp
()
course
=
self
.
course
=
CourseFactory
.
create
(
org
=
"edX"
,
course
=
"999"
,
display_name
=
"Run 666"
)
course2
=
self
.
course2
=
CourseFactory
.
create
(
org
=
"edX"
,
course
=
"999a"
,
display_name
=
"Run 667"
)
coach
=
AdminFactory
.
create
()
role
=
CourseCcxCoachRole
(
course
.
id
)
role
.
add_users
(
coach
)
self
.
ccx
=
CcxFactory
(
course_id
=
course
.
id
,
coach
=
coach
)
self
.
ccx2
=
CcxFactory
(
course_id
=
course
.
id
,
coach
=
coach
)
self
.
ccx3
=
CcxFactory
(
course_id
=
course
.
id
,
coach
=
coach
)
self
.
ccx4
=
CcxFactory
(
course_id
=
course2
.
id
,
coach
=
coach
)
def
call_fut
(
self
,
course_key
):
"""Call the function under test
"""
send_ccx_course_published
(
unicode
(
course_key
))
def
test_signal_not_sent_for_ccx
(
self
):
"""Check that course published signal is not sent when course key is for a ccx
"""
course_key
=
CCXLocator
.
from_course_locator
(
self
.
course
.
id
,
self
.
ccx
.
id
)
with
mock_signal_receiver
(
SignalHandler
.
course_published
)
as
receiver
:
self
.
call_fut
(
course_key
)
self
.
assertEqual
(
receiver
.
call_count
,
0
)
def
test_signal_sent_for_ccx
(
self
):
"""Check that course published signal is sent when course key is not for a ccx.
We have 4 ccx's, but only 3 are derived from the course id used here, so call
count must be 3 to confirm that all derived courses and no more got the signal.
"""
with
mock_signal_receiver
(
SignalHandler
.
course_published
)
as
receiver
:
self
.
call_fut
(
self
.
course
.
id
)
self
.
assertEqual
(
receiver
.
call_count
,
3
)
def
test_course_structure_generated
(
self
):
"""Check that course structure is generated after course published signal is sent
"""
ccx_structure
=
{
u"blocks"
:
{
u"ccx-block-v1:edX+999+Run_666+ccx@1+type@course+block@course"
:
{
u"block_type"
:
u"course"
,
u"graded"
:
False
,
u"format"
:
None
,
u"usage_key"
:
u"ccx-block-v1:edX+999+Run_666+ccx@1+type@course+block@course"
,
u"children"
:
[
],
u"display_name"
:
u"Run 666"
}
},
u"root"
:
u"ccx-block-v1:edX+999+Run_666+ccx@1+type@course+block@course"
}
course_key
=
CCXLocator
.
from_course_locator
(
self
.
course
.
id
,
self
.
ccx
.
id
)
structure
=
CourseStructure
.
objects
.
filter
(
course_id
=
course_key
)
# no structure exists before signal is called
self
.
assertEqual
(
len
(
structure
),
0
)
with
mock_signal_receiver
(
SignalHandler
.
course_published
)
as
receiver
:
self
.
call_fut
(
self
.
course
.
id
)
self
.
assertEqual
(
receiver
.
call_count
,
3
)
structure
=
CourseStructure
.
objects
.
get
(
course_id
=
course_key
)
self
.
assertEqual
(
structure
.
structure
,
ccx_structure
)
def
test_course_overview_deleted
(
self
):
"""Check that course overview is deleted after course published signal is sent
"""
course_key
=
CCXLocator
.
from_course_locator
(
self
.
course
.
id
,
self
.
ccx
.
id
)
overview
=
CourseOverview
(
id
=
course_key
)
overview
.
save
()
overview
=
CourseOverview
.
objects
.
filter
(
id
=
course_key
)
self
.
assertEqual
(
len
(
overview
),
1
)
with
mock_signal_receiver
(
SignalHandler
.
course_published
)
as
receiver
:
self
.
call_fut
(
self
.
course
.
id
)
self
.
assertEqual
(
receiver
.
call_count
,
3
)
overview
=
CourseOverview
.
objects
.
filter
(
id
=
course_key
)
self
.
assertEqual
(
len
(
overview
),
0
)
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