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
71cc602d
Commit
71cc602d
authored
Nov 10, 2016
by
Muhammad Ammar
Committed by
GitHub
Nov 10, 2016
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #13863 from edx/ammar/tnl-4163-reduce-annotatorjs-search-calls
Single search request to fetch notes per unit
parents
3224c027
237ef00a
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
289 additions
and
73 deletions
+289
-73
common/djangoapps/terrain/stubs/edxnotes.py
+18
-6
common/djangoapps/terrain/stubs/tests/test_edxnotes.py
+27
-5
lms/static/js/edxnotes/plugins/search_override.js
+13
-0
lms/static/js/edxnotes/utils/notes_collector.js
+113
-0
lms/static/js/edxnotes/views/notes_factory.js
+9
-3
lms/static/js/spec/edxnotes/plugins/store_error_handler_spec.js
+16
-11
lms/static/js/spec/edxnotes/utils/notes_collector_spec.js
+42
-0
lms/static/js/spec/edxnotes/views/notes_factory_spec.js
+21
-15
lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js
+29
-33
lms/static/lms/js/spec/main.js
+1
-0
No files found.
common/djangoapps/terrain/stubs/edxnotes.py
View file @
71cc602d
...
@@ -243,8 +243,9 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
...
@@ -243,8 +243,9 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
"""
"""
Search for a notes by user id, course_id and usage_id.
Search for a notes by user id, course_id and usage_id.
"""
"""
search_with_usage_id
=
False
user
=
self
.
get_params
.
get
(
"user"
,
None
)
user
=
self
.
get_params
.
get
(
"user"
,
None
)
usage_id
=
self
.
get_params
.
get
(
"usage_id"
,
None
)
usage_id
s
=
self
.
get_params
.
get
(
"usage_id"
,
[]
)
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
=
int
(
self
.
get_params
.
get
(
"page"
,
1
))
...
@@ -257,11 +258,14 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
...
@@ -257,11 +258,14 @@ class StubEdxNotesServiceHandler(StubHttpRequestHandler):
notes
=
self
.
server
.
get_all_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
len
(
usage_ids
)
>
0
:
notes
=
self
.
server
.
filter_by_usage_id
(
notes
,
usage_id
)
search_with_usage_id
=
True
notes
=
self
.
server
.
filter_by_usage_id
(
notes
,
usage_ids
)
if
text
:
if
text
:
notes
=
self
.
server
.
search
(
notes
,
text
)
notes
=
self
.
server
.
search
(
notes
,
text
)
self
.
respond
(
content
=
self
.
_get_paginated_response
(
notes
,
page
,
page_size
))
if
not
search_with_usage_id
:
notes
=
self
.
_get_paginated_response
(
notes
,
page
,
page_size
)
self
.
respond
(
content
=
notes
)
def
_collection
(
self
):
def
_collection
(
self
):
"""
"""
...
@@ -356,11 +360,13 @@ class StubEdxNotesService(StubHttpService):
...
@@ -356,11 +360,13 @@ class StubEdxNotesService(StubHttpService):
"""
"""
return
self
.
filter_by
(
data
,
"user"
,
user
)
return
self
.
filter_by
(
data
,
"user"
,
user
)
def
filter_by_usage_id
(
self
,
data
,
usage_id
):
def
filter_by_usage_id
(
self
,
data
,
usage_id
s
):
"""
"""
Filters provided `data(list)` by the `usage_id(str)`.
Filters provided `data(list)` by the `usage_id(str)`.
"""
"""
return
self
.
filter_by
(
data
,
"usage_id"
,
usage_id
)
if
not
isinstance
(
usage_ids
,
list
):
usage_ids
=
[
usage_ids
]
return
self
.
filter_by_list
(
data
,
"usage_id"
,
usage_ids
)
def
filter_by_course_id
(
self
,
data
,
course_id
):
def
filter_by_course_id
(
self
,
data
,
course_id
):
"""
"""
...
@@ -374,6 +380,12 @@ class StubEdxNotesService(StubHttpService):
...
@@ -374,6 +380,12 @@ class StubEdxNotesService(StubHttpService):
"""
"""
return
[
note
for
note
in
data
if
note
.
get
(
field_name
)
==
value
]
return
[
note
for
note
in
data
if
note
.
get
(
field_name
)
==
value
]
def
filter_by_list
(
self
,
data
,
field_name
,
values
):
"""
Filters provided `data(list)` by the `field_name(str)` in values.
"""
return
[
note
for
note
in
data
if
note
.
get
(
field_name
)
in
values
]
def
search
(
self
,
data
,
query
):
def
search
(
self
,
data
,
query
):
"""
"""
Search the `query(str)` text in the provided `data(list)`.
Search the `query(str)` text in the provided `data(list)`.
...
...
common/djangoapps/terrain/stubs/tests/test_edxnotes.py
View file @
71cc602d
"""
"""
Unit tests for stub EdxNotes implementation.
Unit tests for stub EdxNotes implementation.
"""
"""
import
ddt
import
urlparse
import
urlparse
import
json
import
json
import
unittest
import
unittest
...
@@ -9,6 +10,7 @@ from uuid import uuid4
...
@@ -9,6 +10,7 @@ from uuid import uuid4
from
..edxnotes
import
StubEdxNotesService
from
..edxnotes
import
StubEdxNotesService
@ddt.ddt
class
StubEdxNotesServiceTest
(
unittest
.
TestCase
):
class
StubEdxNotesServiceTest
(
unittest
.
TestCase
):
"""
"""
Test cases for the stub EdxNotes service.
Test cases for the stub EdxNotes service.
...
@@ -27,9 +29,9 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -27,9 +29,9 @@ class StubEdxNotesServiceTest(unittest.TestCase):
"""
"""
Returns a list of dummy notes.
Returns a list of dummy notes.
"""
"""
return
[
self
.
_get_dummy_note
()
for
i
in
xrange
(
count
)]
# pylint: disable=unused-variable
return
[
self
.
_get_dummy_note
(
i
)
for
i
in
xrange
(
count
)]
# pylint: disable=unused-variable
def
_get_dummy_note
(
self
):
def
_get_dummy_note
(
self
,
uid
=
0
):
"""
"""
Returns a single dummy note.
Returns a single dummy note.
"""
"""
...
@@ -39,7 +41,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -39,7 +41,7 @@ class StubEdxNotesServiceTest(unittest.TestCase):
"created"
:
"2014-10-31T10:05:00.000000"
,
"created"
:
"2014-10-31T10:05:00.000000"
,
"updated"
:
"2014-10-31T10:50:00.101010"
,
"updated"
:
"2014-10-31T10:50:00.101010"
,
"user"
:
"dummy-user-id"
,
"user"
:
"dummy-user-id"
,
"usage_id"
:
"dummy-usage-id
"
,
"usage_id"
:
"dummy-usage-id
-"
+
str
(
uid
)
,
"course_id"
:
"dummy-course-id"
,
"course_id"
:
"dummy-course-id"
,
"text"
:
"dummy note text "
+
nid
,
"text"
:
"dummy note text "
+
nid
,
"quote"
:
"dummy note quote"
,
"quote"
:
"dummy note quote"
,
...
@@ -106,7 +108,6 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -106,7 +108,6 @@ class StubEdxNotesServiceTest(unittest.TestCase):
# get response with default page and page size
# 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"
,
"course_id"
:
"dummy-course-id"
,
"course_id"
:
"dummy-course-id"
,
})
})
...
@@ -125,7 +126,6 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -125,7 +126,6 @@ class StubEdxNotesServiceTest(unittest.TestCase):
# search notes with text that don't exist
# search notes with text that don't exist
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"
,
"course_id"
:
"dummy-course-id"
,
"course_id"
:
"dummy-course-id"
,
"text"
:
"world war 2"
"text"
:
"world war 2"
})
})
...
@@ -142,6 +142,28 @@ class StubEdxNotesServiceTest(unittest.TestCase):
...
@@ -142,6 +142,28 @@ class StubEdxNotesServiceTest(unittest.TestCase):
previous_page
=
None
previous_page
=
None
)
)
@ddt.data
(
'?usage_id=dummy-usage-id-0'
,
'?usage_id=dummy-usage-id-0&usage_id=dummy-usage-id-1&dummy-usage-id-2&dummy-usage-id-3&dummy-usage-id-4'
)
def
test_search_usage_ids
(
self
,
usage_ids
):
"""
Test search with usage ids.
"""
url
=
self
.
_get_url
(
'api/v1/search'
)
+
usage_ids
response
=
requests
.
get
(
url
,
params
=
{
'user'
:
'dummy-user-id'
,
'course_id'
:
'dummy-course-id'
})
self
.
assertTrue
(
response
.
ok
)
response
=
response
.
json
()
parsed
=
urlparse
.
urlparse
(
url
)
query_params
=
urlparse
.
parse_qs
(
parsed
.
query
)
query_params
[
'usage_id'
]
.
reverse
()
self
.
assertEqual
(
len
(
response
),
len
(
query_params
[
'usage_id'
]))
for
index
,
usage_id
in
enumerate
(
query_params
[
'usage_id'
]):
self
.
assertEqual
(
response
[
index
][
'usage_id'
],
usage_id
)
def
test_delete
(
self
):
def
test_delete
(
self
):
notes
=
self
.
_get_notes
()
notes
=
self
.
_get_notes
()
response
=
requests
.
delete
(
self
.
_get_url
(
"api/v1/annotations/does_not_exist"
))
response
=
requests
.
delete
(
self
.
_get_url
(
"api/v1/annotations/does_not_exist"
))
...
...
lms/static/js/edxnotes/plugins/search_override.js
0 → 100644
View file @
71cc602d
(
function
(
define
)
{
'use strict'
;
define
([
'annotator_1.2.9'
],
function
(
Annotator
)
{
//
// Override Annotator.Plugin.Store.prototype._getAnnotations. We don't want AnnotatorJS to search notes.
//
// eslint-disable-next-line no-param-reassign, no-underscore-dangle
Annotator
.
Plugin
.
Store
.
prototype
.
_getAnnotations
=
function
()
{
// Do Nothing
};
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
lms/static/js/edxnotes/utils/notes_collector.js
0 → 100644
View file @
71cc602d
(
function
(
define
)
{
'use strict'
;
define
([
'jquery'
,
'underscore'
,
'annotator_1.2.9'
],
function
(
$
,
_
,
Annotator
)
{
var
cleanup
,
renderNotes
,
fetchNotesWhenReady
,
storeNotesRequestData
,
searchRequestsData
=
[];
/**
* Clears the searchRequestsData.
*/
cleanup
=
function
()
{
searchRequestsData
=
[];
};
/**
* Store requests data for each annotatable component and fetch
* notes for them when request for each component is stored.
*
* @param {object} data Request data for each annotatable component
* @param {Number} totalNotesWrappers Total number of edx notes wrappers present
*/
storeNotesRequestData
=
function
(
data
,
totalNotesWrappers
)
{
searchRequestsData
.
push
(
data
);
fetchNotesWhenReady
(
totalNotesWrappers
);
};
/**
* Fetch notes for annotatable components only when desired
* number of requests are stored.
*
* @param {Number} totalNotesWrappers Total number of edx notes wrappers present
*/
fetchNotesWhenReady
=
function
(
totalNotesWrappers
)
{
var
settings
,
usageIds
,
searchEndpoint
;
if
(
totalNotesWrappers
!==
searchRequestsData
.
length
)
{
return
;
}
// `user` and `course_id` values are same for every annotatable
// component so we pick these from first `searchRequestsData` item
settings
=
{
data
:
{
user
:
searchRequestsData
[
0
].
params
.
user
,
course_id
:
searchRequestsData
[
0
].
params
.
courseId
},
type
:
'GET'
,
dataType
:
'json'
,
headers
:
{
'x-annotator-auth-token'
:
searchRequestsData
[
0
].
params
.
token
}
};
searchEndpoint
=
searchRequestsData
[
0
].
params
.
endpoint
+
'search/?'
;
usageIds
=
_
.
map
(
searchRequestsData
,
function
(
item
)
{
return
'usage_id='
+
encodeURIComponent
(
item
.
params
.
usageId
);
});
// Search endpoint expects the below format for query params
// /api/v1/search/?course_id={course_id}&user={user_id}&usage_id={usage_id}&usage_id={usage_id} ...
searchEndpoint
+=
usageIds
.
join
(
'&'
);
$
.
ajax
(
searchEndpoint
,
settings
)
.
done
(
function
(
jqXHR
)
{
renderNotes
(
jqXHR
);
})
.
fail
(
function
(
jqXHR
)
{
// `_action` is used by AnnotatorJS to construct error message
jqXHR
.
_action
=
'search'
;
// eslint-disable-line no-underscore-dangle, no-param-reassign
Annotator
.
Plugin
.
Store
.
prototype
.
_onError
(
jqXHR
);
// eslint-disable-line no-underscore-dangle
})
.
always
(
function
()
{
cleanup
();
});
};
/**
* Pass notes to AnnotatorJS for rendering
*
* @param {Array} notes Notes data received from server
*/
renderNotes
=
function
(
notes
)
{
var
edxNotes
=
{};
// AnnotatorJS expects notes to be present in an array named as `rows`
_
.
each
(
searchRequestsData
,
function
(
item
)
{
edxNotes
[
item
.
params
.
usageId
]
=
{
rows
:
[]};
});
// Place the received notes in the format below
// edxNotes = {
// 'usage_id1': [noteObject, noteObject, noteObject],
// 'usage_id2': [noteObject, noteObject]
// }
_
.
each
(
notes
,
function
(
note
)
{
edxNotes
[
note
.
usage_id
].
rows
.
push
(
note
);
});
// Render the notes for each annotatable component using its associated AnnotatorJS instance
_
.
each
(
searchRequestsData
,
function
(
item
)
{
item
.
annotator
.
plugins
.
Store
.
_onLoadAnnotationsFromSearch
(
// eslint-disable-line no-underscore-dangle
edxNotes
[
item
.
params
.
usageId
]
);
});
};
return
{
storeNotesRequestData
:
storeNotesRequestData
,
cleanup
:
cleanup
};
});
}).
call
(
this
,
define
||
RequireJS
.
define
);
lms/static/js/edxnotes/views/notes_factory.js
View file @
71cc602d
(
function
(
define
,
undefined
)
{
(
function
(
define
,
undefined
)
{
'use strict'
;
'use strict'
;
define
([
define
([
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'js/edxnotes/utils/logger'
,
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'js/edxnotes/utils/logger'
,
'js/edxnotes/utils/notes_collector'
,
'js/edxnotes/views/shim'
,
'js/edxnotes/plugins/scroller'
,
'js/edxnotes/views/shim'
,
'js/edxnotes/plugins/scroller'
,
'js/edxnotes/plugins/events'
,
'js/edxnotes/plugins/accessibility'
,
'js/edxnotes/plugins/events'
,
'js/edxnotes/plugins/accessibility'
,
'js/edxnotes/plugins/caret_navigation'
,
'js/edxnotes/plugins/caret_navigation'
,
'js/edxnotes/plugins/store_error_handler'
'js/edxnotes/plugins/store_error_handler'
,
],
function
(
$
,
_
,
Annotator
,
NotesLogger
)
{
'js/edxnotes/plugins/search_override'
],
function
(
$
,
_
,
Annotator
,
NotesLogger
,
NotesCollector
)
{
var
plugins
=
[
'Auth'
,
'Store'
,
'Scroller'
,
'Events'
,
'Accessibility'
,
'CaretNavigation'
,
'Tags'
],
var
plugins
=
[
'Auth'
,
'Store'
,
'Scroller'
,
'Events'
,
'Accessibility'
,
'CaretNavigation'
,
'Tags'
],
getOptions
,
setupPlugins
,
getAnnotator
;
getOptions
,
setupPlugins
,
getAnnotator
;
...
@@ -84,6 +86,10 @@
...
@@ -84,6 +86,10 @@
annotator
=
el
.
annotator
(
options
).
data
(
'annotator'
);
annotator
=
el
.
annotator
(
options
).
data
(
'annotator'
);
setupPlugins
(
annotator
,
plugins
,
options
);
setupPlugins
(
annotator
,
plugins
,
options
);
NotesCollector
.
storeNotesRequestData
(
{
annotator
:
annotator
,
params
:
params
},
$
(
'.edx-notes-wrapper'
).
length
);
annotator
.
logger
=
logger
;
annotator
.
logger
=
logger
;
logger
.
log
({
'element'
:
element
,
'options'
:
options
});
logger
.
log
({
'element'
:
element
,
'options'
:
options
});
return
annotator
;
return
annotator
;
...
...
lms/static/js/spec/edxnotes/plugins/store_error_handler_spec.js
View file @
71cc602d
...
@@ -2,30 +2,35 @@ define([
...
@@ -2,30 +2,35 @@ define([
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'js/spec/edxnotes/helpers'
,
'js/spec/edxnotes/helpers'
,
'js/edxnotes/views/notes_factory'
'js/edxnotes/views/notes_factory'
,
],
function
(
$
,
_
,
Annotator
,
AjaxHelpers
,
Helpers
,
NotesFactory
)
{
'js/edxnotes/utils/notes_collector'
],
function
(
$
,
_
,
Annotator
,
AjaxHelpers
,
Helpers
,
NotesFactory
,
NotesCollector
)
{
'use strict'
;
'use strict'
;
describe
(
'Store Error Handler Custom Message'
,
function
()
{
describe
(
'Store Error Handler Custom Message'
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
spyOn
(
Annotator
,
'showNotification'
);
spyOn
(
Annotator
,
'showNotification'
);
loadFixtures
(
'js/fixtures/edxnotes/edxnotes_wrapper.html'
);
loadFixtures
(
'js/fixtures/edxnotes/edxnotes_wrapper.html'
);
this
.
wrapper
=
document
.
getElementById
(
'edx-notes-wrapper-123'
);
NotesCollector
.
cleanup
(
);
});
});
afterEach
(
function
()
{
afterEach
(
function
()
{
_
.
invoke
(
Annotator
.
_instances
,
'destroy'
);
while
(
Annotator
.
_instances
.
length
>
0
)
{
// eslint-disable-line no-underscore-dangle
Annotator
.
_instances
[
0
].
destroy
();
// eslint-disable-line no-underscore-dangle
}
});
});
it
(
'can handle custom error if sent from server'
,
function
()
{
it
(
'can handle custom error if sent from server'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
token
=
Helpers
.
makeToken
();
var
token
=
Helpers
.
makeToken
();
NotesFactory
.
factory
(
this
.
wrapper
,
{
_
.
each
(
$
(
'.edx-notes-wrapper'
),
function
(
wrapper
)
{
endpoint
:
'/test_endpoint'
,
NotesFactory
.
factory
(
wrapper
,
{
user
:
'a user'
,
endpoint
:
'/test_endpoint'
,
usageId
:
'an usage'
,
user
:
'a user'
,
courseId
:
'a course'
,
usageId
:
'an usage'
,
token
:
token
,
courseId
:
'a course'
,
tokenUrl
:
'/test_token_url'
token
:
token
,
tokenUrl
:
'/test_token_url'
});
});
});
var
errorMsg
=
'can
\'
t create more notes'
;
var
errorMsg
=
'can
\'
t create more notes'
;
...
...
lms/static/js/spec/edxnotes/utils/notes_collector_spec.js
0 → 100644
View file @
71cc602d
define
([
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'js/edxnotes/views/notes_factory'
,
'js/edxnotes/utils/notes_collector'
,
'js/spec/edxnotes/helpers'
],
function
(
$
,
_
,
Annotator
,
AjaxHelpers
,
NotesFactory
,
NotesCollector
,
Helpers
)
{
'use strict'
;
describe
(
'EdxNotes NotesCollector'
,
function
()
{
beforeEach
(
function
()
{
loadFixtures
(
'js/fixtures/edxnotes/edxnotes_wrapper.html'
);
NotesCollector
.
cleanup
();
});
afterEach
(
function
()
{
while
(
Annotator
.
_instances
.
length
>
0
)
{
// eslint-disable-line no-underscore-dangle
Annotator
.
_instances
[
0
].
destroy
();
// eslint-disable-line no-underscore-dangle
}
NotesCollector
.
cleanup
();
});
it
(
'sends single search request to fetch notes for all HTML components'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
token
=
Helpers
.
makeToken
();
_
.
each
(
$
(
'.edx-notes-wrapper'
),
function
(
wrapper
,
index
)
{
NotesFactory
.
factory
(
wrapper
,
{
endpoint
:
'/test_endpoint/'
,
user
:
'a user'
,
usageId
:
'usage '
+
index
,
courseId
:
'a course'
,
token
:
token
,
tokenUrl
:
'/test_token_url'
});
});
expect
(
requests
.
length
).
toBe
(
1
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/test_endpoint/search/?usage_id=usage%200&usage_id=usage%201&user=a+user&course_id=a+course'
);
});
});
});
lms/static/js/spec/edxnotes/views/notes_factory_spec.js
View file @
71cc602d
define
([
define
([
'
annotator_1.2.9'
,
'js/edxnotes/views/notes_factory'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers
'
,
'
jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'js/edxnotes/views/notes_factory
'
,
'js/spec/edxnotes/helpers'
'
edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'js/edxnotes/utils/notes_collector'
,
'
js/spec/edxnotes/helpers'
],
function
(
Annotator
,
NotesFactory
,
AjaxHelpers
,
Helpers
)
{
],
function
(
$
,
_
,
Annotator
,
NotesFactory
,
AjaxHelpers
,
NotesCollector
,
Helpers
)
{
'use strict'
;
'use strict'
;
describe
(
'EdxNotes NotesFactory'
,
function
()
{
describe
(
'EdxNotes NotesFactory'
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
loadFixtures
(
'js/fixtures/edxnotes/edxnotes_wrapper.html'
);
loadFixtures
(
'js/fixtures/edxnotes/edxnotes_wrapper.html'
);
this
.
wrapper
=
document
.
getElementById
(
'edx-notes-wrapper-123'
);
NotesCollector
.
cleanup
(
);
});
});
afterEach
(
function
()
{
afterEach
(
function
()
{
...
@@ -15,30 +15,36 @@ define([
...
@@ -15,30 +15,36 @@ define([
}
}
});
});
it
(
'can initialize annotator correctly'
,
function
()
{
it
(
'can initialize annotator correctly'
,
function
(
done
)
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
var
requests
=
AjaxHelpers
.
requests
(
this
),
token
=
Helpers
.
makeToken
(),
token
=
Helpers
.
makeToken
(),
options
=
{
options
=
{
user
:
'a user'
,
user
:
'a user'
,
usage_id
:
'an usage'
,
usage_id
:
'an usage'
,
course_id
:
'a course'
course_id
:
'a course'
},
};
annotator
=
NotesFactory
.
factory
(
this
.
wrapper
,
{
_
.
each
(
$
(
'.edx-notes-wrapper'
),
function
(
wrapper
)
{
var
annotator
=
NotesFactory
.
factory
(
wrapper
,
{
endpoint
:
'/test_endpoint'
,
endpoint
:
'/test_endpoint'
,
user
:
'a user'
,
user
:
'a user'
,
usageId
:
'an usage'
,
usageId
:
'an usage'
,
courseId
:
'a course'
,
courseId
:
'a course'
,
token
:
token
,
token
:
token
,
tokenUrl
:
'/test_token_url'
tokenUrl
:
'/test_token_url'
}),
});
request
=
requests
[
0
];
expect
(
requests
).
toHaveLength
(
1
);
expect
(
annotator
.
options
.
auth
.
tokenUrl
).
toBe
(
'/test_token_url'
);
expect
(
request
.
requestHeaders
[
'x-annotator-auth-token'
]).
toBe
(
token
);
expect
(
annotator
.
options
.
store
.
prefix
).
toBe
(
'/test_endpoint'
);
expect
(
annotator
.
options
.
auth
.
tokenUrl
).
toBe
(
'/test_token_url'
);
expect
(
annotator
.
options
.
store
.
annotationData
).
toEqual
(
options
);
expect
(
annotator
.
options
.
store
.
prefix
).
toBe
(
'/test_endpoint'
);
expect
(
annotator
.
options
.
store
.
loadFromSearch
).
toEqual
(
options
);
expect
(
annotator
.
options
.
store
.
annotationData
).
toEqual
(
options
);
});
expect
(
annotator
.
options
.
store
.
loadFromSearch
).
toEqual
(
options
);
jasmine
.
waitUntil
(
function
()
{
return
requests
.
length
===
1
;
}).
done
(
function
()
{
expect
(
requests
[
0
].
requestHeaders
[
'x-annotator-auth-token'
]).
toBe
(
token
);
done
();
});
});
});
});
});
});
});
lms/static/js/spec/edxnotes/views/notes_visibility_factory_spec.js
View file @
71cc602d
define
([
define
([
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'jquery'
,
'underscore'
,
'annotator_1.2.9'
,
'edx-ui-toolkit/js/utils/spec-helpers/ajax-helpers'
,
'js/edxnotes/views/notes_visibility_factory'
,
'js/spec/edxnotes/helpers'
'js/edxnotes/views/notes_visibility_factory'
,
'js/
edxnotes/utils/notes_collector'
,
'js/
spec/edxnotes/helpers'
],
function
(
],
function
(
$
,
_
,
Annotator
,
AjaxHelpers
,
NotesVisibilityFactory
,
Helpers
$
,
_
,
Annotator
,
AjaxHelpers
,
NotesVisibilityFactory
,
NotesCollector
,
Helpers
)
{
)
{
'use strict'
;
'use strict'
;
describe
(
'EdxNotes ToggleNotesFactory'
,
function
()
{
describe
(
'EdxNotes ToggleNotesFactory'
,
function
()
{
var
params
=
{
var
params
=
{
endpoint
:
'/test_endpoint'
,
endpoint
:
'/test_endpoint
/
'
,
user
:
'
a user
'
,
user
:
'
user12345
'
,
usageId
:
'
an usage
'
,
usageId
:
'
usageid777
'
,
courseId
:
'
a course
'
,
courseId
:
'
courseid000
'
,
token
:
Helpers
.
makeToken
(),
token
:
Helpers
.
makeToken
(),
tokenUrl
:
'/test_token_url'
tokenUrl
:
'/test_token_url'
};
};
...
@@ -27,10 +27,11 @@ define([
...
@@ -27,10 +27,11 @@ define([
document
.
getElementById
(
'edx-notes-wrapper-456'
),
params
,
true
document
.
getElementById
(
'edx-notes-wrapper-456'
),
params
,
true
);
);
this
.
toggleNotes
=
NotesVisibilityFactory
.
ToggleVisibilityView
(
true
,
'/test_url'
);
this
.
toggleNotes
=
NotesVisibilityFactory
.
ToggleVisibilityView
(
true
,
'/test_url'
);
this
.
b
utton
=
$
(
'.action-toggle-notes'
);
this
.
toggleVisibilityB
utton
=
$
(
'.action-toggle-notes'
);
this
.
label
=
this
.
b
utton
.
find
(
'.utility-control-label'
);
this
.
label
=
this
.
toggleVisibilityB
utton
.
find
(
'.utility-control-label'
);
this
.
toggleMessage
=
$
(
'.action-toggle-message'
);
this
.
toggleMessage
=
$
(
'.action-toggle-message'
);
spyOn
(
this
.
toggleNotes
,
'toggleHandler'
).
and
.
callThrough
();
spyOn
(
this
.
toggleNotes
,
'toggleHandler'
).
and
.
callThrough
();
NotesCollector
.
cleanup
();
});
});
afterEach
(
function
()
{
afterEach
(
function
()
{
...
@@ -39,49 +40,45 @@ define([
...
@@ -39,49 +40,45 @@ define([
Annotator
.
_instances
[
0
].
destroy
();
Annotator
.
_instances
[
0
].
destroy
();
}
}
$
(
'.annotator-notice'
).
remove
();
$
(
'.annotator-notice'
).
remove
();
NotesCollector
.
cleanup
();
});
});
it
(
'can toggle notes'
,
function
()
{
it
(
'can toggle notes'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
);
var
requests
=
AjaxHelpers
.
requests
(
this
);
expect
(
this
.
b
utton
).
not
.
toHaveClass
(
'is-disabled'
);
expect
(
this
.
toggleVisibilityB
utton
).
not
.
toHaveClass
(
'is-disabled'
);
expect
(
this
.
label
).
toContainText
(
'Hide notes'
);
expect
(
this
.
label
).
toContainText
(
'Hide notes'
);
expect
(
this
.
b
utton
).
toHaveClass
(
'is-active'
);
expect
(
this
.
toggleVisibilityB
utton
).
toHaveClass
(
'is-active'
);
expect
(
this
.
b
utton
).
toHaveAttr
(
'aria-pressed'
,
'true'
);
expect
(
this
.
toggleVisibilityB
utton
).
toHaveAttr
(
'aria-pressed'
,
'true'
);
expect
(
this
.
toggleMessage
).
not
.
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
not
.
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes visible'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes visible'
);
this
.
b
utton
.
click
();
this
.
toggleVisibilityB
utton
.
click
();
expect
(
this
.
label
).
toContainText
(
'Show notes'
);
expect
(
this
.
label
).
toContainText
(
'Show notes'
);
expect
(
this
.
b
utton
).
not
.
toHaveClass
(
'is-active'
);
expect
(
this
.
toggleVisibilityB
utton
).
not
.
toHaveClass
(
'is-active'
);
expect
(
this
.
toggleMessage
).
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes hidden'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes hidden'
);
expect
(
Annotator
.
_instances
).
toHaveLength
(
0
);
expect
(
Annotator
.
_instances
).
toHaveLength
(
0
);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/test_url'
,
{
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/test_url'
,
{
'visibility'
:
false
visibility
:
false
});
});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
this
.
b
utton
.
click
();
this
.
toggleVisibilityB
utton
.
click
();
expect
(
this
.
label
).
toContainText
(
'Hide notes'
);
expect
(
this
.
label
).
toContainText
(
'Hide notes'
);
expect
(
this
.
b
utton
).
toHaveClass
(
'is-active'
);
expect
(
this
.
toggleVisibilityB
utton
).
toHaveClass
(
'is-active'
);
expect
(
this
.
toggleMessage
).
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
toHaveClass
(
'is-fleeting'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes visible'
);
expect
(
this
.
toggleMessage
).
toContainText
(
'Notes visible'
);
expect
(
Annotator
.
_instances
).
toHaveLength
(
2
);
expect
(
Annotator
.
_instances
).
toHaveLength
(
2
);
// TODO: why is the same search request made twice?
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/test_endpoint/search/?us
er=a+user&usage_id=an+usage&course_id=a+course
'
'/test_endpoint/search/?us
age_id=usageid777&usage_id=usageid777&user=user12345&course_id=courseid000
'
);
);
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
[]);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/test_url'
,
{
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/test_url'
,
{
'visibility'
:
true
visibility
:
true
});
});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
});
});
...
@@ -90,7 +87,7 @@ define([
...
@@ -90,7 +87,7 @@ define([
var
requests
=
AjaxHelpers
.
requests
(
this
),
var
requests
=
AjaxHelpers
.
requests
(
this
),
$errorContainer
=
$
(
'.annotator-notice'
);
$errorContainer
=
$
(
'.annotator-notice'
);
this
.
b
utton
.
click
();
this
.
toggleVisibilityB
utton
.
click
();
AjaxHelpers
.
respondWithError
(
requests
);
AjaxHelpers
.
respondWithError
(
requests
);
expect
(
$errorContainer
).
toContainText
(
expect
(
$errorContainer
).
toContainText
(
'An error has occurred. Make sure that you are connected to the Internet, '
+
'An error has occurred. Make sure that you are connected to the Internet, '
+
...
@@ -100,19 +97,18 @@ define([
...
@@ -100,19 +97,18 @@ define([
expect
(
$errorContainer
).
toHaveClass
(
'annotator-notice-show'
);
expect
(
$errorContainer
).
toHaveClass
(
'annotator-notice-show'
);
expect
(
$errorContainer
).
toHaveClass
(
'annotator-notice-error'
);
expect
(
$errorContainer
).
toHaveClass
(
'annotator-notice-error'
);
this
.
b
utton
.
click
();
this
.
toggleVisibilityB
utton
.
click
();
// TODO: why is the same search request made twice?
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/test_endpoint/search/?us
er=a+user&usage_id=an+usage&course_id=a+course
'
'/test_endpoint/search/?us
age_id=usageid777&usage_id=usageid777&user=user12345&course_id=courseid000
'
);
);
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
[]);
AjaxHelpers
.
expectJsonRequest
(
requests
,
'GET'
,
'/test_endpoint/search/?user=a+user&usage_id=an+usage&course_id=a+course'
);
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
expectJsonRequest
(
requests
,
'PUT'
,
'/test_url'
,
{
visibility
:
true
});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
AjaxHelpers
.
respondWithJson
(
requests
,
{});
expect
(
$errorContainer
).
not
.
toHaveClass
(
'annotator-notice-show'
);
expect
(
$errorContainer
).
not
.
toHaveClass
(
'annotator-notice-show'
);
});
});
...
...
lms/static/lms/js/spec/main.js
View file @
71cc602d
...
@@ -712,6 +712,7 @@
...
@@ -712,6 +712,7 @@
'js/spec/edxnotes/plugins/scroller_spec.js'
,
'js/spec/edxnotes/plugins/scroller_spec.js'
,
'js/spec/edxnotes/plugins/store_error_handler_spec.js'
,
'js/spec/edxnotes/plugins/store_error_handler_spec.js'
,
'js/spec/edxnotes/utils/logger_spec.js'
,
'js/spec/edxnotes/utils/logger_spec.js'
,
'js/spec/edxnotes/utils/notes_collector_spec.js'
,
'js/spec/edxnotes/views/note_item_spec.js'
,
'js/spec/edxnotes/views/note_item_spec.js'
,
'js/spec/edxnotes/views/notes_factory_spec.js'
,
'js/spec/edxnotes/views/notes_factory_spec.js'
,
'js/spec/edxnotes/views/notes_page_spec.js'
,
'js/spec/edxnotes/views/notes_page_spec.js'
,
...
...
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