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
840f5017
Commit
840f5017
authored
Dec 30, 2015
by
Ehtesham
Committed by
muzaffaryousaf
Feb 24, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[TNL-3940] Adding pagination in stub server and updating unit tests
parent
e2333214
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
230 additions
and
23 deletions
+230
-23
common/djangoapps/terrain/stubs/edxnotes.py
+61
-10
common/djangoapps/terrain/stubs/tests/test_edxnotes.py
+169
-13
No files found.
common/djangoapps/terrain/stubs/edxnotes.py
View file @
840f5017
...
@@ -7,11 +7,12 @@ import re
...
@@ -7,11 +7,12 @@ import re
from
uuid
import
uuid4
from
uuid
import
uuid4
from
datetime
import
datetime
from
datetime
import
datetime
from
copy
import
deepcopy
from
copy
import
deepcopy
from
math
import
ceil
from
urllib
import
urlencode
from
.http
import
StubHttpRequestHandler
,
StubHttpService
from
.http
import
StubHttpRequestHandler
,
StubHttpService
# pylint: disable=invalid-name
class
StubEdxNotesServiceHandler
(
StubHttpRequestHandler
):
class
StubEdxNotesServiceHandler
(
StubHttpRequestHandler
):
"""
"""
Handler for EdxNotes requests.
Handler for EdxNotes requests.
...
@@ -165,7 +166,7 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
...
@@ -165,7 +166,7 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
"""
"""
Return the note by note id.
Return the note by note id.
"""
"""
notes
=
self
.
server
.
get_notes
()
notes
=
self
.
server
.
get_
all_
notes
()
result
=
self
.
server
.
filter_by_id
(
notes
,
note_id
)
result
=
self
.
server
.
filter_by_id
(
notes
,
note_id
)
if
result
:
if
result
:
self
.
respond
(
content
=
result
[
0
])
self
.
respond
(
content
=
result
[
0
])
...
@@ -191,6 +192,53 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
...
@@ -191,6 +192,53 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
else
:
else
:
self
.
respond
(
404
,
"404 Not Found"
)
self
.
respond
(
404
,
"404 Not Found"
)
@staticmethod
def
_get_next_prev_url
(
url_path
,
query_params
,
page_num
,
page_size
):
"""
makes url with the query params including pagination params
for pagination next and previous urls
"""
query_params
=
deepcopy
(
query_params
)
query_params
.
update
({
"page"
:
page_num
,
"page_size"
:
page_size
})
return
url_path
+
"?"
+
urlencode
(
query_params
)
def
_get_paginated_response
(
self
,
notes
,
page_num
,
page_size
):
"""
Returns a paginated response of notes.
"""
start
=
(
page_num
-
1
)
*
page_size
end
=
start
+
page_size
total_notes
=
len
(
notes
)
url_path
=
"http://{server_address}:{port}{path}"
.
format
(
server_address
=
self
.
client_address
[
0
],
port
=
self
.
server
.
port
,
path
=
self
.
path_only
)
next_url
=
None
if
end
>=
total_notes
else
self
.
_get_next_prev_url
(
url_path
,
self
.
get_params
,
page_num
+
1
,
page_size
)
prev_url
=
None
if
page_num
==
1
else
self
.
_get_next_prev_url
(
url_path
,
self
.
get_params
,
page_num
-
1
,
page_size
)
# Get notes from range
notes
=
deepcopy
(
notes
[
start
:
end
])
paginated_response
=
{
'total'
:
total_notes
,
'num_pages'
:
int
(
ceil
(
float
(
total_notes
)
/
page_size
)),
'current_page'
:
page_num
,
'rows'
:
notes
,
'next'
:
next_url
,
'start'
:
start
,
'previous'
:
prev_url
}
return
paginated_response
def
_search
(
self
):
def
_search
(
self
):
"""
"""
Search for a notes by user id, course_id and usage_id.
Search for a notes by user id, course_id and usage_id.
...
@@ -199,32 +247,35 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
...
@@ -199,32 +247,35 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
usage_id
=
self
.
get_params
.
get
(
"usage_id"
,
None
)
usage_id
=
self
.
get_params
.
get
(
"usage_id"
,
None
)
course_id
=
self
.
get_params
.
get
(
"course_id"
,
None
)
course_id
=
self
.
get_params
.
get
(
"course_id"
,
None
)
text
=
self
.
get_params
.
get
(
"text"
,
None
)
text
=
self
.
get_params
.
get
(
"text"
,
None
)
page
=
int
(
self
.
get_params
.
get
(
"page"
,
1
))
page_size
=
int
(
self
.
get_params
.
get
(
"page_size"
,
2
))
if
user
is
None
:
if
user
is
None
:
self
.
respond
(
400
,
"Bad Request"
)
self
.
respond
(
400
,
"Bad Request"
)
return
return
notes
=
self
.
server
.
get_notes
()
notes
=
self
.
server
.
get_
all_
notes
()
if
course_id
is
not
None
:
if
course_id
is
not
None
:
notes
=
self
.
server
.
filter_by_course_id
(
notes
,
course_id
)
notes
=
self
.
server
.
filter_by_course_id
(
notes
,
course_id
)
if
usage_id
is
not
None
:
if
usage_id
is
not
None
:
notes
=
self
.
server
.
filter_by_usage_id
(
notes
,
usage_id
)
notes
=
self
.
server
.
filter_by_usage_id
(
notes
,
usage_id
)
if
text
:
if
text
:
notes
=
self
.
server
.
search
(
notes
,
text
)
notes
=
self
.
server
.
search
(
notes
,
text
)
self
.
respond
(
content
=
{
self
.
respond
(
content
=
self
.
_get_paginated_response
(
notes
,
page
,
page_size
))
"total"
:
len
(
notes
),
"rows"
:
notes
,
})
def
_collection
(
self
):
def
_collection
(
self
):
"""
"""
Return all notes for the user.
Return all notes for the user.
"""
"""
user
=
self
.
get_params
.
get
(
"user"
,
None
)
user
=
self
.
get_params
.
get
(
"user"
,
None
)
page
=
int
(
self
.
get_params
.
get
(
"page"
,
1
))
page_size
=
int
(
self
.
get_params
.
get
(
"page_size"
,
2
))
notes
=
self
.
server
.
get_all_notes
()
if
user
is
None
:
if
user
is
None
:
self
.
send_response
(
400
,
content
=
"Bad Request"
)
self
.
send_response
(
400
,
content
=
"Bad Request"
)
return
return
notes
=
self
.
server
.
get_notes
(
)
notes
=
self
.
_get_paginated_response
(
notes
,
page
,
page_size
)
self
.
respond
(
content
=
notes
)
self
.
respond
(
content
=
notes
)
def
_cleanup
(
self
):
def
_cleanup
(
self
):
...
@@ -245,9 +296,9 @@ class StubEdxNotesService(StubHttpService):
...
@@ -245,9 +296,9 @@ class StubEdxNotesService(StubHttpService):
super
(
StubEdxNotesService
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
super
(
StubEdxNotesService
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
self
.
notes
=
list
()
self
.
notes
=
list
()
def
get_notes
(
self
):
def
get_
all_
notes
(
self
):
"""
"""
Returns a list of all notes
.
Returns a list of all notes
without pagination
"""
"""
notes
=
deepcopy
(
self
.
notes
)
notes
=
deepcopy
(
self
.
notes
)
notes
.
reverse
()
notes
.
reverse
()
...
...
common/djangoapps/terrain/stubs/tests/test_edxnotes.py
View file @
840f5017
"""
"""
Unit tests for stub EdxNotes implementation.
Unit tests for stub EdxNotes implementation.
"""
"""
import
urlparse
import
json
import
json
import
unittest
import
unittest
import
requests
import
requests
...
@@ -19,7 +19,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -19,7 +19,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
"""
"""
super
(
StubEdxNotesServiceTest
,
self
)
.
setUp
()
super
(
StubEdxNotesServiceTest
,
self
)
.
setUp
()
self
.
server
=
StubEdxNotesService
()
self
.
server
=
StubEdxNotesService
()
dummy_notes
=
self
.
_get_dummy_notes
(
count
=
2
)
dummy_notes
=
self
.
_get_dummy_notes
(
count
=
5
)
self
.
server
.
add_notes
(
dummy_notes
)
self
.
server
.
add_notes
(
dummy_notes
)
self
.
addCleanup
(
self
.
server
.
shutdown
)
self
.
addCleanup
(
self
.
server
.
shutdown
)
...
@@ -99,17 +99,48 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -99,17 +99,48 @@ class StubEdxNotesServiceTest(unittest.TestCase):
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
def
test_search
(
self
):
def
test_search
(
self
):
# Without user
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/search"
))
self
.
assertEqual
(
response
.
status_code
,
400
)
# get response with default page and page size
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/search"
),
params
=
{
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/search"
),
params
=
{
"user"
:
"dummy-user-id"
,
"user"
:
"dummy-user-id"
,
"usage_id"
:
"dummy-usage-id"
,
"usage_id"
:
"dummy-usage-id"
,
"course_id"
:
"dummy-course-id"
,
"course_id"
:
"dummy-course-id"
,
})
})
notes
=
self
.
_get_notes
()
self
.
assertTrue
(
response
.
ok
)
self
.
assertTrue
(
response
.
ok
)
self
.
assertDictEqual
({
"total"
:
2
,
"rows"
:
notes
},
response
.
json
())
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
5
,
num_pages
=
3
,
notes_per_page
=
2
,
start
=
0
,
current_page
=
1
,
next_page
=
2
,
previous_page
=
None
)
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/search"
))
# search notes with text that don't exist
self
.
assertEqual
(
response
.
status_code
,
400
)
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/search"
),
params
=
{
"user"
:
"dummy-user-id"
,
"usage_id"
:
"dummy-usage-id"
,
"course_id"
:
"dummy-course-id"
,
"text"
:
"world war 2"
})
self
.
assertTrue
(
response
.
ok
)
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
0
,
num_pages
=
0
,
notes_per_page
=
0
,
start
=
0
,
current_page
=
1
,
next_page
=
None
,
previous_page
=
None
)
def
test_delete
(
self
):
def
test_delete
(
self
):
notes
=
self
.
_get_notes
()
notes
=
self
.
_get_notes
()
...
@@ -119,7 +150,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -119,7 +150,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
for
note
in
notes
:
for
note
in
notes
:
response
=
requests
.
delete
(
self
.
_get_url
(
"api/v1/annotations/"
+
note
[
"id"
]))
response
=
requests
.
delete
(
self
.
_get_url
(
"api/v1/annotations/"
+
note
[
"id"
]))
self
.
assertEqual
(
response
.
status_code
,
204
)
self
.
assertEqual
(
response
.
status_code
,
204
)
remaining_notes
=
self
.
server
.
get_notes
()
remaining_notes
=
self
.
server
.
get_
all_
notes
()
self
.
assertNotIn
(
note
[
"id"
],
[
note
[
"id"
]
for
note
in
remaining_notes
])
self
.
assertNotIn
(
note
[
"id"
],
[
note
[
"id"
]
for
note
in
remaining_notes
])
self
.
assertEqual
(
len
(
remaining_notes
),
0
)
self
.
assertEqual
(
len
(
remaining_notes
),
0
)
...
@@ -139,24 +170,149 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -139,24 +170,149 @@ class StubEdxNotesServiceTest(unittest.TestCase):
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations/does_not_exist"
))
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations/does_not_exist"
))
self
.
assertEqual
(
response
.
status_code
,
404
)
self
.
assertEqual
(
response
.
status_code
,
404
)
# pylint: disable=too-many-arguments
def
_verify_pagination_info
(
self
,
response
,
total_notes
,
num_pages
,
notes_per_page
,
current_page
,
previous_page
,
next_page
,
start
):
"""
Verify the pagination information.
Argument:
response: response from api
total_notes: total notes in the response
num_pages: total number of pages in response
notes_per_page: number of notes in the response
current_page: current page number
previous_page: previous page number
next_page: next page number
start: start of the current page
"""
def
get_page_value
(
url
):
"""
Return page value extracted from url.
"""
if
url
is
None
:
return
None
parsed
=
urlparse
.
urlparse
(
url
)
query_params
=
urlparse
.
parse_qs
(
parsed
.
query
)
page
=
query_params
[
"page"
][
0
]
return
page
if
page
is
None
else
int
(
page
)
self
.
assertEqual
(
response
[
"total"
],
total_notes
)
self
.
assertEqual
(
response
[
"num_pages"
],
num_pages
)
self
.
assertEqual
(
len
(
response
[
"rows"
]),
notes_per_page
)
self
.
assertEqual
(
response
[
"current_page"
],
current_page
)
self
.
assertEqual
(
get_page_value
(
response
[
"previous"
]),
previous_page
)
self
.
assertEqual
(
get_page_value
(
response
[
"next"
]),
next_page
)
self
.
assertEqual
(
response
[
"start"
],
start
)
def
test_notes_collection
(
self
):
def
test_notes_collection
(
self
):
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
),
params
=
{
"user"
:
"dummy-user-id"
})
"""
self
.
assertTrue
(
response
.
ok
)
Test paginated response of notes api
self
.
assertEqual
(
len
(
response
.
json
()),
2
)
"""
# Without user
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
))
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
))
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
status_code
,
400
)
# Without any pagination parameters
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
),
params
=
{
"user"
:
"dummy-user-id"
})
self
.
assertTrue
(
response
.
ok
)
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
5
,
num_pages
=
3
,
notes_per_page
=
2
,
start
=
0
,
current_page
=
1
,
next_page
=
2
,
previous_page
=
None
)
# With pagination parameters
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
),
params
=
{
"user"
:
"dummy-user-id"
,
"page"
:
2
,
"page_size"
:
3
})
self
.
assertTrue
(
response
.
ok
)
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
5
,
num_pages
=
2
,
notes_per_page
=
2
,
start
=
3
,
current_page
=
2
,
next_page
=
None
,
previous_page
=
1
)
def
test_notes_collection_next_previous_with_one_page
(
self
):
"""
Test next and previous urls of paginated response of notes api
when number of pages are 1
"""
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
),
params
=
{
"user"
:
"dummy-user-id"
,
"page_size"
:
10
})
self
.
assertTrue
(
response
.
ok
)
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
5
,
num_pages
=
1
,
notes_per_page
=
5
,
start
=
0
,
current_page
=
1
,
next_page
=
None
,
previous_page
=
None
)
def
test_notes_collection_when_no_notes
(
self
):
"""
Test paginated response of notes api when there's no note present
"""
# Delete all notes
self
.
test_cleanup
()
# Get default page
response
=
requests
.
get
(
self
.
_get_url
(
"api/v1/annotations"
),
params
=
{
"user"
:
"dummy-user-id"
})
self
.
assertTrue
(
response
.
ok
)
self
.
_verify_pagination_info
(
response
=
response
.
json
(),
total_notes
=
0
,
num_pages
=
0
,
notes_per_page
=
0
,
start
=
0
,
current_page
=
1
,
next_page
=
None
,
previous_page
=
None
)
def
test_cleanup
(
self
):
def
test_cleanup
(
self
):
response
=
requests
.
put
(
self
.
_get_url
(
"cleanup"
))
response
=
requests
.
put
(
self
.
_get_url
(
"cleanup"
))
self
.
assertTrue
(
response
.
ok
)
self
.
assertTrue
(
response
.
ok
)
self
.
assertEqual
(
len
(
self
.
server
.
get_notes
()),
0
)
self
.
assertEqual
(
len
(
self
.
server
.
get_
all_
notes
()),
0
)
def
test_create_notes
(
self
):
def
test_create_notes
(
self
):
dummy_notes
=
self
.
_get_dummy_notes
(
count
=
2
)
dummy_notes
=
self
.
_get_dummy_notes
(
count
=
2
)
response
=
requests
.
post
(
self
.
_get_url
(
"create_notes"
),
data
=
json
.
dumps
(
dummy_notes
))
response
=
requests
.
post
(
self
.
_get_url
(
"create_notes"
),
data
=
json
.
dumps
(
dummy_notes
))
self
.
assertTrue
(
response
.
ok
)
self
.
assertTrue
(
response
.
ok
)
self
.
assertEqual
(
len
(
self
.
_get_notes
()),
4
)
self
.
assertEqual
(
len
(
self
.
_get_notes
()),
7
)
response
=
requests
.
post
(
self
.
_get_url
(
"create_notes"
))
response
=
requests
.
post
(
self
.
_get_url
(
"create_notes"
))
self
.
assertEqual
(
response
.
status_code
,
400
)
self
.
assertEqual
(
response
.
status_code
,
400
)
...
@@ -177,7 +333,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -177,7 +333,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
"""
"""
Return a list of notes from the stub EdxNotes service.
Return a list of notes from the stub EdxNotes service.
"""
"""
notes
=
self
.
server
.
get_notes
()
notes
=
self
.
server
.
get_
all_
notes
()
self
.
assertGreater
(
len
(
notes
),
0
,
"Notes are empty."
)
self
.
assertGreater
(
len
(
notes
),
0
,
"Notes are empty."
)
return
notes
return
notes
...
...
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