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
f71e78b6
Commit
f71e78b6
authored
Apr 22, 2014
by
jsa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add acceptance tests for user profile pagination.
JIRA: FOR-492
parent
909903eb
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
225 additions
and
4 deletions
+225
-4
common/djangoapps/terrain/stubs/comments.py
+30
-2
common/test/acceptance/fixtures/discussion.py
+16
-0
common/test/acceptance/pages/lms/discussion.py
+73
-0
common/test/acceptance/tests/test_discussion.py
+106
-2
No files found.
common/djangoapps/terrain/stubs/comments.py
View file @
f71e78b6
...
@@ -8,8 +8,14 @@ from .http import StubHttpRequestHandler, StubHttpService
...
@@ -8,8 +8,14 @@ from .http import StubHttpRequestHandler, StubHttpService
class
StubCommentsServiceHandler
(
StubHttpRequestHandler
):
class
StubCommentsServiceHandler
(
StubHttpRequestHandler
):
@property
def
_params
(
self
):
return
urlparse
.
parse_qs
(
urlparse
.
urlparse
(
self
.
path
)
.
query
)
def
do_GET
(
self
):
def
do_GET
(
self
):
pattern_handlers
=
{
pattern_handlers
=
{
"/api/v1/users/(?P<user_id>
\\
d+)/active_threads$"
:
self
.
do_user_profile
,
"/api/v1/users/(?P<user_id>
\\
d+)$"
:
self
.
do_user
,
"/api/v1/users/(?P<user_id>
\\
d+)$"
:
self
.
do_user
,
"/api/v1/threads$"
:
self
.
do_threads
,
"/api/v1/threads$"
:
self
.
do_threads
,
"/api/v1/threads/(?P<thread_id>
\\
w+)$"
:
self
.
do_thread
,
"/api/v1/threads/(?P<thread_id>
\\
w+)$"
:
self
.
do_thread
,
...
@@ -34,12 +40,34 @@ class StubCommentsServiceHandler(StubHttpRequestHandler):
...
@@ -34,12 +40,34 @@ class StubCommentsServiceHandler(StubHttpRequestHandler):
self
.
send_json_response
({})
self
.
send_json_response
({})
def
do_user
(
self
,
user_id
):
def
do_user
(
self
,
user_id
):
self
.
send_json_response
(
{
response
=
{
"id"
:
user_id
,
"id"
:
user_id
,
"upvoted_ids"
:
[],
"upvoted_ids"
:
[],
"downvoted_ids"
:
[],
"downvoted_ids"
:
[],
"subscribed_thread_ids"
:
[],
"subscribed_thread_ids"
:
[],
})
}
if
'course_id'
in
self
.
_params
:
response
.
update
({
"threads_count"
:
1
,
"comments_count"
:
2
})
self
.
send_json_response
(
response
)
def
do_user_profile
(
self
,
user_id
):
if
'active_threads'
in
self
.
server
.
config
:
user_threads
=
self
.
server
.
config
[
'active_threads'
][:]
params
=
self
.
_params
page
=
int
(
params
.
get
(
"page"
,
[
"1"
])[
0
])
per_page
=
int
(
params
.
get
(
"per_page"
,
[
"20"
])[
0
])
num_pages
=
max
(
len
(
user_threads
)
-
1
,
1
)
/
per_page
+
1
user_threads
=
user_threads
[(
page
-
1
)
*
per_page
:
page
*
per_page
]
self
.
send_json_response
({
"collection"
:
user_threads
,
"page"
:
page
,
"num_pages"
:
num_pages
})
else
:
self
.
send_response
(
404
,
content
=
"404 Not Found"
)
def
do_thread
(
self
,
thread_id
):
def
do_thread
(
self
,
thread_id
):
if
thread_id
in
self
.
server
.
config
.
get
(
'threads'
,
{}):
if
thread_id
in
self
.
server
.
config
.
get
(
'threads'
,
{}):
...
...
common/test/acceptance/fixtures/discussion.py
View file @
f71e78b6
...
@@ -87,3 +87,19 @@ class SingleThreadViewFixture(object):
...
@@ -87,3 +87,19 @@ class SingleThreadViewFixture(object):
"comments"
:
json
.
dumps
(
self
.
_get_comment_map
())
"comments"
:
json
.
dumps
(
self
.
_get_comment_map
())
}
}
)
)
class
UserProfileViewFixture
(
object
):
def
__init__
(
self
,
threads
):
self
.
threads
=
threads
def
push
(
self
):
"""
Push the data to the stub comments service.
"""
requests
.
put
(
'{}/set_config'
.
format
(
COMMENTS_STUB_URL
),
data
=
{
"active_threads"
:
json
.
dumps
(
self
.
threads
),
}
)
common/test/acceptance/pages/lms/discussion.py
View file @
f71e78b6
...
@@ -231,3 +231,76 @@ class InlineDiscussionThreadPage(DiscussionThreadPage):
...
@@ -231,3 +231,76 @@ class InlineDiscussionThreadPage(DiscussionThreadPage):
"Thread expanded"
"Thread expanded"
)
.
fulfill
()
)
.
fulfill
()
class
DiscussionUserProfilePage
(
CoursePage
):
TEXT_NEXT
=
u'Next >'
TEXT_PREV
=
u'< Previous'
PAGING_SELECTOR
=
"a.discussion-pagination[data-page-number]"
def
__init__
(
self
,
browser
,
course_id
,
user_id
,
username
,
page
=
1
):
super
(
DiscussionUserProfilePage
,
self
)
.
__init__
(
browser
,
course_id
)
self
.
url_path
=
"discussion/forum/dummy/users/{}?page={}"
.
format
(
user_id
,
page
)
self
.
username
=
username
def
is_browser_on_page
(
self
):
return
(
self
.
q
(
css
=
'section.discussion-user-threads[data-course-id="{}"]'
.
format
(
self
.
course_id
))
.
present
and
self
.
q
(
css
=
'section.user-profile div.sidebar-username'
)
.
present
and
self
.
q
(
css
=
'section.user-profile div.sidebar-username'
)
.
text
[
0
]
==
self
.
username
)
def
get_shown_thread_ids
(
self
):
elems
=
self
.
q
(
css
=
"article.discussion-thread"
)
return
[
elem
.
get_attribute
(
"id"
)[
7
:]
for
elem
in
elems
]
def
get_current_page
(
self
):
return
int
(
self
.
q
(
css
=
"nav.discussion-paginator li.current-page"
)
.
text
[
0
])
def
_check_pager
(
self
,
text
,
page_number
=
None
):
"""
returns True if 'text' matches the text in any of the pagination elements. If
page_number is provided, only return True if the element points to that result
page.
"""
elems
=
self
.
q
(
css
=
self
.
PAGING_SELECTOR
)
.
filter
(
lambda
elem
:
elem
.
text
==
text
)
if
page_number
:
elems
=
elems
.
filter
(
lambda
elem
:
int
(
elem
.
get_attribute
(
'data-page-number'
))
==
page_number
)
return
elems
.
present
def
get_clickable_pages
(
self
):
return
sorted
([
int
(
elem
.
get_attribute
(
'data-page-number'
))
for
elem
in
self
.
q
(
css
=
self
.
PAGING_SELECTOR
)
if
str
(
elem
.
text
)
.
isdigit
()
])
def
is_prev_button_shown
(
self
,
page_number
=
None
):
return
self
.
_check_pager
(
self
.
TEXT_PREV
,
page_number
)
def
is_next_button_shown
(
self
,
page_number
=
None
):
return
self
.
_check_pager
(
self
.
TEXT_NEXT
,
page_number
)
def
_click_pager_with_text
(
self
,
text
,
page_number
):
"""
click the first pagination element with whose text is `text` and ensure
the resulting page number matches `page_number`.
"""
targets
=
[
elem
for
elem
in
self
.
q
(
css
=
self
.
PAGING_SELECTOR
)
if
elem
.
text
==
text
]
targets
[
0
]
.
click
()
EmptyPromise
(
lambda
:
self
.
get_current_page
()
==
page_number
,
"navigated to desired page"
)
.
fulfill
()
def
click_prev_page
(
self
):
self
.
_click_pager_with_text
(
self
.
TEXT_PREV
,
self
.
get_current_page
()
-
1
)
def
click_next_page
(
self
):
self
.
_click_pager_with_text
(
self
.
TEXT_NEXT
,
self
.
get_current_page
()
+
1
)
def
click_on_page
(
self
,
page_number
):
self
.
_click_pager_with_text
(
unicode
(
page_number
),
page_number
)
common/test/acceptance/tests/test_discussion.py
View file @
f71e78b6
...
@@ -10,10 +10,11 @@ from ..pages.lms.courseware import CoursewarePage
...
@@ -10,10 +10,11 @@ from ..pages.lms.courseware import CoursewarePage
from
..pages.lms.discussion
import
(
from
..pages.lms.discussion
import
(
DiscussionTabSingleThreadPage
,
DiscussionTabSingleThreadPage
,
InlineDiscussionPage
,
InlineDiscussionPage
,
InlineDiscussionThreadPage
InlineDiscussionThreadPage
,
DiscussionUserProfilePage
)
)
from
..fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
..fixtures.course
import
CourseFixture
,
XBlockFixtureDesc
from
..fixtures.discussion
import
SingleThreadViewFixture
,
Thread
,
Response
,
Comment
from
..fixtures.discussion
import
SingleThreadViewFixture
,
UserProfileViewFixture
,
Thread
,
Response
,
Comment
class
DiscussionResponsePaginationTestMixin
(
object
):
class
DiscussionResponsePaginationTestMixin
(
object
):
...
@@ -301,3 +302,106 @@ class InlineDiscussionTest(UniqueCourseTest, DiscussionResponsePaginationTestMix
...
@@ -301,3 +302,106 @@ class InlineDiscussionTest(UniqueCourseTest, DiscussionResponsePaginationTestMix
def
test_expand_discussion_empty
(
self
):
def
test_expand_discussion_empty
(
self
):
self
.
discussion_page
.
expand_discussion
()
self
.
discussion_page
.
expand_discussion
()
self
.
assertEqual
(
self
.
discussion_page
.
get_num_displayed_threads
(),
0
)
self
.
assertEqual
(
self
.
discussion_page
.
get_num_displayed_threads
(),
0
)
class
DiscussionUserProfileTest
(
UniqueCourseTest
):
"""
Tests for user profile page in discussion tab.
"""
PAGE_SIZE
=
20
# django_comment_client.forum.views.THREADS_PER_PAGE
PROFILED_USERNAME
=
"profiled-user"
def
setUp
(
self
):
super
(
DiscussionUserProfileTest
,
self
)
.
setUp
()
CourseFixture
(
**
self
.
course_info
)
.
install
()
# The following line creates a user enrolled in our course, whose
# threads will be viewed, but not the one who will view the page.
# It isn't necessary to log them in, but using the AutoAuthPage
# saves a lot of code.
self
.
profiled_user_id
=
AutoAuthPage
(
self
.
browser
,
username
=
self
.
PROFILED_USERNAME
,
course_id
=
self
.
course_id
)
.
visit
()
.
get_user_id
()
# now create a second user who will view the profile.
self
.
user_id
=
AutoAuthPage
(
self
.
browser
,
course_id
=
self
.
course_id
)
.
visit
()
.
get_user_id
()
def
check_pages
(
self
,
num_threads
):
# set up the stub server to return the desired amount of thread results
threads
=
[
Thread
(
id
=
uuid4
()
.
hex
)
for
_
in
range
(
num_threads
)]
UserProfileViewFixture
(
threads
)
.
push
()
# navigate to default view (page 1)
page
=
DiscussionUserProfilePage
(
self
.
browser
,
self
.
course_id
,
self
.
profiled_user_id
,
self
.
PROFILED_USERNAME
)
page
.
visit
()
current_page
=
1
total_pages
=
max
(
num_threads
-
1
,
1
)
/
self
.
PAGE_SIZE
+
1
all_pages
=
range
(
1
,
total_pages
+
1
)
def
_check_page
():
# ensure the page being displayed as "current" is the expected one
self
.
assertEqual
(
page
.
get_current_page
(),
current_page
)
# ensure the expected threads are being shown in the right order
threads_expected
=
threads
[(
current_page
-
1
)
*
self
.
PAGE_SIZE
:
current_page
*
self
.
PAGE_SIZE
]
self
.
assertEqual
(
page
.
get_shown_thread_ids
(),
[
t
[
"id"
]
for
t
in
threads_expected
])
# ensure the clickable page numbers are the expected ones
self
.
assertEqual
(
page
.
get_clickable_pages
(),
[
p
for
p
in
all_pages
if
p
!=
current_page
and
p
-
2
<=
current_page
<=
p
+
2
or
(
current_page
>
2
and
p
==
1
)
or
(
current_page
<
total_pages
and
p
==
total_pages
)
])
# ensure the previous button is shown, but only if it should be.
# when it is shown, make sure it works.
if
current_page
>
1
:
self
.
assertTrue
(
page
.
is_prev_button_shown
(
current_page
-
1
))
page
.
click_prev_page
()
self
.
assertEqual
(
page
.
get_current_page
(),
current_page
-
1
)
page
.
click_next_page
()
self
.
assertEqual
(
page
.
get_current_page
(),
current_page
)
else
:
self
.
assertFalse
(
page
.
is_prev_button_shown
())
# ensure the next button is shown, but only if it should be.
if
current_page
<
total_pages
:
self
.
assertTrue
(
page
.
is_next_button_shown
(
current_page
+
1
))
else
:
self
.
assertFalse
(
page
.
is_next_button_shown
())
# click all the way up through each page
for
i
in
range
(
current_page
,
total_pages
):
_check_page
()
if
current_page
<
total_pages
:
page
.
click_on_page
(
current_page
+
1
)
current_page
+=
1
# click all the way back down
for
i
in
range
(
current_page
,
0
,
-
1
):
_check_page
()
if
current_page
>
1
:
page
.
click_on_page
(
current_page
-
1
)
current_page
-=
1
def
test_0_threads
(
self
):
self
.
check_pages
(
0
)
def
test_1_thread
(
self
):
self
.
check_pages
(
1
)
def
test_20_threads
(
self
):
self
.
check_pages
(
20
)
def
test_21_threads
(
self
):
self
.
check_pages
(
21
)
def
test_151_threads
(
self
):
self
.
check_pages
(
151
)
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