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
1059456d
Commit
1059456d
authored
Sep 02, 2015
by
wajeeha-khalid
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
added GET method for Threads in Dicussion API
parent
83e6da06
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
261 additions
and
3 deletions
+261
-3
lms/djangoapps/discussion_api/api.py
+18
-1
lms/djangoapps/discussion_api/tests/test_api.py
+171
-0
lms/djangoapps/discussion_api/tests/test_views.py
+64
-0
lms/djangoapps/discussion_api/views.py
+7
-1
lms/djangoapps/django_comment_client/base/views.py
+1
-1
No files found.
lms/djangoapps/discussion_api/api.py
View file @
1059456d
...
...
@@ -39,7 +39,7 @@ from django_comment_common.signals import (
comment_created
,
comment_edited
,
comment_voted
,
comment_deleted
comment_deleted
,
)
from
django_comment_client.utils
import
get_accessible_discussion_modules
,
is_commentable_cohorted
from
lms.lib.comment_client.comment
import
Comment
...
...
@@ -697,6 +697,23 @@ def update_comment(request, comment_id, update_data):
return
api_comment
def
get_thread
(
request
,
thread_id
):
"""
Retrieve a thread.
Arguments:
request: The django request object used for build_absolute_uri and
determining the requesting user.
thread_id: The id for the thread to retrieve
"""
cc_thread
,
context
=
_get_thread_and_context
(
request
,
thread_id
)
serializer
=
ThreadSerializer
(
cc_thread
,
context
=
context
)
return
serializer
.
data
def
delete_thread
(
request
,
thread_id
):
"""
Delete a thread.
...
...
lms/djangoapps/discussion_api/tests/test_api.py
View file @
1059456d
...
...
@@ -33,6 +33,7 @@ from discussion_api.api import (
get_thread_list
,
update_comment
,
update_thread
,
get_thread
,
)
from
discussion_api.tests.utils
import
(
CommentsServiceMockMixin
,
...
...
@@ -2786,3 +2787,173 @@ class DeleteCommentTest(
self
.
assertFalse
(
expected_error
)
except
Http404
:
self
.
assertTrue
(
expected_error
)
@ddt.ddt
class
RetrieveThreadTest
(
CommentsServiceMockMixin
,
UrlResetMixin
,
SharedModuleStoreTestCase
):
"""Tests for get_thread"""
@classmethod
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_DISCUSSION_SERVICE"
:
True
})
def
setUpClass
(
cls
):
super
(
RetrieveThreadTest
,
cls
)
.
setUpClass
()
cls
.
course
=
CourseFactory
.
create
()
@mock.patch.dict
(
"django.conf.settings.FEATURES"
,
{
"ENABLE_DISCUSSION_SERVICE"
:
True
})
def
setUp
(
self
):
super
(
RetrieveThreadTest
,
self
)
.
setUp
()
httpretty
.
reset
()
httpretty
.
enable
()
self
.
addCleanup
(
httpretty
.
disable
)
self
.
thread_author
=
UserFactory
.
create
()
self
.
register_get_user_response
(
self
.
thread_author
)
self
.
request
=
RequestFactory
()
.
get
(
"/test_path"
)
self
.
request
.
user
=
self
.
thread_author
self
.
thread_id
=
"test_thread"
CourseEnrollmentFactory
.
create
(
user
=
self
.
thread_author
,
course_id
=
self
.
course
.
id
)
def
register_thread
(
self
,
overrides
=
None
):
"""
Make a thread with appropriate data overridden by the overrides
parameter and register mock responses for GET on its
endpoint.
"""
cs_data
=
make_minimal_cs_thread
({
"id"
:
self
.
thread_id
,
"course_id"
:
unicode
(
self
.
course
.
id
),
"commentable_id"
:
"test_topic"
,
"username"
:
self
.
thread_author
.
username
,
"user_id"
:
str
(
self
.
thread_author
.
id
),
"title"
:
"Test Title"
,
"body"
:
"Test body"
,
"created_at"
:
"2015-05-29T00:00:00Z"
,
"updated_at"
:
"2015-05-29T00:00:00Z"
})
cs_data
.
update
(
overrides
or
{})
self
.
register_get_thread_response
(
cs_data
)
def
test_basic
(
self
):
expected_response_data
=
{
"author"
:
self
.
thread_author
.
username
,
"author_label"
:
None
,
"created_at"
:
"2015-05-29T00:00:00Z"
,
"updated_at"
:
"2015-05-29T00:00:00Z"
,
"raw_body"
:
"Test body"
,
"rendered_body"
:
"<p>Test body</p>"
,
"abuse_flagged"
:
False
,
"voted"
:
False
,
"vote_count"
:
0
,
"editable_fields"
:
[
"abuse_flagged"
,
"following"
,
"raw_body"
,
"title"
,
"topic_id"
,
"type"
,
"voted"
],
"course_id"
:
unicode
(
self
.
course
.
id
),
"topic_id"
:
"test_topic"
,
"group_id"
:
None
,
"group_name"
:
None
,
"title"
:
"Test Title"
,
"pinned"
:
False
,
"closed"
:
False
,
"following"
:
False
,
"comment_count"
:
0
,
"unread_comment_count"
:
0
,
"comment_list_url"
:
"http://testserver/api/discussion/v1/comments/?thread_id=test_thread"
,
"endorsed_comment_list_url"
:
None
,
"non_endorsed_comment_list_url"
:
None
,
"read"
:
False
,
"has_endorsed"
:
False
,
"id"
:
"test_thread"
,
"type"
:
"discussion"
}
self
.
register_thread
()
self
.
assertEqual
(
get_thread
(
self
.
request
,
self
.
thread_id
),
expected_response_data
)
self
.
assertEqual
(
httpretty
.
last_request
()
.
method
,
"GET"
)
def
test_thread_id_not_found
(
self
):
self
.
register_get_thread_error_response
(
"missing_thread"
,
404
)
with
self
.
assertRaises
(
Http404
):
get_thread
(
self
.
request
,
"missing_thread"
)
def
test_nonauthor_enrolled_in_course
(
self
):
expected_response_data
=
{
"author"
:
self
.
thread_author
.
username
,
"author_label"
:
None
,
"created_at"
:
"2015-05-29T00:00:00Z"
,
"updated_at"
:
"2015-05-29T00:00:00Z"
,
"raw_body"
:
"Test body"
,
"rendered_body"
:
"<p>Test body</p>"
,
"abuse_flagged"
:
False
,
"voted"
:
False
,
"vote_count"
:
0
,
"editable_fields"
:
[
"abuse_flagged"
,
"following"
,
"voted"
],
"course_id"
:
unicode
(
self
.
course
.
id
),
"topic_id"
:
"test_topic"
,
"group_id"
:
None
,
"group_name"
:
None
,
"title"
:
"Test Title"
,
"pinned"
:
False
,
"closed"
:
False
,
"following"
:
False
,
"comment_count"
:
0
,
"unread_comment_count"
:
0
,
"comment_list_url"
:
"http://testserver/api/discussion/v1/comments/?thread_id=test_thread"
,
"endorsed_comment_list_url"
:
None
,
"non_endorsed_comment_list_url"
:
None
,
"read"
:
False
,
"has_endorsed"
:
False
,
"id"
:
"test_thread"
,
"type"
:
"discussion"
}
non_author_user
=
UserFactory
.
create
()
# pylint: disable=attribute-defined-outside-init
self
.
register_get_user_response
(
non_author_user
)
CourseEnrollmentFactory
.
create
(
user
=
non_author_user
,
course_id
=
self
.
course
.
id
)
self
.
register_thread
()
self
.
request
.
user
=
non_author_user
self
.
assertEqual
(
get_thread
(
self
.
request
,
self
.
thread_id
),
expected_response_data
)
self
.
assertEqual
(
httpretty
.
last_request
()
.
method
,
"GET"
)
@ddt.data
(
*
itertools
.
product
(
[
FORUM_ROLE_ADMINISTRATOR
,
FORUM_ROLE_MODERATOR
,
FORUM_ROLE_COMMUNITY_TA
,
FORUM_ROLE_STUDENT
,
],
[
True
,
False
],
[
"no_group"
,
"match_group"
,
"different_group"
],
)
)
@ddt.unpack
def
test_group_access
(
self
,
role_name
,
course_is_cohorted
,
thread_group_state
):
"""
Tests group access for retrieving a thread
All privileged roles are able to retrieve a thread. A student role can
only retrieve a thread if,
the student role is the author and the thread is not in a cohort,
the student role is the author and the thread is in the author's cohort.
"""
cohort_course
=
CourseFactory
.
create
(
cohort_config
=
{
"cohorted"
:
course_is_cohorted
})
CourseEnrollmentFactory
.
create
(
user
=
self
.
thread_author
,
course_id
=
cohort_course
.
id
)
cohort
=
CohortFactory
.
create
(
course_id
=
cohort_course
.
id
,
users
=
[
self
.
thread_author
])
role
=
Role
.
objects
.
create
(
name
=
role_name
,
course_id
=
cohort_course
.
id
)
role
.
users
=
[
self
.
thread_author
]
self
.
register_thread
({
"course_id"
:
unicode
(
cohort_course
.
id
),
"group_id"
:
(
None
if
thread_group_state
==
"no_group"
else
cohort
.
id
if
thread_group_state
==
"match_group"
else
cohort
.
id
+
1
),
})
expected_error
=
(
role_name
==
FORUM_ROLE_STUDENT
and
course_is_cohorted
and
thread_group_state
==
"different_group"
)
try
:
get_thread
(
self
.
request
,
self
.
thread_id
)
self
.
assertFalse
(
expected_error
)
except
Http404
:
self
.
assertTrue
(
expected_error
)
lms/djangoapps/discussion_api/tests/test_views.py
View file @
1059456d
...
...
@@ -588,6 +588,7 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self
.
thread_id
=
"test_thread"
def
test_basic
(
self
):
#from nose.tools import set_trace;set_trace()
self
.
register_get_user_response
(
self
.
user
)
cs_thread
=
make_minimal_cs_thread
({
"id"
:
self
.
thread_id
,
...
...
@@ -607,6 +608,7 @@ class ThreadViewSetDeleteTest(DiscussionAPIViewTestMixin, ModuleStoreTestCase):
self
.
assertEqual
(
httpretty
.
last_request
()
.
method
,
"DELETE"
)
def
test_delete_nonexistent_thread
(
self
):
#from nose.tools import set_trace;set_trace()
self
.
register_get_thread_error_response
(
self
.
thread_id
,
404
)
response
=
self
.
client
.
delete
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
404
)
...
...
@@ -951,3 +953,65 @@ class CommentViewSetPartialUpdateTest(DiscussionAPIViewTestMixin, ModuleStoreTes
self
.
assertEqual
(
response
.
status_code
,
400
)
response_data
=
json
.
loads
(
response
.
content
)
self
.
assertEqual
(
response_data
,
expected_response_data
)
@httpretty.activate
class
ThreadViewSetRetrieveTest
(
DiscussionAPIViewTestMixin
,
ModuleStoreTestCase
):
"""Tests for ThreadViewSet Retrieve"""
def
setUp
(
self
):
super
(
ThreadViewSetRetrieveTest
,
self
)
.
setUp
()
self
.
url
=
reverse
(
"thread-detail"
,
kwargs
=
{
"thread_id"
:
"test_thread"
})
self
.
thread_id
=
"test_thread"
def
test_basic
(
self
):
self
.
register_get_user_response
(
self
.
user
)
cs_thread
=
make_minimal_cs_thread
({
"id"
:
self
.
thread_id
,
"course_id"
:
unicode
(
self
.
course
.
id
),
"commentable_id"
:
"test_topic"
,
"username"
:
self
.
user
.
username
,
"user_id"
:
str
(
self
.
user
.
id
),
"title"
:
"Test Title"
,
"body"
:
"Test body"
,
"created_at"
:
"2015-05-29T00:00:00Z"
,
"updated_at"
:
"2015-05-29T00:00:00Z"
})
expected_response_data
=
{
"author"
:
self
.
user
.
username
,
"author_label"
:
None
,
"created_at"
:
"2015-05-29T00:00:00Z"
,
"updated_at"
:
"2015-05-29T00:00:00Z"
,
"raw_body"
:
"Test body"
,
"rendered_body"
:
"<p>Test body</p>"
,
"abuse_flagged"
:
False
,
"voted"
:
False
,
"vote_count"
:
0
,
"editable_fields"
:
[
"abuse_flagged"
,
"following"
,
"raw_body"
,
"title"
,
"topic_id"
,
"type"
,
"voted"
],
"course_id"
:
unicode
(
self
.
course
.
id
),
"topic_id"
:
"test_topic"
,
"group_id"
:
None
,
"group_name"
:
None
,
"title"
:
"Test Title"
,
"pinned"
:
False
,
"closed"
:
False
,
"following"
:
False
,
"comment_count"
:
0
,
"unread_comment_count"
:
0
,
"comment_list_url"
:
"http://testserver/api/discussion/v1/comments/?thread_id=test_thread"
,
"endorsed_comment_list_url"
:
None
,
"non_endorsed_comment_list_url"
:
None
,
"read"
:
False
,
"has_endorsed"
:
False
,
"id"
:
"test_thread"
,
"type"
:
"discussion"
}
self
.
register_get_thread_response
(
cs_thread
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
json
.
loads
(
response
.
content
),
expected_response_data
)
self
.
assertEqual
(
httpretty
.
last_request
()
.
method
,
"GET"
)
def
test_retrieve_nonexistent_thread
(
self
):
self
.
register_get_thread_error_response
(
self
.
thread_id
,
404
)
response
=
self
.
client
.
get
(
self
.
url
)
self
.
assertEqual
(
response
.
status_code
,
404
)
lms/djangoapps/discussion_api/views.py
View file @
1059456d
...
...
@@ -22,7 +22,7 @@ from discussion_api.api import (
get_thread_list
,
update_comment
,
update_thread
,
)
get_thread
)
from
discussion_api.forms
import
CommentListGetForm
,
ThreadListGetForm
from
openedx.core.lib.api.view_utils
import
DeveloperErrorViewMixin
...
...
@@ -257,6 +257,12 @@ class ThreadViewSet(_ViewMixin, DeveloperErrorViewMixin, ViewSet):
)
)
def
retrieve
(
self
,
request
,
thread_id
=
None
):
"""
Implements the GET method for thread ID
"""
return
Response
(
get_thread
(
request
,
thread_id
))
def
create
(
self
,
request
):
"""
Implements the POST method for the list endpoint as described in the
...
...
lms/djangoapps/django_comment_client/base/views.py
View file @
1059456d
...
...
@@ -27,7 +27,7 @@ from django_comment_common.signals import (
comment_edited
,
comment_voted
,
comment_deleted
,
comment_endorsed
comment_endorsed
,
)
from
django_comment_common.utils
import
ThreadContext
from
django_comment_client.utils
import
(
...
...
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